<commit_before>import os
import sys
import time
import logging
import argparse
import numpy as np

import h5py

class dim:
    READ = 0
    PHS1 = 1
    PHS2 = 2
    COIL = 3
    MAPS = 4
    TIME = 10
    NDIM = 20

parser = argparse.ArgumentParser(description='Parallel Imaging and Compressed Sensing.')
parser.add_argument('-i', type=int, default=20, help='number of iterations')
parser.add_argument('--backend', type=str, default='numpy', choices=['mkl', 'numpy', 'cuda', 'customcpu', 'customgpu'])
parser.add_argument('--debug', type=int, default=logging.INFO, help='logging level')
parser.add_argument('--crop', help='crop data before recon: --crop "COIL:2,TIME:4')
parser.add_argument('-O', '--recipe', type=int, default=3, choices=range(5), help='optimization level')
parser.add_argument('data', nargs='?', default="scan.h5", help='kspace data in an HDF file')
args = parser.parse_args()

# set up logging
logging.basicConfig(level=args.debug)
log = logging.getLogger("pics")

# instantiate backend
import indigo.backends
B = indigo.backends.get_backend(args.backend)
log.info("using backend: %s", type(B).__name__)

# open input file
hdf = h5py.File(args.data, 'r+')
data = hdf['data']
maps = hdf['maps']
traj = hdf['traj']

# crop input data
crops = [1e6] * dim.NDIM
if args.crop:
    for d, size in eval("{%s}"%args.crop, {}, dim.__dict__).items():
        crops[-(d+1)] = size
        log.info("cropping dim %d to length %d", d, size)

# Read subsets of data to work on
ksp  = data[tuple(slice(0,min(n,c)) for n,c in zip(data.shape, crops))].T
mps  = maps[tuple(slice(0,min(n,c)) for n,c in zip(maps.shape, crops))].T
traj = traj[tuple(slice(0,min(n,c)) for n,c in zip(traj.shape, crops))].T

# determine dimensions
ksp_nc_dims = ksp.shape
ksp_c_dims  = mps.shape[:4] + ksp.shape[4:]
img_dims    = mps.shape[:3] + (1,) + ksp.shape[4:]

log.info('img %s %s', img_dims, ksp.dtype)
log.info('mps %s %s', mps.shape, mps.dtype)
log.info('ksp %s %s', ksp.shape, ksp.dtype)
log.info('trj %s %s', traj.shape, traj.dtype)

# normalize trajectory coords
traj[0] /= mps.shape[0]
traj[1] /= mps.shape[1]
traj[2] /= mps.shape[2]

for i in range(3):
    log.debug("traj[%d]: %f %f", i, np.amin(traj[i]), np.amax(traj[i]))

# construct operators
C = ksp.shape[dim.COIL]
T = ksp.shape[dim.TIME]
M = ksp.shape[dim.MAPS]
assert M == 1, "No support for multiple maps."
assert T == 1, "No support for multiple timepoints."

slc = [0] * dim.NDIM
slc[dim.READ] = slice(None)
slc[dim.PHS1] = slice(None)
slc[dim.PHS2] = slice(None)

osf = (640/480, 270/208, 432/308) # cpu
#osf = (600/480, 264/208, 432/308) # knl
#osf = (600/480, 270/208, 392/308) # gpu

F1= B.NUFFT(ksp_nc_dims[:3], ksp_c_dims[:3], traj[slc], oversamp=osf, dtype=ksp.dtype)
F = B.KronI(C, F1)
S = B.VStack([B.Diag(mps[:,:,:,c:c+1]) for c in range(C)], name='maps')
A = F * S; A._name = 'SENSE1'

from indigo.transforms import Transform, Visitor
from indigo.operators import Product, UnscaledFFT, SpMatrix, VStack, KronI
import scipy.sparse as spp

class MriGoodAdjoints(Transform):
    def visit_SpMatrix(self, node):
        if 'zpad' in node._name:
            return node.H.realize().H
        else:
            return node

class UseExwriteProperty(Transform):
    def visit_SpMatrix(self, node):
        node._allow_exwrite = True
        return node

class MriRealize(Transform):
    def visit_VStack(self, node):
        return node.realize()

    def visit_Product(self, node):
        l, r = node.children
        if isinstance(r, VStack) and isinstance(l, KronI):
            return node.realize()

        node = self.generic_visit(node)
        l, r = node.children
        if isinstance(r, SpMatrix) and isinstance(l, SpMatrix):
            return node.realize()
        else:
            return node

class DistKroniOverFFT(Transform):
    def visit_KronI(self, node):
        child = node.child
        if isinstance(child, Product) and node.has(UnscaledFFT):
            l, r = child.children
            kl = l._backend.KronI( node._c, l )
            kr = r._backend.KronI( node._c, r )
            return self.visit(kl * kr)
        else:
            return node

class AssocSpMatrices(Transform):
    def visit_Product(self, node):
        l = self.visit(node.left_child)
        r = self.visit(node.right_child)

        try:
            rl = r.left_child
            rr = r.right_child
            if isinstance(l, SpMatrix) and not isinstance(rl, UnscaledFFT):
                return (l*rl) * rr
        except (AttributeError, AssertionError):
            pass

        return l*r

class MakeRightLeaning(Transform):
    def visit_Product(self, node):
        l = self.visit(node.left_child)
        r = self.visit(node.right_child)
        if isinstance(l, Product):
            ll = l.left_child
            lr = l.right_child
            return self.visit(ll*(lr*r))
        else:
            return l*r

class MakeLeftLeaning(Transform):
    def visit_Product(self, node):
        l = self.visit(node.left_child)
        r = self.visit(node.right_child)
        if isinstance(r, Product):
            rl = r.left_child
            rr = r.right_child
            return self.visit((l*rl)*rr)
        else:
            return l*r

recipe = []
if args.recipe >= 1:
    recipe += [
        MakeRightLeaning,
        AssocSpMatrices,
        DistKroniOverFFT,
        MakeRightLeaning]
if args.recipe >= 2:
    recipe += [MriRealize]
if args.recipe >= 3:
    recipe += [MriGoodAdjoints]
if args.recipe >= 4:
    recipe += [UseExwriteProperty]

A = A.optimize(recipe)

AHA = A.H * A
AHA._name = 'SENSE'
log.info("tree:\n%s", AHA.dump())

node_mem = AHA.memusage()
alg_mem = 4 * AHA.shape[1] * ksp.dtype.itemsize
log.info('using %d MB of device memory' % ((node_mem+alg_mem)/1e6))

# prep data
AHy = A.H * ksp
AHy /= abs(AHy).max()
x = np.zeros((AHA.shape[1],1), dtype=ksp.dtype, order='F')

# do reconstruction
B.cg(AHA, AHy, x, maxiter=args.i)

# write out full image
img = x.reshape(img_dims, order='F')
if 'rec' in hdf: del hdf['rec']
hdf.create_dataset('rec', data=img.T)
hdf.close()

# write out preview
try:
    from scipy.misc import imsave
    slc = [slice(None)] * img.ndim
    slc[dim.PHS2] = img.shape[dim.PHS2] // 2
    for t in range(T):
        slc[dim.TIME] = t
        imsave("img_t%02d.jpg" % t, abs(img[slc].T.squeeze()))
except ImportError:
    log.warn("install PIL or Pillow to generate preview images.")

log.info("reconstruction complete")
<commit_msg>update pics fft shape<commit_after>import os
import sys
import time
import logging
import argparse
import numpy as np

import h5py

class dim:
    READ = 0
    PHS1 = 1
    PHS2 = 2
    COIL = 3
    MAPS = 4
    TIME = 10
    NDIM = 20

parser = argparse.ArgumentParser(description='Parallel Imaging and Compressed Sensing.')
parser.add_argument('-i', type=int, default=20, help='number of iterations')
parser.add_argument('--backend', type=str, default='numpy', choices=['mkl', 'numpy', 'cuda', 'customcpu', 'customgpu'])
parser.add_argument('--debug', type=int, default=logging.INFO, help='logging level')
parser.add_argument('--crop', help='crop data before recon: --crop "COIL:2,TIME:4')
parser.add_argument('-O', '--recipe', type=int, default=3, choices=range(5), help='optimization level')
parser.add_argument('data', nargs='?', default="scan.h5", help='kspace data in an HDF file')
args = parser.parse_args()

# set up logging
logging.basicConfig(level=args.debug)
log = logging.getLogger("pics")

# instantiate backend
import indigo.backends
B = indigo.backends.get_backend(args.backend)
log.info("using backend: %s", type(B).__name__)

# open input file
hdf = h5py.File(args.data, 'r+')
data = hdf['data']
maps = hdf['maps']
traj = hdf['traj']

# crop input data
crops = [1e6] * dim.NDIM
if args.crop:
    for d, size in eval("{%s}"%args.crop, {}, dim.__dict__).items():
        crops[-(d+1)] = size
        log.info("cropping dim %d to length %d", d, size)

# Read subsets of data to work on
ksp  = data[tuple(slice(0,min(n,c)) for n,c in zip(data.shape, crops))].T
mps  = maps[tuple(slice(0,min(n,c)) for n,c in zip(maps.shape, crops))].T
traj = traj[tuple(slice(0,min(n,c)) for n,c in zip(traj.shape, crops))].T

# determine dimensions
ksp_nc_dims = ksp.shape
ksp_c_dims  = mps.shape[:4] + ksp.shape[4:]
img_dims    = mps.shape[:3] + (1,) + ksp.shape[4:]

log.info('img %s %s', img_dims, ksp.dtype)
log.info('mps %s %s', mps.shape, mps.dtype)
log.info('ksp %s %s', ksp.shape, ksp.dtype)
log.info('trj %s %s', traj.shape, traj.dtype)

# normalize trajectory coords
traj[0] /= mps.shape[0]
traj[1] /= mps.shape[1]
traj[2] /= mps.shape[2]

for i in range(3):
    log.debug("traj[%d]: %f %f", i, np.amin(traj[i]), np.amax(traj[i]))

# construct operators
C = ksp.shape[dim.COIL]
T = ksp.shape[dim.TIME]
M = ksp.shape[dim.MAPS]
assert M == 1, "No support for multiple maps."
assert T == 1, "No support for multiple timepoints."

slc = [0] * dim.NDIM
slc[dim.READ] = slice(None)
slc[dim.PHS1] = slice(None)
slc[dim.PHS2] = slice(None)

#osf = (640/480, 270/208, 432/308) # cpu
#osf = (640/480, 288/208, 400/308) # knl
osf = (600/480, 270/208, 392/308) # gpu

F1= B.NUFFT(ksp_nc_dims[:3], ksp_c_dims[:3], traj[slc], oversamp=osf, dtype=ksp.dtype)
F = B.KronI(C, F1)
S = B.VStack([B.Diag(mps[:,:,:,c:c+1]) for c in range(C)], name='maps')
A = F * S; A._name = 'SENSE1'

from indigo.transforms import Transform, Visitor
from indigo.operators import Product, UnscaledFFT, SpMatrix, VStack, KronI
import scipy.sparse as spp

class MriGoodAdjoints(Transform):
    def visit_SpMatrix(self, node):
        if 'zpad' in node._name:
            return node.H.realize().H
        else:
            return node

class UseExwriteProperty(Transform):
    def visit_SpMatrix(self, node):
        node._allow_exwrite = True
        return node

class MriRealize(Transform):
    def visit_VStack(self, node):
        return node.realize()

    def visit_Product(self, node):
        l, r = node.children
        if isinstance(r, VStack) and isinstance(l, KronI):
            return node.realize()

        node = self.generic_visit(node)
        l, r = node.children
        if isinstance(r, SpMatrix) and isinstance(l, SpMatrix):
            return node.realize()
        else:
            return node

class DistKroniOverFFT(Transform):
    def visit_KronI(self, node):
        child = node.child
        if isinstance(child, Product) and node.has(UnscaledFFT):
            l, r = child.children
            kl = l._backend.KronI( node._c, l )
            kr = r._backend.KronI( node._c, r )
            return self.visit(kl * kr)
        else:
            return node

class AssocSpMatrices(Transform):
    def visit_Product(self, node):
        l = self.visit(node.left_child)
        r = self.visit(node.right_child)

        try:
            rl = r.left_child
            rr = r.right_child
            if isinstance(l, SpMatrix) and not isinstance(rl, UnscaledFFT):
                return (l*rl) * rr
        except (AttributeError, AssertionError):
            pass

        return l*r

class MakeRightLeaning(Transform):
    def visit_Product(self, node):
        l = self.visit(node.left_child)
        r = self.visit(node.right_child)
        if isinstance(l, Product):
            ll = l.left_child
            lr = l.right_child
            return self.visit(ll*(lr*r))
        else:
            return l*r

class MakeLeftLeaning(Transform):
    def visit_Product(self, node):
        l = self.visit(node.left_child)
        r = self.visit(node.right_child)
        if isinstance(r, Product):
            rl = r.left_child
            rr = r.right_child
            return self.visit((l*rl)*rr)
        else:
            return l*r

recipe = []
if args.recipe >= 1:
    recipe += [
        MakeRightLeaning,
        AssocSpMatrices,
        DistKroniOverFFT,
        MakeRightLeaning]
if args.recipe >= 2:
    recipe += [MriRealize]
if args.recipe >= 3:
    recipe += [MriGoodAdjoints]
if args.recipe >= 4:
    recipe += [UseExwriteProperty]

A = A.optimize(recipe)

AHA = A.H * A
AHA._name = 'SENSE'
log.info("tree:\n%s", AHA.dump())

node_mem = AHA.memusage()
alg_mem = 4 * AHA.shape[1] * ksp.dtype.itemsize
log.info('using %d MB of device memory' % ((node_mem+alg_mem)/1e6))

# prep data
AHy = A.H * ksp
AHy /= abs(AHy).max()
x = np.zeros((AHA.shape[1],1), dtype=ksp.dtype, order='F')

# do reconstruction
B.cg(AHA, AHy, x, maxiter=args.i)

# write out full image
img = x.reshape(img_dims, order='F')
if 'rec' in hdf: del hdf['rec']
hdf.create_dataset('rec', data=img.T)
hdf.close()

# write out preview
try:
    from scipy.misc import imsave
    slc = [slice(None)] * img.ndim
    slc[dim.PHS2] = img.shape[dim.PHS2] // 2
    for t in range(T):
        slc[dim.TIME] = t
        imsave("img_t%02d.jpg" % t, abs(img[slc].T.squeeze()))
except ImportError:
    log.warn("install PIL or Pillow to generate preview images.")

log.info("reconstruction complete")
<|endoftext|>


<commit_before>#!/usr/bin/python
#==========================================================================
#
#   Copyright Insight Software Consortium
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#          http://www.apache.org/licenses/LICENSE-2.0.txt
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
#
#
#==========================================================================*/
# This script is used to automate the modularization process. The following
# steps  are included:
# 1. Move the files in the monolithic ITK into modules of the modularized ITK.
#    A manifest text file that lists all the files and their destinations is
#    required to run the script.By default, the manifest file is named as
#    "Manifest.txt" in the  same directory of this script.
# 2. Create CMake Files and put them into modules.

# To run it, type ./modulizer.py  ITK_PATH  ModularITK_PATH   from
# the itk-modulizer root directory.

print "*************************************************************************"
print "WARNINGs! This modularization script is still in its experimental stage."
print "Current ITK users should not run this script."
print "*************************************************************************"

import re
import sys
import os
import shutil
import stat
import glob

if len(sys.argv) < 3:
    print("USAGE:  "+sys.argv[0]+" [monolithic ITK PATH] [modular ITK PATH]")
    sys.exit(-1)

HeadOfITKTree = sys.argv[1];
if (HeadOfITKTree[-1] == '/'):
    HeadOfITKTree = HeadOfITKTree[0:-1]

HeadOfModularITKTree = sys.argv[2];
if (HeadOfModularITKTree[-1] ==  '/'):
    HeadOfModularITKTree = HeadOfModularITKTree[0:-1]

# clean up the dirs first
if os.path.isdir(HeadOfModularITKTree):
   if  len(sys.argv) > 3:
      if (sys.argv[3] == 'y'):
         answer = 'y'
   else:
      print('Warning: The directory '+HeadOfModularITKTree+' exists! It needs to be wiped out first.')
      answer = raw_input("Do you really want to clean up this directory? [y/n]: " )

   if (answer == 'y'):
       os.system("rm -Rf "+ HeadOfModularITKTree)
       print('removed '+HeadOfModularITKTree)
       # get the supporting modules and cmake packaing files
       cmd ='git clone git://www.kitware.com/itk/modularITKSupport.git  '+HeadOfModularITKTree
       os.system(cmd)
       print("modularITKSupport repository cloned into " + HeadOfModularITKTree)
   if (answer =='n'):
       print("Please rerun the program with a different directory.")
       exit(-1)
   if (answer =='a'): #advanced
       print('Advanced Option Warning: This is only for developer\'s convinience.\nThe git clone step will be skipped; Old files in the directory will be overwritten.')
else:
   # get the supporting modules and cmake packaing files
   cmd ='git clone git://www.kitware.com/itk/modularITKSupport.git  '+HeadOfModularITKTree
   os.system(cmd)
   print("modularITKSupport repository cloned into " + HeadOfModularITKTree)

# copy the whole ITK tree over to a tempery dir, except the data
HeadOfTempTree = HeadOfModularITKTree+'/ITK_remaining'

def copy_directory(source, target):
    if not os.path.exists(target):
        os.mkdir(target)
    for root, dirs, files in os.walk(source):
        if '.git' in dirs:
            dirs.remove('.git')
        if 'Data' in dirs:
            dirs.remove('Data')
        for file in files:
            if os.path.splitext(file)[-1] in ('.git*'):
               continue
            from_ = os.path.join(root, file)
            to_ = from_.replace(source, target, 1)
            to_directory = os.path.split(to_)[0]
            if not os.path.exists(to_directory):
                os.makedirs(to_directory)
            shutil.copyfile(from_, to_)

print("Start to copy" + HeadOfITKTree + " to " + HeadOfTempTree + "   ...")
copy_directory(HeadOfITKTree, HeadOfTempTree)
print("Done copying!")

LogDir=HeadOfModularITKTree+'/logs'
if not os.path.isdir(LogDir):
  os.makedirs(LogDir)

# read the manifest file
print ("moving files from "+HeadOfTempTree+" into modules in "+HeadOfModularITKTree)
numOfMissingFiles = 0;
missingf =  open(LogDir+'/missingFiles.log','w')
moduleList=[];
for line in open("./Manifest.txt",'r'):
   # parse the string
 if line[0] != '#':
    words = line.split()
    if len(words) != 4:
        print "Missing entries at: "+line
        exit(-1)

    itkFileName = words[0]
    groupName = words[1]
    moduleName = words[2]
    subdirName = words[3]

    inputfile = HeadOfTempTree+'/'+words[0]
    outputPath = HeadOfModularITKTree+'/modules/'+ moduleName+'/'+subdirName
    if len(moduleList) == 0:
       moduleList.append(moduleName)
    elif moduleName != moduleList[-1]:
       moduleList.append(moduleName)

    # creat the path
    if not os.path.isdir(outputPath):
       os.makedirs(outputPath)

    # copying files to the destination
    if  os.path.isfile(inputfile):
       os.system('mv ' +inputfile+'  '+ outputPath)
    else:
       missingFileName = inputfile.split(HeadOfTempTree+'/')[1]
       missingf.write(missingFileName + '\n')
       numOfMissingFiles = numOfMissingFiles + 1

missingf.close()

# find the unique module names
def unique(seq):
    # not order preserving
    set = {}
    map(set.__setitem__, seq, [])
    return set.keys()

moduleList = unique(moduleList)

# list the new files
newf =  open(LogDir+'/newFiles.log','w')
for (root, subDirs, files) in os.walk(HeadOfTempTree):
   for afile in files:
     newFilePath = os.path.join(root, afile)
     newFileName = newFilePath.split(HeadOfTempTree+'/')[1]
     newf.write(newFileName+'\n')
newf.close()
print ("listed new files to"+LogDir+"/newFiles.log")

###########################################################################
def ModularITKAddTest(executableSearch, moduleName):
    addTestLines="";
    for line in  open("./AddTestsWithArguments.txt",'r'):
      if(line[0] != '#'):
        argns=""
        words = line[0:-1].split(";")
        if (len(words) < 3):
            # No test driver , no arguments
            testName = words[0]
            # parse the executableName from the path
            executableName = words[1].split("/")[-1]
        else:
            testName = words[0]
            testDriver = words[1]
            if (words[2] == "--compare"):
               #ignore now, TO DO
               executableName = "--";
            else:
               executableName = words[2]
               argns =' '.join(words[3:])
            if (executableName != executableSearch):
                # try again , assuming no test driver
               executableName = words[1].split("/")[-1]
               argns =' '.join(words[2:])

        if (executableName == executableSearch):
            addTestLines = addTestLines + "add_test(NAME "+ testName+ "\n      COMMAND "+moduleName+'-tests  ' + executableName
            if (argns !=""):
               addTestLines = addTestLines + "\n              "+argns
            addTestLines = addTestLines +")\n"
    return  addTestLines

print ('creating cmake files for each module (from the template module)')
#moduleList = os.listdir(HeadOfModularITKTree)
for  moduleName in moduleList:
  if os.path.isdir(HeadOfModularITKTree+'/modules/'+moduleName):
     # cooy the LICENSE and NOTICE
     os.system('cp ./templateModule/itk-template-module/LICENSE'+'  '+ HeadOfModularITKTree+'/modules/'+moduleName)
     os.system('cp ./templateModule/itk-template-module/NOTICE'+'  '+ HeadOfModularITKTree+'/modules/'+moduleName)

     # write CMakeLists.txt
     filepath = HeadOfModularITKTree+'/modules/'+moduleName+'/CMakeLists.txt'
     if not os.path.isfile(filepath):
       o = open(filepath,'w')
       for line in open('./templateModule/itk-template-module/CMakeLists.txt','r'):
           line = line.replace('itk-template-module',moduleName)
           o.write(line);
       o.close()

     # write src/CMakeLists.txt
     # list of CXX files
     if os.path.isdir(HeadOfModularITKTree+'/modules/'+moduleName+'/src'):
       cxxFiles = glob.glob(HeadOfModularITKTree+'/modules/'+moduleName+'/src/*.cxx')
       cxxFileList='';
       for cxxf in cxxFiles:
            cxxFileList = cxxFileList+cxxf.split('/')[-1]+'\n'
       filepath = HeadOfModularITKTree+'/modules/'+moduleName+'/src/CMakeLists.txt'
       if not os.path.isfile(filepath):
         o = open(filepath,'w')
         for line in open('./templateModule/itk-template-module/src/CMakeLists.txt','r'):
            line = line.replace('itk-template-module',moduleName)
            line = line.replace('LIST_OF_CXX_FILES',cxxFileList[0:-1]) #get rid of the last \n
            o.write(line);
         o.close()

     # write  test/CMakeLists.txt
     if os.path.isdir(HeadOfModularITKTree+'/modules/'+moduleName+'/test'):
       cxxFiles = glob.glob(HeadOfModularITKTree+'/modules/'+moduleName+'/test/*.cxx')
       cxxFileList='';
       for cxxf in cxxFiles:
            cxxFileList = cxxFileList+cxxf.split('/')[-1]+'\n'
       filepath = HeadOfModularITKTree+'/modules/'+moduleName+'/test/CMakeLists.txt'

       if not os.path.isfile(filepath):
         o = open(filepath,'w')
         line = 'create_test_sourcelist(Tests '+moduleName+'-tests.cxx\n'+cxxFileList+')\n\n'
         o.write(line)

         #line = 'set (TestsTorun ${Tests})\nremove(TestsToRun '+moduleName+'-tests.cxx)\n\n'
         #o.write(line)

         line = 'add_executable('+moduleName+'-tests  ${Tests} )\n'
         o.write(line)

         line = 'target_link_libraries('+moduleName+'-tests  ${'+moduleName+'_LIBRARIES} )\n\n'
         o.write(line)

         #line = 'set('+ moduleName+'_TESTS'+ '  ${ITK_EXECUTABLE_PATH}/'+moduleName+'-tests)\n'
         #o.write(line)
         for cxxf in cxxFiles:
            cxxFileName = cxxf.split('/')[-1]
            executableName = cxxFileName[0:-4];
            line = ModularITKAddTest(executableName, moduleName)
            #line = 'add_test(NAME '+ + '\n      COMMAND '+moduleName+'-tests  ' + executbaleName +')\n\n'
            o.write(line)
         o.close()

    # write CTestConfig.cmake
     filepath = HeadOfModularITKTree+'/modules/'+moduleName+'/CTestConfig.cmake'
     if not os.path.isfile(filepath):
        o = open(filepath,'w')
        for line in open('./templateModule/itk-template-module/CTestConfig.cmake','r'):
            line = line.replace('itk-template-module',moduleName)
            o.write(line);
        o.close()

   # write itk-module.cmake, which contains dependency info
     filepath = HeadOfModularITKTree+'/modules/'+moduleName+'/itk-module.cmake'
     if not os.path.isfile(filepath):
        o = open(filepath,'w')
        for line in open('./templateModule/itk-template-module/itk-module.cmake','r'):
            line = line.replace('itk-template-module',moduleName)
            o.write(line);
        o.close()
<commit_msg>ENH: Update modularITKSupport repo's url.<commit_after>#!/usr/bin/python
#==========================================================================
#
#   Copyright Insight Software Consortium
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#          http://www.apache.org/licenses/LICENSE-2.0.txt
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
#
#
#==========================================================================*/
# This script is used to automate the modularization process. The following
# steps  are included:
# 1. Move the files in the monolithic ITK into modules of the modularized ITK.
#    A manifest text file that lists all the files and their destinations is
#    required to run the script.By default, the manifest file is named as
#    "Manifest.txt" in the  same directory of this script.
# 2. Create CMake Files and put them into modules.

# To run it, type ./modulizer.py  ITK_PATH  ModularITK_PATH   from
# the itk-modulizer root directory.

print "*************************************************************************"
print "WARNINGs! This modularization script is still in its experimental stage."
print "Current ITK users should not run this script."
print "*************************************************************************"

import re
import sys
import os
import shutil
import stat
import glob

if len(sys.argv) < 3:
    print("USAGE:  "+sys.argv[0]+" [monolithic ITK PATH] [modular ITK PATH]")
    sys.exit(-1)

HeadOfITKTree = sys.argv[1];
if (HeadOfITKTree[-1] == '/'):
    HeadOfITKTree = HeadOfITKTree[0:-1]

HeadOfModularITKTree = sys.argv[2];
if (HeadOfModularITKTree[-1] ==  '/'):
    HeadOfModularITKTree = HeadOfModularITKTree[0:-1]

# clean up the dirs first
if os.path.isdir(HeadOfModularITKTree):
   if  len(sys.argv) > 3:
      if (sys.argv[3] == 'y'):
         answer = 'y'
   else:
      print('Warning: The directory '+HeadOfModularITKTree+' exists! It needs to be wiped out first.')
      answer = raw_input("Do you really want to clean up this directory? [y/n]: " )

   if (answer == 'y'):
       os.system("rm -Rf "+ HeadOfModularITKTree)
       print('removed '+HeadOfModularITKTree)
       # get the supporting modules and cmake packaing files
       cmd ='git clone http://itk.org/tmp/modularITKSupport.git '+HeadOfModularITKTree
       os.system(cmd)
       print("modularITKSupport repository cloned into " + HeadOfModularITKTree)
   if (answer =='n'):
       print("Please rerun the program with a different directory.")
       exit(-1)
   if (answer =='a'): #advanced
       print('Advanced Option Warning: This is only for developer\'s convinience.\nThe git clone step will be skipped; Old files in the directory will be overwritten.')
else:
   # get the supporting modules and cmake packaing files
   cmd ='git clone git://www.kitware.com/itk/modularITKSupport.git  '+HeadOfModularITKTree
   os.system(cmd)
   print("modularITKSupport repository cloned into " + HeadOfModularITKTree)

# copy the whole ITK tree over to a tempery dir, except the data
HeadOfTempTree = HeadOfModularITKTree+'/ITK_remaining'

def copy_directory(source, target):
    if not os.path.exists(target):
        os.mkdir(target)
    for root, dirs, files in os.walk(source):
        if '.git' in dirs:
            dirs.remove('.git')
        if 'Data' in dirs:
            dirs.remove('Data')
        for file in files:
            if os.path.splitext(file)[-1] in ('.git*'):
               continue
            from_ = os.path.join(root, file)
            to_ = from_.replace(source, target, 1)
            to_directory = os.path.split(to_)[0]
            if not os.path.exists(to_directory):
                os.makedirs(to_directory)
            shutil.copyfile(from_, to_)

print("Start to copy" + HeadOfITKTree + " to " + HeadOfTempTree + "   ...")
copy_directory(HeadOfITKTree, HeadOfTempTree)
print("Done copying!")

LogDir=HeadOfModularITKTree+'/logs'
if not os.path.isdir(LogDir):
  os.makedirs(LogDir)

# read the manifest file
print ("moving files from "+HeadOfTempTree+" into modules in "+HeadOfModularITKTree)
numOfMissingFiles = 0;
missingf =  open(LogDir+'/missingFiles.log','w')
moduleList=[];
for line in open("./Manifest.txt",'r'):
   # parse the string
 if line[0] != '#':
    words = line.split()
    if len(words) != 4:
        print "Missing entries at: "+line
        exit(-1)

    itkFileName = words[0]
    groupName = words[1]
    moduleName = words[2]
    subdirName = words[3]

    inputfile = HeadOfTempTree+'/'+words[0]
    outputPath = HeadOfModularITKTree+'/modules/'+ moduleName+'/'+subdirName
    if len(moduleList) == 0:
       moduleList.append(moduleName)
    elif moduleName != moduleList[-1]:
       moduleList.append(moduleName)

    # creat the path
    if not os.path.isdir(outputPath):
       os.makedirs(outputPath)

    # copying files to the destination
    if  os.path.isfile(inputfile):
       os.system('mv ' +inputfile+'  '+ outputPath)
    else:
       missingFileName = inputfile.split(HeadOfTempTree+'/')[1]
       missingf.write(missingFileName + '\n')
       numOfMissingFiles = numOfMissingFiles + 1

missingf.close()

# find the unique module names
def unique(seq):
    # not order preserving
    set = {}
    map(set.__setitem__, seq, [])
    return set.keys()

moduleList = unique(moduleList)

# list the new files
newf =  open(LogDir+'/newFiles.log','w')
for (root, subDirs, files) in os.walk(HeadOfTempTree):
   for afile in files:
     newFilePath = os.path.join(root, afile)
     newFileName = newFilePath.split(HeadOfTempTree+'/')[1]
     newf.write(newFileName+'\n')
newf.close()
print ("listed new files to"+LogDir+"/newFiles.log")

###########################################################################
def ModularITKAddTest(executableSearch, moduleName):
    addTestLines="";
    for line in  open("./AddTestsWithArguments.txt",'r'):
      if(line[0] != '#'):
        argns=""
        words = line[0:-1].split(";")
        if (len(words) < 3):
            # No test driver , no arguments
            testName = words[0]
            # parse the executableName from the path
            executableName = words[1].split("/")[-1]
        else:
            testName = words[0]
            testDriver = words[1]
            if (words[2] == "--compare"):
               #ignore now, TO DO
               executableName = "--";
            else:
               executableName = words[2]
               argns =' '.join(words[3:])
            if (executableName != executableSearch):
                # try again , assuming no test driver
               executableName = words[1].split("/")[-1]
               argns =' '.join(words[2:])

        if (executableName == executableSearch):
            addTestLines = addTestLines + "add_test(NAME "+ testName+ "\n      COMMAND "+moduleName+'-tests  ' + executableName
            if (argns !=""):
               addTestLines = addTestLines + "\n              "+argns
            addTestLines = addTestLines +")\n"
    return  addTestLines

print ('creating cmake files for each module (from the template module)')
#moduleList = os.listdir(HeadOfModularITKTree)
for  moduleName in moduleList:
  if os.path.isdir(HeadOfModularITKTree+'/modules/'+moduleName):
     # cooy the LICENSE and NOTICE
     os.system('cp ./templateModule/itk-template-module/LICENSE'+'  '+ HeadOfModularITKTree+'/modules/'+moduleName)
     os.system('cp ./templateModule/itk-template-module/NOTICE'+'  '+ HeadOfModularITKTree+'/modules/'+moduleName)

     # write CMakeLists.txt
     filepath = HeadOfModularITKTree+'/modules/'+moduleName+'/CMakeLists.txt'
     if not os.path.isfile(filepath):
       o = open(filepath,'w')
       for line in open('./templateModule/itk-template-module/CMakeLists.txt','r'):
           line = line.replace('itk-template-module',moduleName)
           o.write(line);
       o.close()

     # write src/CMakeLists.txt
     # list of CXX files
     if os.path.isdir(HeadOfModularITKTree+'/modules/'+moduleName+'/src'):
       cxxFiles = glob.glob(HeadOfModularITKTree+'/modules/'+moduleName+'/src/*.cxx')
       cxxFileList='';
       for cxxf in cxxFiles:
            cxxFileList = cxxFileList+cxxf.split('/')[-1]+'\n'
       filepath = HeadOfModularITKTree+'/modules/'+moduleName+'/src/CMakeLists.txt'
       if not os.path.isfile(filepath):
         o = open(filepath,'w')
         for line in open('./templateModule/itk-template-module/src/CMakeLists.txt','r'):
            line = line.replace('itk-template-module',moduleName)
            line = line.replace('LIST_OF_CXX_FILES',cxxFileList[0:-1]) #get rid of the last \n
            o.write(line);
         o.close()

     # write  test/CMakeLists.txt
     if os.path.isdir(HeadOfModularITKTree+'/modules/'+moduleName+'/test'):
       cxxFiles = glob.glob(HeadOfModularITKTree+'/modules/'+moduleName+'/test/*.cxx')
       cxxFileList='';
       for cxxf in cxxFiles:
            cxxFileList = cxxFileList+cxxf.split('/')[-1]+'\n'
       filepath = HeadOfModularITKTree+'/modules/'+moduleName+'/test/CMakeLists.txt'

       if not os.path.isfile(filepath):
         o = open(filepath,'w')
         line = 'create_test_sourcelist(Tests '+moduleName+'-tests.cxx\n'+cxxFileList+')\n\n'
         o.write(line)

         #line = 'set (TestsTorun ${Tests})\nremove(TestsToRun '+moduleName+'-tests.cxx)\n\n'
         #o.write(line)

         line = 'add_executable('+moduleName+'-tests  ${Tests} )\n'
         o.write(line)

         line = 'target_link_libraries('+moduleName+'-tests  ${'+moduleName+'_LIBRARIES} )\n\n'
         o.write(line)

         #line = 'set('+ moduleName+'_TESTS'+ '  ${ITK_EXECUTABLE_PATH}/'+moduleName+'-tests)\n'
         #o.write(line)
         for cxxf in cxxFiles:
            cxxFileName = cxxf.split('/')[-1]
            executableName = cxxFileName[0:-4];
            line = ModularITKAddTest(executableName, moduleName)
            #line = 'add_test(NAME '+ + '\n      COMMAND '+moduleName+'-tests  ' + executbaleName +')\n\n'
            o.write(line)
         o.close()

    # write CTestConfig.cmake
     filepath = HeadOfModularITKTree+'/modules/'+moduleName+'/CTestConfig.cmake'
     if not os.path.isfile(filepath):
        o = open(filepath,'w')
        for line in open('./templateModule/itk-template-module/CTestConfig.cmake','r'):
            line = line.replace('itk-template-module',moduleName)
            o.write(line);
        o.close()

   # write itk-module.cmake, which contains dependency info
     filepath = HeadOfModularITKTree+'/modules/'+moduleName+'/itk-module.cmake'
     if not os.path.isfile(filepath):
        o = open(filepath,'w')
        for line in open('./templateModule/itk-template-module/itk-module.cmake','r'):
            line = line.replace('itk-template-module',moduleName)
            o.write(line);
        o.close()
<|endoftext|>


<commit_before>from django.http import JsonResponse
from django.apps import apps
from django.db.models import Q

def get_unreview_list(request, unreview_kind, *args, **kwargs):
    """Get Unreview List.
    ログインしているユーザーの未レビューの最新５件を返す。
    """
    back_num = 5
    user = request.user # Login User

    res_obj = {'unreviewd_list': []}

    if user.is_anonymous():
        return JsonResponse(res_obj)

    # href="{% url 'user:unreviewed' %}"

    # href="{% url 'user:post_review' %}?event_id={{event_id}}"
    if user.roll == 'helper':
        unreview_list = user.get_past_participated_and_unreviewed_events() # event
        for event in unreview_list[:back_num]:

            res_obj['unreviewd_list'].append({
                'event_id': event.id,
                'event_name': event.name,
                'event_host': event.host_user,
                'event_img': event.get_image_url(),
                'message' : event.name + 'へのレビューをおねがいします。'
            })

    # href="{% url 'user:post_review' %}?event_id={{event_id}}&to_user_id={{helper_id}}"
    else:
        counter = 0
        unreview_list = user.get_zipped_unreviewed_hosted() # zip(event, user_list)
        for event, user_list in unreview_list:
            if counter >= back_num:
                break

            for h_user in user_list:
                if counter >= back_num:
                    break
                res_obj['unreviewd_list'].append({
                    'event_id': event.id,
                    'event_name': event.name,
                    'event_host': event.host_user,
                    'event_img': event.get_image_url(),
                    'helper_name': h_user.username,
                    'helper_id': h_user.pk,
                    'helper_img': h_user.get_image_url(),
                    'message' : h_user.username + 'さんへのレビューをおねがいします。'
                })
                counter += 1

    return JsonResponse(res_obj)
<commit_msg>[COSME] F401 'django.apps.apps' imported but unused<commit_after>from django.http import JsonResponse
from django.db.models import Q

def get_unreview_list(request, unreview_kind, *args, **kwargs):
    """Get Unreview List.
    ログインしているユーザーの未レビューの最新５件を返す。
    """
    back_num = 5
    user = request.user # Login User

    res_obj = {'unreviewd_list': []}

    if user.is_anonymous():
        return JsonResponse(res_obj)

    # href="{% url 'user:unreviewed' %}"

    # href="{% url 'user:post_review' %}?event_id={{event_id}}"
    if user.roll == 'helper':
        unreview_list = user.get_past_participated_and_unreviewed_events() # event
        for event in unreview_list[:back_num]:

            res_obj['unreviewd_list'].append({
                'event_id': event.id,
                'event_name': event.name,
                'event_host': event.host_user,
                'event_img': event.get_image_url(),
                'message' : event.name + 'へのレビューをおねがいします。'
            })

    # href="{% url 'user:post_review' %}?event_id={{event_id}}&to_user_id={{helper_id}}"
    else:
        counter = 0
        unreview_list = user.get_zipped_unreviewed_hosted() # zip(event, user_list)
        for event, user_list in unreview_list:
            if counter >= back_num:
                break

            for h_user in user_list:
                if counter >= back_num:
                    break
                res_obj['unreviewd_list'].append({
                    'event_id': event.id,
                    'event_name': event.name,
                    'event_host': event.host_user,
                    'event_img': event.get_image_url(),
                    'helper_name': h_user.username,
                    'helper_id': h_user.pk,
                    'helper_img': h_user.get_image_url(),
                    'message' : h_user.username + 'さんへのレビューをおねがいします。'
                })
                counter += 1

    return JsonResponse(res_obj)
<|endoftext|>


<commit_before>import struct
import hashlib
from binascii import hexlify, unhexlify
from typing import List, Optional

import ecdsa
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.serialization import load_der_public_key
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric.utils import Prehashed
from ecdsa.util import sigencode_der

from torba.client.basetransaction import BaseTransaction, BaseInput, BaseOutput, ReadOnlyList
from torba.client.hash import hash160, sha256, Base58
from lbrynet.schema.claim import Claim
from lbrynet.wallet.account import Account
from lbrynet.wallet.script import InputScript, OutputScript

class Input(BaseInput):
    script: InputScript
    script_class = InputScript

class Output(BaseOutput):
    script: OutputScript
    script_class = OutputScript

    __slots__ = 'channel', 'private_key'

    def __init__(self, *args, channel: Optional['Output'] = None,
                 private_key: Optional[str] = None, **kwargs) -> None:
        super().__init__(*args, **kwargs)
        self.channel = channel
        self.private_key = private_key

    def update_annotations(self, annotated):
        super().update_annotations(annotated)
        self.channel = annotated.channel if annotated else None
        self.private_key = annotated.private_key if annotated else None

    def get_fee(self, ledger):
        name_fee = 0
        if self.script.is_claim_name:
            name_fee = len(self.script.values['claim_name']) * ledger.fee_per_name_char
        return max(name_fee, super().get_fee(ledger))

    @property
    def is_claim(self) -> bool:
        return self.script.is_claim_name or self.script.is_update_claim

    @property
    def claim_hash(self) -> bytes:
        if self.script.is_claim_name:
            return hash160(self.tx_ref.hash + struct.pack('>I', self.position))
        elif self.script.is_update_claim or self.script.is_support_claim:
            return self.script.values['claim_id']
        else:
            raise ValueError('No claim_id associated.')

    @property
    def claim_id(self) -> str:
        return hexlify(self.claim_hash[::-1]).decode()

    @property
    def claim_name(self) -> str:
        if self.script.is_claim_involved:
            return self.script.values['claim_name'].decode()
        raise ValueError('No claim_name associated.')

    @property
    def claim(self) -> Claim:
        if self.is_claim:
            if not isinstance(self.script.values['claim'], Claim):
                self.script.values['claim'] = Claim.from_bytes(self.script.values['claim'])
            return self.script.values['claim']
        raise ValueError('Only claim name and claim update have the claim payload.')

    @property
    def permanent_url(self) -> str:
        if self.script.is_claim_involved:
            return f"{self.claim_name}#{self.claim_id}"
        raise ValueError('No claim associated.')

    @property
    def has_private_key(self):
        return self.private_key is not None

    def is_signed_by(self, channel: 'Output', ledger=None):
        if self.claim.unsigned_payload:
            pieces = [
                Base58.decode(self.get_address(ledger)),
                self.claim.unsigned_payload,
                self.claim.signing_channel_hash[::-1]
            ]
        else:
            pieces = [
                self.tx_ref.tx.inputs[0].txo_ref.hash,
                self.claim.signing_channel_hash,
                self.claim.to_message_bytes()
            ]
        digest = sha256(b''.join(pieces))
        public_key = load_der_public_key(channel.claim.channel.public_key_bytes, default_backend())
        hash = hashes.SHA256()
        signature = hexlify(self.claim.signature)
        r = int(signature[:int(len(signature)/2)], 16)
        s = int(signature[int(len(signature)/2):], 16)
        encoded_sig = sigencode_der(r, s, len(signature)*4)
        public_key.verify(encoded_sig, digest, ec.ECDSA(Prehashed(hash)))
        return True

    def sign(self, channel: 'Output', first_input_id=None):
        self.channel = channel
        self.claim.signing_channel_hash = channel.claim_hash
        digest = sha256(b''.join([
            first_input_id or self.tx_ref.tx.inputs[0].txo_ref.id.encode(),
            self.claim.signing_channel_hash,
            self.claim.to_message_bytes()
        ]))
        private_key = ecdsa.SigningKey.from_pem(channel.private_key, hashfunc=hashlib.sha256)
        self.claim.signature = private_key.sign_digest_deterministic(digest, hashfunc=hashlib.sha256)
        self.script.generate()

    def generate_channel_private_key(self):
        private_key = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1, hashfunc=hashlib.sha256)
        self.private_key = private_key.to_pem().decode()
        self.claim.channel.public_key_bytes = private_key.get_verifying_key().to_der()
        self.script.generate()
        return self.private_key

    def is_channel_private_key(self, private_key_pem):
        private_key = ecdsa.SigningKey.from_pem(private_key_pem, hashfunc=hashlib.sha256)
        return self.claim.channel.public_key_bytes == private_key.get_verifying_key().to_der()

    @classmethod
    def pay_claim_name_pubkey_hash(
            cls, amount: int, claim_name: str, claim: Claim, pubkey_hash: bytes) -> 'Output':
        script = cls.script_class.pay_claim_name_pubkey_hash(
            claim_name.encode(), claim, pubkey_hash)
        txo = cls(amount, script)
        return txo

    @classmethod
    def pay_update_claim_pubkey_hash(
            cls, amount: int, claim_name: str, claim_id: str, claim: Claim, pubkey_hash: bytes) -> 'Output':
        script = cls.script_class.pay_update_claim_pubkey_hash(
            claim_name.encode(), unhexlify(claim_id)[::-1], claim, pubkey_hash)
        txo = cls(amount, script)
        return txo

    @classmethod
    def pay_support_pubkey_hash(cls, amount: int, claim_name: str, claim_id: str, pubkey_hash: bytes) -> 'Output':
        script = cls.script_class.pay_support_pubkey_hash(claim_name.encode(), unhexlify(claim_id)[::-1], pubkey_hash)
        return cls(amount, script)

    @classmethod
    def purchase_claim_pubkey_hash(cls, amount: int, claim_id: str, pubkey_hash: bytes) -> 'Output':
        script = cls.script_class.purchase_claim_pubkey_hash(unhexlify(claim_id)[::-1], pubkey_hash)
        return cls(amount, script)

class Transaction(BaseTransaction):

    input_class = Input
    output_class = Output

    outputs: ReadOnlyList[Output]
    inputs: ReadOnlyList[Input]

    @classmethod
    def pay(cls, amount: int, address: bytes, funding_accounts: List[Account], change_account: Account):
        ledger = cls.ensure_all_have_same_ledger(funding_accounts, change_account)
        output = Output.pay_pubkey_hash(amount, ledger.address_to_hash160(address))
        return cls.create([], [output], funding_accounts, change_account)

    @classmethod
    def claim_create(
            cls, name: str, claim: Claim, amount: int, holding_address: str,
            funding_accounts: List[Account], change_account: Account, signing_channel: Output = None):
        ledger = cls.ensure_all_have_same_ledger(funding_accounts, change_account)
        claim_output = Output.pay_claim_name_pubkey_hash(
            amount, name, claim, ledger.address_to_hash160(holding_address)
        )
        if signing_channel is not None:
            claim_output.sign(signing_channel, b'placeholder txid:nout')
        return cls.create([], [claim_output], funding_accounts, change_account, sign=False)

    @classmethod
    def claim_update(
            cls, previous_claim: Output, amount: int, holding_address: str,
            funding_accounts: List[Account], change_account: Account, signing_channel: Output = None):
        ledger = cls.ensure_all_have_same_ledger(funding_accounts, change_account)
        updated_claim = Output.pay_update_claim_pubkey_hash(
            amount, previous_claim.claim_name, previous_claim.claim_id,
            previous_claim.claim, ledger.address_to_hash160(holding_address)
        )
        if signing_channel is not None:
            updated_claim.sign(signing_channel, b'placeholder txid:nout')
        return cls.create(
            [Input.spend(previous_claim)], [updated_claim], funding_accounts, change_account, sign=False
        )

    @classmethod
    def support(cls, claim_name: str, claim_id: str, amount: int, holding_address: str,
                funding_accounts: List[Account], change_account: Account):
        ledger = cls.ensure_all_have_same_ledger(funding_accounts, change_account)
        support_output = Output.pay_support_pubkey_hash(
            amount, claim_name, claim_id, ledger.address_to_hash160(holding_address)
        )
        return cls.create([], [support_output], funding_accounts, change_account)

    @classmethod
    def purchase(cls, claim: Output, amount: int, merchant_address: bytes,
                 funding_accounts: List[Account], change_account: Account):
        ledger = cls.ensure_all_have_same_ledger(funding_accounts, change_account)
        claim_output = Output.purchase_claim_pubkey_hash(
            amount, claim.claim_id, ledger.address_to_hash160(merchant_address)
        )
        return cls.create([], [claim_output], funding_accounts, change_account)

    @property
    def my_inputs(self):
        for txi in self.inputs:
            if txi.txo_ref.txo is not None and txi.txo_ref.txo.is_my_account:
                yield txi

    def _filter_my_outputs(self, f):
        for txo in self.outputs:
            if txo.is_my_account and f(txo.script):
                yield txo

    def _filter_other_outputs(self, f):
        for txo in self.outputs:
            if not txo.is_my_account and f(txo.script):
                yield txo

    @property
    def my_claim_outputs(self):
        return self._filter_my_outputs(lambda s: s.is_claim_name)

    @property
    def my_update_outputs(self):
        return self._filter_my_outputs(lambda s: s.is_update_claim)

    @property
    def my_support_outputs(self):
        return self._filter_my_outputs(lambda s: s.is_support_claim)

    @property
    def other_support_outputs(self):
        return self._filter_other_outputs(lambda s: s.is_support_claim)

    @property
    def my_abandon_outputs(self):
        for txi in self.inputs:
            abandon = txi.txo_ref.txo
            if abandon is not None and abandon.is_my_account and abandon.script.is_claim_involved:
                is_update = False
                if abandon.script.is_claim_name or abandon.script.is_update_claim:
                    for update in self.my_update_outputs:
                        if abandon.claim_id == update.claim_id:
                            is_update = True
                            break
                if not is_update:
                    yield abandon
<commit_msg>use TXORef.hash instead of TXORef.id when signing claim with channel<commit_after>import struct
import hashlib
from binascii import hexlify, unhexlify
from typing import List, Optional

import ecdsa
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.serialization import load_der_public_key
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric.utils import Prehashed
from ecdsa.util import sigencode_der

from torba.client.basetransaction import BaseTransaction, BaseInput, BaseOutput, ReadOnlyList
from torba.client.hash import hash160, sha256, Base58
from lbrynet.schema.claim import Claim
from lbrynet.wallet.account import Account
from lbrynet.wallet.script import InputScript, OutputScript

class Input(BaseInput):
    script: InputScript
    script_class = InputScript

class Output(BaseOutput):
    script: OutputScript
    script_class = OutputScript

    __slots__ = 'channel', 'private_key'

    def __init__(self, *args, channel: Optional['Output'] = None,
                 private_key: Optional[str] = None, **kwargs) -> None:
        super().__init__(*args, **kwargs)
        self.channel = channel
        self.private_key = private_key

    def update_annotations(self, annotated):
        super().update_annotations(annotated)
        self.channel = annotated.channel if annotated else None
        self.private_key = annotated.private_key if annotated else None

    def get_fee(self, ledger):
        name_fee = 0
        if self.script.is_claim_name:
            name_fee = len(self.script.values['claim_name']) * ledger.fee_per_name_char
        return max(name_fee, super().get_fee(ledger))

    @property
    def is_claim(self) -> bool:
        return self.script.is_claim_name or self.script.is_update_claim

    @property
    def claim_hash(self) -> bytes:
        if self.script.is_claim_name:
            return hash160(self.tx_ref.hash + struct.pack('>I', self.position))
        elif self.script.is_update_claim or self.script.is_support_claim:
            return self.script.values['claim_id']
        else:
            raise ValueError('No claim_id associated.')

    @property
    def claim_id(self) -> str:
        return hexlify(self.claim_hash[::-1]).decode()

    @property
    def claim_name(self) -> str:
        if self.script.is_claim_involved:
            return self.script.values['claim_name'].decode()
        raise ValueError('No claim_name associated.')

    @property
    def claim(self) -> Claim:
        if self.is_claim:
            if not isinstance(self.script.values['claim'], Claim):
                self.script.values['claim'] = Claim.from_bytes(self.script.values['claim'])
            return self.script.values['claim']
        raise ValueError('Only claim name and claim update have the claim payload.')

    @property
    def permanent_url(self) -> str:
        if self.script.is_claim_involved:
            return f"{self.claim_name}#{self.claim_id}"
        raise ValueError('No claim associated.')

    @property
    def has_private_key(self):
        return self.private_key is not None

    def is_signed_by(self, channel: 'Output', ledger=None):
        if self.claim.unsigned_payload:
            pieces = [
                Base58.decode(self.get_address(ledger)),
                self.claim.unsigned_payload,
                self.claim.signing_channel_hash[::-1]
            ]
        else:
            pieces = [
                self.tx_ref.tx.inputs[0].txo_ref.hash,
                self.claim.signing_channel_hash,
                self.claim.to_message_bytes()
            ]
        digest = sha256(b''.join(pieces))
        public_key = load_der_public_key(channel.claim.channel.public_key_bytes, default_backend())
        hash = hashes.SHA256()
        signature = hexlify(self.claim.signature)
        r = int(signature[:int(len(signature)/2)], 16)
        s = int(signature[int(len(signature)/2):], 16)
        encoded_sig = sigencode_der(r, s, len(signature)*4)
        public_key.verify(encoded_sig, digest, ec.ECDSA(Prehashed(hash)))
        return True

    def sign(self, channel: 'Output', first_input_id=None):
        self.channel = channel
        self.claim.signing_channel_hash = channel.claim_hash
        digest = sha256(b''.join([
            first_input_id or self.tx_ref.tx.inputs[0].txo_ref.hash,
            self.claim.signing_channel_hash,
            self.claim.to_message_bytes()
        ]))
        private_key = ecdsa.SigningKey.from_pem(channel.private_key, hashfunc=hashlib.sha256)
        self.claim.signature = private_key.sign_digest_deterministic(digest, hashfunc=hashlib.sha256)
        self.script.generate()

    def generate_channel_private_key(self):
        private_key = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1, hashfunc=hashlib.sha256)
        self.private_key = private_key.to_pem().decode()
        self.claim.channel.public_key_bytes = private_key.get_verifying_key().to_der()
        self.script.generate()
        return self.private_key

    def is_channel_private_key(self, private_key_pem):
        private_key = ecdsa.SigningKey.from_pem(private_key_pem, hashfunc=hashlib.sha256)
        return self.claim.channel.public_key_bytes == private_key.get_verifying_key().to_der()

    @classmethod
    def pay_claim_name_pubkey_hash(
            cls, amount: int, claim_name: str, claim: Claim, pubkey_hash: bytes) -> 'Output':
        script = cls.script_class.pay_claim_name_pubkey_hash(
            claim_name.encode(), claim, pubkey_hash)
        txo = cls(amount, script)
        return txo

    @classmethod
    def pay_update_claim_pubkey_hash(
            cls, amount: int, claim_name: str, claim_id: str, claim: Claim, pubkey_hash: bytes) -> 'Output':
        script = cls.script_class.pay_update_claim_pubkey_hash(
            claim_name.encode(), unhexlify(claim_id)[::-1], claim, pubkey_hash)
        txo = cls(amount, script)
        return txo

    @classmethod
    def pay_support_pubkey_hash(cls, amount: int, claim_name: str, claim_id: str, pubkey_hash: bytes) -> 'Output':
        script = cls.script_class.pay_support_pubkey_hash(claim_name.encode(), unhexlify(claim_id)[::-1], pubkey_hash)
        return cls(amount, script)

    @classmethod
    def purchase_claim_pubkey_hash(cls, amount: int, claim_id: str, pubkey_hash: bytes) -> 'Output':
        script = cls.script_class.purchase_claim_pubkey_hash(unhexlify(claim_id)[::-1], pubkey_hash)
        return cls(amount, script)

class Transaction(BaseTransaction):

    input_class = Input
    output_class = Output

    outputs: ReadOnlyList[Output]
    inputs: ReadOnlyList[Input]

    @classmethod
    def pay(cls, amount: int, address: bytes, funding_accounts: List[Account], change_account: Account):
        ledger = cls.ensure_all_have_same_ledger(funding_accounts, change_account)
        output = Output.pay_pubkey_hash(amount, ledger.address_to_hash160(address))
        return cls.create([], [output], funding_accounts, change_account)

    @classmethod
    def claim_create(
            cls, name: str, claim: Claim, amount: int, holding_address: str,
            funding_accounts: List[Account], change_account: Account, signing_channel: Output = None):
        ledger = cls.ensure_all_have_same_ledger(funding_accounts, change_account)
        claim_output = Output.pay_claim_name_pubkey_hash(
            amount, name, claim, ledger.address_to_hash160(holding_address)
        )
        if signing_channel is not None:
            claim_output.sign(signing_channel, b'placeholder txid:nout')
        return cls.create([], [claim_output], funding_accounts, change_account, sign=False)

    @classmethod
    def claim_update(
            cls, previous_claim: Output, amount: int, holding_address: str,
            funding_accounts: List[Account], change_account: Account, signing_channel: Output = None):
        ledger = cls.ensure_all_have_same_ledger(funding_accounts, change_account)
        updated_claim = Output.pay_update_claim_pubkey_hash(
            amount, previous_claim.claim_name, previous_claim.claim_id,
            previous_claim.claim, ledger.address_to_hash160(holding_address)
        )
        if signing_channel is not None:
            updated_claim.sign(signing_channel, b'placeholder txid:nout')
        return cls.create(
            [Input.spend(previous_claim)], [updated_claim], funding_accounts, change_account, sign=False
        )

    @classmethod
    def support(cls, claim_name: str, claim_id: str, amount: int, holding_address: str,
                funding_accounts: List[Account], change_account: Account):
        ledger = cls.ensure_all_have_same_ledger(funding_accounts, change_account)
        support_output = Output.pay_support_pubkey_hash(
            amount, claim_name, claim_id, ledger.address_to_hash160(holding_address)
        )
        return cls.create([], [support_output], funding_accounts, change_account)

    @classmethod
    def purchase(cls, claim: Output, amount: int, merchant_address: bytes,
                 funding_accounts: List[Account], change_account: Account):
        ledger = cls.ensure_all_have_same_ledger(funding_accounts, change_account)
        claim_output = Output.purchase_claim_pubkey_hash(
            amount, claim.claim_id, ledger.address_to_hash160(merchant_address)
        )
        return cls.create([], [claim_output], funding_accounts, change_account)

    @property
    def my_inputs(self):
        for txi in self.inputs:
            if txi.txo_ref.txo is not None and txi.txo_ref.txo.is_my_account:
                yield txi

    def _filter_my_outputs(self, f):
        for txo in self.outputs:
            if txo.is_my_account and f(txo.script):
                yield txo

    def _filter_other_outputs(self, f):
        for txo in self.outputs:
            if not txo.is_my_account and f(txo.script):
                yield txo

    @property
    def my_claim_outputs(self):
        return self._filter_my_outputs(lambda s: s.is_claim_name)

    @property
    def my_update_outputs(self):
        return self._filter_my_outputs(lambda s: s.is_update_claim)

    @property
    def my_support_outputs(self):
        return self._filter_my_outputs(lambda s: s.is_support_claim)

    @property
    def other_support_outputs(self):
        return self._filter_other_outputs(lambda s: s.is_support_claim)

    @property
    def my_abandon_outputs(self):
        for txi in self.inputs:
            abandon = txi.txo_ref.txo
            if abandon is not None and abandon.is_my_account and abandon.script.is_claim_involved:
                is_update = False
                if abandon.script.is_claim_name or abandon.script.is_update_claim:
                    for update in self.my_update_outputs:
                        if abandon.claim_id == update.claim_id:
                            is_update = True
                            break
                if not is_update:
                    yield abandon
<|endoftext|>


<commit_before>from django.shortcuts import render, redirect
from django.views.generic import View
from registration.backends.hmac.views import RegistrationView
from django.conf import settings
from askapp import forms, models
from askapp.settings import BLACKLISTED_DOMAINS
from django.views.generic.edit import CreateView, UpdateView
from django.views.generic.detail import DetailView
from django.core.urlresolvers import reverse_lazy
from django.db.models import ObjectDoesNotExist
from django.http import Http404

import rules_light
import askapp.auth_rules
import logging

class LoginRequiredMixin(object):
    def dispatch(self, request, *args, **kwargs):
        if request.user.is_authenticated() and request.user.is_active:
            return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)
        else:
            return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))

class HomeView(View):
    def get_threads(self):
        return models.Thread.objects.all().order_by('-score')

    def get(self, request, *args, **kwargs):
        context = {
            'threads': self.get_threads(),
            'tags': models.Tag.objects.all(),
            'users': models.User.objects.filter(is_active=True).order_by('-date_joined')[:5]
        }
        return render(request, 'index.html', context)

class RecentThreadsView(HomeView):
    def get_threads(self):
        return models.Thread.objects.all().order_by('-created')

class ProfileView(DetailView):
    model = models.User
    template_name = 'profile.html'

    def get_context_data(self, **kwargs):
        context = super(ProfileView, self).get_context_data(**kwargs)
        context['threads'] = models.Thread.objects.filter(user=self.object).order_by('-created')
        return context

class NewRegisterView(View):
    def get(self, request, *args, **kwargs):
        context = {
            'key1': "value",
        }
        return render(request, 'new-registration.html', context)

class ThankyouView(View):
    def get(self, request, *args, **kwargs):
        context = {
            'key1': "value",
        }
        return render(request, 'content.html', context)

class NewLoginView(View):
    def get(self, request, *args, **kwargs):
        context = {
            'key1': "value",
        }
        return render(request, 'new-login.html', context)

class ProfileEditView(LoginRequiredMixin, UpdateView):
    form_class = forms.ProfileForm
    template_name = 'profile_edit.html'
    success_url = reverse_lazy('profile_edit')

    def get_object(self, queryset=None):
        try:
            profile = self.request.user.profile
        except:
            return models.Profile.objects.model(user=self.request.user)
        return profile

@rules_light.class_decorator('askapp.profile.update')
class AdminProfileEditView(LoginRequiredMixin, UpdateView):
    form_class = forms.ProfileForm
    template_name = 'profile_edit.html'
    model = models.Profile

    def get_context_data(self, **kwargs):
        context = super(AdminProfileEditView, self).get_context_data(**kwargs)
        context['admin_view'] = True
        return context

    def get_object(self, queryset=None):
        user = models.User.objects.get(id=self.kwargs['pk'])
        try:
            profile = user.profile
        except:
            return models.Profile.objects.model(user=user)
        return profile

    def post(self, request, *args, **kwargs):
        if 'block_user' in request._post:
            user = models.User.objects.get(id=self.kwargs['pk'])
            user.is_active = False
            user.save(update_fields={'is_active': False})
            self.object = user.profile
            return redirect(self.get_success_url())
        else:
            return super(AdminProfileEditView, self).post(self, request, *args, **kwargs)

    def get_success_url(self):
        return reverse_lazy('profile', args=(self.object.user.id,))

class ThreadView(DetailView):
    model = models.Thread
    template_name = 'thread.html'

    def get_context_data(self, **kwargs):
        context = super(ThreadView, self).get_context_data(**kwargs)
        return context

class QuestionView(View):
    def get(self, request, *args, **kwargs):
        context = {
            'key1': "value",
        }
        return render(request, 'question.html', context)

class CommentView(View):
    def get(self, request, *args, **kwargs):
        context = {
            'key1': "value",
        }
        return render(request, 'comment.html', context)

class AskappRegistrationView(RegistrationView):
    form_class = forms.RecaptchaRegistrationForm
    template_name = 'registration_form.html'

    @staticmethod
    def is_email_blacklisted(email):
        return any([email.lower().endswith('@'+d) for d in BLACKLISTED_DOMAINS])

    def send_activation_email(self, user):
        if self.is_email_blacklisted(user.email):
            logging.debug('blacklisted email %s', user.email)
        else:
            super(AskappRegistrationView, self).send_activation_email(user)

class NewThreadView(LoginRequiredMixin, CreateView):
    form_class = forms.NewThreadForm
    template_name = 'new_thread.html'

    def get_success_url(self):
        return reverse_lazy('thread', args=(self.object.id,))

@rules_light.class_decorator('askapp.thread.update')
class EditThreadView(LoginRequiredMixin, UpdateView):
    form_class = forms.EditThreadForm
    model = models.Thread
    template_name = 'new_thread.html'

    def get_context_data(self, **kwargs):
        context = super(EditThreadView, self).get_context_data(**kwargs)
        context['hide_type'] = True
        context['hide_link'] = self.object.thread_type != 'LL'
        return context

    def get_success_url(self):
        return reverse_lazy('thread', args=(self.object.id,))

class ReplyMixin(LoginRequiredMixin, CreateView):
    """
    Common class for inline and standalone comment form
    """
    form_class = forms.ReplyForm
    model = models.Post

    def get_form(self, form_class=None):
        if not hasattr(self, 'thread'):
            thread_id = self.kwargs.get('thread_id')
            self.thread = models.Thread.objects.get(pk=thread_id)
        rules_light.require(self.request.user, 'askapp.post.create', self.thread)
        return super(ReplyMixin, self).get_form(form_class)

    def form_valid(self, form):
        form.instance.user = self.request.user
        form.instance.thread = self.thread
        return super(ReplyMixin, self).form_valid(form)

    def get_success_url(self):
        return reverse_lazy('thread', args=(self.kwargs.get('thread_id'),))

class ReplyThreadView(ReplyMixin):
    """
    Inline comment handler
    """
    template_name = 'index.html'

    def form_invalid(self, form):
        return redirect(self.get_success_url())

    def get(self, request, *args, **kwargs):
        return redirect(self.get_success_url())

class ReplyCommentView(ReplyMixin):
    """
    Standalone comment handler
    """
    template_name = 'comment.html'

    def get_form(self, form_class=None):
        post_id = self.kwargs.get('post_id')
        self.post = models.Post.objects.get(pk=post_id)
        self.kwargs['thread_id'] = self.post.thread.id  # for get_success_url()
        return super(ReplyCommentView, self).get_form(form_class)

    def get_context_data(self, **kwargs):
        context = {'object': self.post}
        context.update(kwargs)
        return super(ReplyCommentView, self).get_context_data(**context)

    def form_valid(self, form):
        form.instance.parent = self.post
        return super(ReplyCommentView, self).form_valid(form)

class DeleteCommentView(LoginRequiredMixin, View):
    """
    Actually this is not a view, but just a request handler
    """
    def get(self, request, *args, **kwargs):
        post = models.Post.objects.get(pk=kwargs['post_id'])
        rules_light.require(request.user, 'askapp.post.delete', post)
        post.deleted = True
        post.save()
        return redirect(reverse_lazy('thread', args=(post.thread.id, )))

class TagView(HomeView):
    """
    Display threads by tag
    """
    def get_threads(self):
        try:
            tag = models.Tag.objects.get(slug=self.kwargs['slug'])
        except ObjectDoesNotExist:
            raise Http404
        return tag.thread_set.order_by('-created')

class ThreadLikeView(LoginRequiredMixin, View):
    def get(self, request, *args, **kwargs):
        thread = models.Thread.objects.get(pk=kwargs['thread_id'])
        rules_light.require(request.user, 'askapp.threadlike.create', thread)
        models.ThreadLike.vote(thread, request.user, kwargs['verb'])
        return redirect(request.META.get('HTTP_REFERER', reverse_lazy('thread', args=(thread.id))))

class PostLikeView(LoginRequiredMixin, View):
    def get(self, request, *args, **kwargs):
        post = models.Post.objects.get(pk=kwargs['post_id'])
        rules_light.require(request.user, 'askapp.postlike.create', post)
        models.PostLike.vote(post, request.user, kwargs['verb'])
        return redirect(request.META.get('HTTP_REFERER', reverse_lazy('thread', args=(post.thread.id))))
<commit_msg>bugfix: current user was replaced by viewed user at /profile/:id<commit_after>from django.shortcuts import render, redirect
from django.views.generic import View
from registration.backends.hmac.views import RegistrationView
from django.conf import settings
from askapp import forms, models
from askapp.settings import BLACKLISTED_DOMAINS
from django.views.generic.edit import CreateView, UpdateView
from django.views.generic.detail import DetailView
from django.core.urlresolvers import reverse_lazy
from django.db.models import ObjectDoesNotExist
from django.http import Http404

import rules_light
import askapp.auth_rules
import logging

class LoginRequiredMixin(object):
    def dispatch(self, request, *args, **kwargs):
        if request.user.is_authenticated() and request.user.is_active:
            return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)
        else:
            return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))

class HomeView(View):
    def get_threads(self):
        return models.Thread.objects.all().order_by('-score')

    def get(self, request, *args, **kwargs):
        context = {
            'threads': self.get_threads(),
            'tags': models.Tag.objects.all(),
            'users': models.User.objects.filter(is_active=True).order_by('-date_joined')[:5]
        }
        return render(request, 'index.html', context)

class RecentThreadsView(HomeView):
    def get_threads(self):
        return models.Thread.objects.all().order_by('-created')

class ProfileView(DetailView):
    model = models.User
    template_name = 'profile.html'

    def get_context_object_name(self, obj):
        return 'object'

    def get_context_data(self, **kwargs):
        context = super(ProfileView, self).get_context_data(**kwargs)
        context['threads'] = models.Thread.objects.filter(user=self.object).order_by('-created')
        return context

class NewRegisterView(View):
    def get(self, request, *args, **kwargs):
        context = {
            'key1': "value",
        }
        return render(request, 'new-registration.html', context)

class ThankyouView(View):
    def get(self, request, *args, **kwargs):
        context = {
            'key1': "value",
        }
        return render(request, 'content.html', context)

class NewLoginView(View):
    def get(self, request, *args, **kwargs):
        context = {
            'key1': "value",
        }
        return render(request, 'new-login.html', context)

class ProfileEditView(LoginRequiredMixin, UpdateView):
    form_class = forms.ProfileForm
    template_name = 'profile_edit.html'
    success_url = reverse_lazy('profile_edit')

    def get_object(self, queryset=None):
        try:
            profile = self.request.user.profile
        except:
            return models.Profile.objects.model(user=self.request.user)
        return profile

@rules_light.class_decorator('askapp.profile.update')
class AdminProfileEditView(LoginRequiredMixin, UpdateView):
    form_class = forms.ProfileForm
    template_name = 'profile_edit.html'
    model = models.Profile

    def get_context_data(self, **kwargs):
        context = super(AdminProfileEditView, self).get_context_data(**kwargs)
        context['admin_view'] = True
        return context

    def get_object(self, queryset=None):
        user = models.User.objects.get(id=self.kwargs['pk'])
        try:
            profile = user.profile
        except:
            return models.Profile.objects.model(user=user)
        return profile

    def post(self, request, *args, **kwargs):
        if 'block_user' in request._post:
            user = models.User.objects.get(id=self.kwargs['pk'])
            user.is_active = False
            user.save(update_fields={'is_active': False})
            self.object = user.profile
            return redirect(self.get_success_url())
        else:
            return super(AdminProfileEditView, self).post(self, request, *args, **kwargs)

    def get_success_url(self):
        return reverse_lazy('profile', args=(self.object.user.id,))

class ThreadView(DetailView):
    model = models.Thread
    template_name = 'thread.html'

    def get_context_data(self, **kwargs):
        context = super(ThreadView, self).get_context_data(**kwargs)
        return context

class QuestionView(View):
    def get(self, request, *args, **kwargs):
        context = {
            'key1': "value",
        }
        return render(request, 'question.html', context)

class CommentView(View):
    def get(self, request, *args, **kwargs):
        context = {
            'key1': "value",
        }
        return render(request, 'comment.html', context)

class AskappRegistrationView(RegistrationView):
    form_class = forms.RecaptchaRegistrationForm
    template_name = 'registration_form.html'

    @staticmethod
    def is_email_blacklisted(email):
        return any([email.lower().endswith('@'+d) for d in BLACKLISTED_DOMAINS])

    def send_activation_email(self, user):
        if self.is_email_blacklisted(user.email):
            logging.debug('blacklisted email %s', user.email)
        else:
            super(AskappRegistrationView, self).send_activation_email(user)

class NewThreadView(LoginRequiredMixin, CreateView):
    form_class = forms.NewThreadForm
    template_name = 'new_thread.html'

    def get_success_url(self):
        return reverse_lazy('thread', args=(self.object.id,))

@rules_light.class_decorator('askapp.thread.update')
class EditThreadView(LoginRequiredMixin, UpdateView):
    form_class = forms.EditThreadForm
    model = models.Thread
    template_name = 'new_thread.html'

    def get_context_data(self, **kwargs):
        context = super(EditThreadView, self).get_context_data(**kwargs)
        context['hide_type'] = True
        context['hide_link'] = self.object.thread_type != 'LL'
        return context

    def get_success_url(self):
        return reverse_lazy('thread', args=(self.object.id,))

class ReplyMixin(LoginRequiredMixin, CreateView):
    """
    Common class for inline and standalone comment form
    """
    form_class = forms.ReplyForm
    model = models.Post

    def get_form(self, form_class=None):
        if not hasattr(self, 'thread'):
            thread_id = self.kwargs.get('thread_id')
            self.thread = models.Thread.objects.get(pk=thread_id)
        rules_light.require(self.request.user, 'askapp.post.create', self.thread)
        return super(ReplyMixin, self).get_form(form_class)

    def form_valid(self, form):
        form.instance.user = self.request.user
        form.instance.thread = self.thread
        return super(ReplyMixin, self).form_valid(form)

    def get_success_url(self):
        return reverse_lazy('thread', args=(self.kwargs.get('thread_id'),))

class ReplyThreadView(ReplyMixin):
    """
    Inline comment handler
    """
    template_name = 'index.html'

    def form_invalid(self, form):
        return redirect(self.get_success_url())

    def get(self, request, *args, **kwargs):
        return redirect(self.get_success_url())

class ReplyCommentView(ReplyMixin):
    """
    Standalone comment handler
    """
    template_name = 'comment.html'

    def get_form(self, form_class=None):
        post_id = self.kwargs.get('post_id')
        self.post = models.Post.objects.get(pk=post_id)
        self.kwargs['thread_id'] = self.post.thread.id  # for get_success_url()
        return super(ReplyCommentView, self).get_form(form_class)

    def get_context_data(self, **kwargs):
        context = {'object': self.post}
        context.update(kwargs)
        return super(ReplyCommentView, self).get_context_data(**context)

    def form_valid(self, form):
        form.instance.parent = self.post
        return super(ReplyCommentView, self).form_valid(form)

class DeleteCommentView(LoginRequiredMixin, View):
    """
    Actually this is not a view, but just a request handler
    """
    def get(self, request, *args, **kwargs):
        post = models.Post.objects.get(pk=kwargs['post_id'])
        rules_light.require(request.user, 'askapp.post.delete', post)
        post.deleted = True
        post.save()
        return redirect(reverse_lazy('thread', args=(post.thread.id, )))

class TagView(HomeView):
    """
    Display threads by tag
    """
    def get_threads(self):
        try:
            tag = models.Tag.objects.get(slug=self.kwargs['slug'])
        except ObjectDoesNotExist:
            raise Http404
        return tag.thread_set.order_by('-created')

class ThreadLikeView(LoginRequiredMixin, View):
    def get(self, request, *args, **kwargs):
        thread = models.Thread.objects.get(pk=kwargs['thread_id'])
        rules_light.require(request.user, 'askapp.threadlike.create', thread)
        models.ThreadLike.vote(thread, request.user, kwargs['verb'])
        return redirect(request.META.get('HTTP_REFERER', reverse_lazy('thread', args=(thread.id))))

class PostLikeView(LoginRequiredMixin, View):
    def get(self, request, *args, **kwargs):
        post = models.Post.objects.get(pk=kwargs['post_id'])
        rules_light.require(request.user, 'askapp.postlike.create', post)
        models.PostLike.vote(post, request.user, kwargs['verb'])
        return redirect(request.META.get('HTTP_REFERER', reverse_lazy('thread', args=(post.thread.id))))
<|endoftext|>


<commit_before>from django.db import models
from django.dispatch.dispatcher import receiver
from django.contrib.auth.models import User
from django.conf import settings
from django.template.defaultfilters import filesizeformat
import json
import os
import shutil
import random
import textbase

class DropBoxInfo(models.Model):
    user = models.OneToOneField(User, primary_key=True)
    access_token = models.CharField(max_length=100)
    timestamp = models.DateTimeField(auto_now=True)

project_status_choices = (
    ('new', 'New'),
    ('downloading', 'Busy Downloading Files'),
    ('layout', 'Needs Layout'),
    ('preview', 'Has a Preview'),
    ('generating', 'Busy Generating'),
    ('dzgen', 'Busy Making DeepZoom'),
    ('done', 'Done with making your Metabotnik'),
    ('deleted', 'Deleted'),
)
project_layout_choices = (
    ('horizontal', 'horizontal'),
    ('vertical', 'vertical'),
    ('random', 'random')
)
class Project(models.Model):
    name = models.CharField(max_length=250, blank=True)
    description = models.TextField(blank=True)
    # Consider adding a 'source type' so that we can also get files from other places than Dropbox
    # For example, we might make one directly from Arkyves using symlinks,
    # and then path should point somewhere on local disk?
    path = models.TextField()
    user = models.ForeignKey(User, related_name='projects')
    status = models.CharField(max_length=100, choices=project_status_choices, default='new')
    num_files_on_dropbox = models.IntegerField(default=0)
    created = models.DateTimeField(auto_now_add=True)
    layout_mode = models.CharField(max_length=100, choices=project_layout_choices, default='horizontal')
    layout_data = models.TextField(null=True, blank=True)
    background_color = models.CharField(max_length=7, default='#ffffff')
    metabotnik_nonce = models.CharField(max_length=100, null=True, blank=True)
    public = models.BooleanField(default=False)
    storage_size = models.IntegerField(default=0)

    def layout_as_dict(self):
        if not self.layout_data:
            return {}
        return json.loads(self.layout_data)

    def calc_storage_size(self):
        'Returns the number of bytes of storage used by this project, sets the storage_size attribute'
        total = 0
        for dirpath, dirnames, filenames in os.walk(self.storage_path):
            for filename in filenames:
                filepath = os.path.join(dirpath, filename)
                tmp = os.stat(filepath).st_size
                total += tmp
        self.storage_size = total
        self.save()
        return total

    def show(self):
        if self.name:
            return self.name
        return self.path[1:]

    def __unicode__(self):
        return self.show()

    @property
    def user_full_name(self):
        return self.user.get_full_name()

    def set_file_order(self, file_list):
        # Given a list of file in file_list (which may contain blank lines too)
        # Try to set the order of the files of this project to match the file_list order
        if not file_list:
            return # just bail if empty
        current_files, incoming_files = {}, {}
        for f in self.files.all():
            current_files[f.filename] = f
            f.order = 0
            f.is_break = False
        for i, filename in enumerate(file_list):
            if filename:
                incoming_files[i] = filename
            else:
                # if there is a break, find the _preceding_ file and set a break flag on it
                break_filename_to_set = incoming_files[i-1]
                break_file = current_files.get(break_filename_to_set)
                if break_file:
                    break_file.is_break = True
            tmp_file = current_files.get(filename)
            if tmp_file:
                tmp_file.order = i

        for f in current_files.values():
            f.save()

    def set_metadata(self, textbase_buffer):
        data = {}
        for tmp in textbase.TextBase(textbase_buffer.encode('utf8')):
            data[tmp.get('FILENAME', [None])[0]] = tmp
        for f in self.files.all():
            metadata = data.get(f.filename)
            if metadata:
                for k,v in metadata.copy().items():
                    if not filter(None, v):
                        del metadata[k]
                f.metadata = json.dumps(metadata)
                f.save()

    def set_status(self, status):
        self.status = status
        self.save()

    @property
    def storage_path(self):
        tmp = os.path.join(settings.STORAGE_PATH, 'project_%s' % self.pk)
        if not os.path.exists(tmp): os.mkdir(tmp)
        return tmp

    @property
    def originals_path(self):
        tmp = os.path.join(self.storage_path, 'originals')
        if not os.path.exists(tmp): os.mkdir(tmp)
        return tmp

    @property
    def num_files_local(self):
        return len([f for f in os.listdir(self.originals_path) if f.lower().endswith('.jpg')])

    def metabotnik_path(self):
        tmp = os.path.join(self.storage_path, 'metabotnik.jpg')
        if os.path.exists(tmp):
            return tmp

    def deepzoom(self):
        tmp = os.path.join(self.storage_path, 'deepzoom_files')
        if os.path.exists(tmp):
            return tmp

@receiver(models.signals.post_delete, sender=Project)
def project_delete(sender, instance, **kwargs):
    shutil.rmtree(instance.storage_path, ignore_errors=True)

class File(models.Model):
    project = models.ForeignKey(Project, related_name='files')
    filename = models.CharField(max_length=250)
    metadata = models.TextField(null=True, blank=True) # store a JSON blob of data
    width = models.IntegerField(default=0)
    height = models.IntegerField(default=0)
    x = models.IntegerField(default=0) # And record the position
    y = models.IntegerField(default=0)
    new_width = models.IntegerField(default=0) # When doing a layout images need to be resized...
    new_height = models.IntegerField(default=0)
    size = models.IntegerField(default=0) # filesize in bytes
    order = models.IntegerField(default=0)
    is_break = models.BooleanField(default=False) # indicates that a column/row should be broken after this file

    class Meta:
        ordering = ('project', 'order')

    def __unicode__(self):
        return u'%s : %s' % (self.project, self.filename)

    def pretty_size(self):
        return filesizeformat(self.size)

    def metadata_as_textbase(self):
        if not self.metadata:
            return ''
        metadata = json.loads(self.metadata)
        metadata['FILENAME'] = [self.filename]
        if 'filepath' in metadata:
            del metadata['filepath']
        if 'DESCRIPTION' in metadata:
            del metadata['DESCRIPTION']

        buf = []
        for k,v in metadata.items():
            if type(v) is not list:
                vv = [v]
            else:
                vv = v
            buf.append(k+' '+u'\n; '.join(vv))
        return u'\n'.join(buf)

task_status_choices = (
    ('new', 'New'),
    ('wip', 'In Progress'),
    ('error', 'Error'),
    ('done', 'Done'),
)
class Task(models.Model):
    project = models.ForeignKey(Project, related_name='tasks', null=True, blank=True)
    action = models.CharField(max_length=200)
    user = models.ForeignKey(User, related_name='tasks')
    created = models.DateTimeField(auto_now_add=True)
    time_started = models.DateTimeField(null=True, blank=True)
    time_ended = models.DateTimeField(null=True, blank=True)
    status = models.CharField(max_length=100, choices=task_status_choices, default='new')
    payload_data = models.TextField()
    # scheduled time when this should not be run before
    # repeat count, default = 0
    # project foreign key

    class Meta:
        ordering = ('created',)

    def get_payload(self):
        try:
            return json.loads(self.payload_data)
        except (ValueError, TypeError):
            return {}
    def set_payload(self, payload):
        self.payload_data = json.dumps(payload)
        self.save()

    def __unicode__(self):
        return u'%s %s' % (self.action, self.user.email)

    def duration(self):
        # This is a timedelta of the self.time_ended - self.time_started
        # for simplicity only do the seconds
        if not self.time_ended:
            return None
        tmp = self.time_ended.replace(microsecond=0) - self.time_started.replace(microsecond=0)
        return tmp

    @property
    def user_full_name(self):
        return self.user.get_full_name()

def new_task(user, payload):
    'Where payload is a dict containing the task details'
    tmp = json.dumps(payload)
    action = payload.get('action')
    project = payload.get('project_id')
    if project:
        project = Project.objects.get(pk=project)
    return Task.objects.create(action=action, project=project, payload_data=tmp, user=user)

# class Viewpoint(models.Model):
#     user = models.ForeignKey(User, related_name='tasks')
#     project = models.ForeignKey(Project, related_name='files')
# #    next = models.OneToOneField
<commit_msg>If layout has not been done yet, do so.<commit_after>from django.db import models
from django.dispatch.dispatcher import receiver
from django.contrib.auth.models import User
from django.conf import settings
from django.template.defaultfilters import filesizeformat
import json
import os
import shutil
import textbase
from metabotnik.planodo import horzvert_layout

class DropBoxInfo(models.Model):
    user = models.OneToOneField(User, primary_key=True)
    access_token = models.CharField(max_length=100)
    timestamp = models.DateTimeField(auto_now=True)

project_status_choices = (
    ('new', 'New'),
    ('downloading', 'Busy Downloading Files'),
    ('layout', 'Needs Layout'),
    ('preview', 'Has a Preview'),
    ('generating', 'Busy Generating'),
    ('dzgen', 'Busy Making DeepZoom'),
    ('done', 'Done with making your Metabotnik'),
    ('deleted', 'Deleted'),
)
project_layout_choices = (
    ('horizontal', 'horizontal'),
    ('vertical', 'vertical'),
    ('random', 'random')
)
class Project(models.Model):
    name = models.CharField(max_length=250, blank=True)
    description = models.TextField(blank=True)
    # Consider adding a 'source type' so that we can also get files from other places than Dropbox
    # For example, we might make one directly from Arkyves using symlinks,
    # and then path should point somewhere on local disk?
    path = models.TextField()
    user = models.ForeignKey(User, related_name='projects')
    status = models.CharField(max_length=100, choices=project_status_choices, default='new')
    num_files_on_dropbox = models.IntegerField(default=0)
    created = models.DateTimeField(auto_now_add=True)
    layout_mode = models.CharField(max_length=100, choices=project_layout_choices, default='horizontal')
    layout_data = models.TextField(null=True, blank=True)
    background_color = models.CharField(max_length=7, default='#ffffff')
    metabotnik_nonce = models.CharField(max_length=100, null=True, blank=True)
    public = models.BooleanField(default=False)
    storage_size = models.IntegerField(default=0)

    def layout_as_dict(self):
        if not self.layout_data:
            self.layout_data = horzvert_layout(self)
            self.save()
        return json.loads(self.layout_data)

    def calc_storage_size(self):
        'Returns the number of bytes of storage used by this project, sets the storage_size attribute'
        total = 0
        for dirpath, dirnames, filenames in os.walk(self.storage_path):
            for filename in filenames:
                filepath = os.path.join(dirpath, filename)
                tmp = os.stat(filepath).st_size
                total += tmp
        self.storage_size = total
        self.save()
        return total

    def show(self):
        if self.name:
            return self.name
        return self.path[1:]

    def __unicode__(self):
        return self.show()

    @property
    def user_full_name(self):
        return self.user.get_full_name()

    def set_file_order(self, file_list):
        # Given a list of file in file_list (which may contain blank lines too)
        # Try to set the order of the files of this project to match the file_list order
        if not file_list:
            return # just bail if empty
        current_files, incoming_files = {}, {}
        for f in self.files.all():
            current_files[f.filename] = f
            f.order = 0
            f.is_break = False
        for i, filename in enumerate(file_list):
            if filename:
                incoming_files[i] = filename
            else:
                # if there is a break, find the _preceding_ file and set a break flag on it
                break_filename_to_set = incoming_files[i-1]
                break_file = current_files.get(break_filename_to_set)
                if break_file:
                    break_file.is_break = True
            tmp_file = current_files.get(filename)
            if tmp_file:
                tmp_file.order = i

        for f in current_files.values():
            f.save()

    def set_metadata(self, textbase_buffer):
        data = {}
        for tmp in textbase.TextBase(textbase_buffer.encode('utf8')):
            data[tmp.get('FILENAME', [None])[0]] = tmp
        for f in self.files.all():
            metadata = data.get(f.filename)
            if metadata:
                for k,v in metadata.copy().items():
                    if not filter(None, v):
                        del metadata[k]
                f.metadata = json.dumps(metadata)
                f.save()

    def set_status(self, status):
        self.status = status
        self.save()

    @property
    def storage_path(self):
        tmp = os.path.join(settings.STORAGE_PATH, 'project_%s' % self.pk)
        if not os.path.exists(tmp): os.mkdir(tmp)
        return tmp

    @property
    def originals_path(self):
        tmp = os.path.join(self.storage_path, 'originals')
        if not os.path.exists(tmp): os.mkdir(tmp)
        return tmp

    @property
    def num_files_local(self):
        return len([f for f in os.listdir(self.originals_path) if f.lower().endswith('.jpg')])

    def metabotnik_path(self):
        tmp = os.path.join(self.storage_path, 'metabotnik.jpg')
        if os.path.exists(tmp):
            return tmp

    def deepzoom(self):
        tmp = os.path.join(self.storage_path, 'deepzoom_files')
        if os.path.exists(tmp):
            return tmp

@receiver(models.signals.post_delete, sender=Project)
def project_delete(sender, instance, **kwargs):
    shutil.rmtree(instance.storage_path, ignore_errors=True)

class File(models.Model):
    project = models.ForeignKey(Project, related_name='files')
    filename = models.CharField(max_length=250)
    metadata = models.TextField(null=True, blank=True) # store a JSON blob of data
    width = models.IntegerField(default=0)
    height = models.IntegerField(default=0)
    x = models.IntegerField(default=0) # And record the position
    y = models.IntegerField(default=0)
    new_width = models.IntegerField(default=0) # When doing a layout images need to be resized...
    new_height = models.IntegerField(default=0)
    size = models.IntegerField(default=0) # filesize in bytes
    order = models.IntegerField(default=0)
    is_break = models.BooleanField(default=False) # indicates that a column/row should be broken after this file

    class Meta:
        ordering = ('project', 'order')

    def __unicode__(self):
        return u'%s : %s' % (self.project, self.filename)

    def pretty_size(self):
        return filesizeformat(self.size)

    def metadata_as_textbase(self):
        if not self.metadata:
            return ''
        metadata = json.loads(self.metadata)
        metadata['FILENAME'] = [self.filename]
        if 'filepath' in metadata:
            del metadata['filepath']
        if 'DESCRIPTION' in metadata:
            del metadata['DESCRIPTION']

        buf = []
        for k,v in metadata.items():
            if type(v) is not list:
                vv = [v]
            else:
                vv = v
            buf.append(k+' '+u'\n; '.join(vv))
        return u'\n'.join(buf)

task_status_choices = (
    ('new', 'New'),
    ('wip', 'In Progress'),
    ('error', 'Error'),
    ('done', 'Done'),
)
class Task(models.Model):
    project = models.ForeignKey(Project, related_name='tasks', null=True, blank=True)
    action = models.CharField(max_length=200)
    user = models.ForeignKey(User, related_name='tasks')
    created = models.DateTimeField(auto_now_add=True)
    time_started = models.DateTimeField(null=True, blank=True)
    time_ended = models.DateTimeField(null=True, blank=True)
    status = models.CharField(max_length=100, choices=task_status_choices, default='new')
    payload_data = models.TextField()
    # scheduled time when this should not be run before
    # repeat count, default = 0
    # project foreign key

    class Meta:
        ordering = ('created',)

    def get_payload(self):
        try:
            return json.loads(self.payload_data)
        except (ValueError, TypeError):
            return {}
    def set_payload(self, payload):
        self.payload_data = json.dumps(payload)
        self.save()

    def __unicode__(self):
        return u'%s %s' % (self.action, self.user.email)

    def duration(self):
        # This is a timedelta of the self.time_ended - self.time_started
        # for simplicity only do the seconds
        if not self.time_ended:
            return None
        tmp = self.time_ended.replace(microsecond=0) - self.time_started.replace(microsecond=0)
        return tmp

    @property
    def user_full_name(self):
        return self.user.get_full_name()

def new_task(user, payload):
    'Where payload is a dict containing the task details'
    tmp = json.dumps(payload)
    action = payload.get('action')
    project = payload.get('project_id')
    if project:
        project = Project.objects.get(pk=project)
    return Task.objects.create(action=action, project=project, payload_data=tmp, user=user)

# class Viewpoint(models.Model):
#     user = models.ForeignKey(User, related_name='tasks')
#     project = models.ForeignKey(Project, related_name='files')
# #    next = models.OneToOneField
<|endoftext|>