<commit_before>
"""
IMRED

Reduction script for SALT data -- this is
for science level reductions with variance frames

This includes step that are not yet included in the pipeline
and can be used for extended reductions of SALT data.

It does require the pysalt package to be installed
and up to date.

"""

import os, sys, glob, shutil

import numpy as np
from astropy.io import fits
from scipy.ndimage.filters import median_filter

from pyraf import iraf
from iraf import pysalt

from saltobslog import obslog
from saltprepare import  *
from saltbias import saltbias
from saltgain import saltgain
from saltxtalk import saltxtalk
from saltcrclean import saltcrclean
from saltcombine import saltcombine
from saltflat import saltflat
from saltmosaic import saltmosaic
from saltillum import saltillum

def imred(infile_list, prodir, bpmfile=None, gaindb = None, geomfile = None, cleanup=True):

    #get the name of the files
    infiles=','.join(['%s' % x for x in infile_list])

    #get the current date for the files
    obsdate=os.path.basename(infile_list[0])[1:9]
    print obsdate

    #set up some files that will be needed
    logfile='spec'+obsdate+'.log'
    flatimage='FLAT%s.fits' % (obsdate)
    dbfile='spec%s.db' % obsdate

    #create the observation log
    obs_dict=obslog(infile_list)

    #prepare the data
    saltprepare(infiles, '', 'p', createvar=False, badpixelimage='', clobber=True, logfile=logfile, verbose=True)

    #bias subtract the data
    saltbias('pP*fits', '', 'b', subover=True, trim=True, subbias=False, masterbias='',
              median=False, function='polynomial', order=5, rej_lo=3.0, rej_hi=5.0,
              niter=10, plotover=False, turbo=False,
              clobber=True, logfile=logfile, verbose=True)

    add_variance('bpP*fits', bpmfile)

    #gain correct the data
    usedb = False
    if gaindb: usedb = True
    saltgain('bpP*fits', '', 'g', gaindb=gaindb, usedb=usedb, mult=True, clobber=True, logfile=logfile, verbose=True)

    #cross talk correct the data
    saltxtalk('gbpP*fits', '', 'x', xtalkfile = "", usedb=False, clobber=True, logfile=logfile, verbose=True)

    #flat field correct the data
    flat_imgs=''
    for i in range(len(infile_list)):
        if obs_dict['CCDTYPE'][i].count('FLAT'):
           if flat_imgs: flat_imgs += ','
           flat_imgs += 'xgbp'+os.path.basename(infile_list[i])

    if 0: #len(flat_imgs)!=0:
         saltcombine(flat_imgs,flatimage, method='median', reject=None, mask=False,    \
                weight=False, blank=0, scale=None, statsec='[200:300, 600:800]', lthresh=3,    \
                hthresh=3, clobber=True, logfile=logfile, verbose=True)
         saltillum(flatimage, flatimage, '', mbox=11, clobber=True, logfile=logfile, verbose=True)

         saltflat('xgbpP*fits', '', 'f', flatimage, minflat=0.8, allext=False, clobber=True, logfile=logfile, verbose=True)
    else:
         flats=None
         imfiles=glob.glob('xgbpP*fits')
         for f in imfiles:
             shutil.copy(f, 'f'+f)

    #cosmic ray clean the data
    #only clean the object data
    for i in range(len(infile_list)):
        if obs_dict['CCDTYPE'][i].count('OBJECT') and obs_dict['INSTRUME'][i].count('RSS'):
          img='fxgbp'+os.path.basename(infile_list[i])
          #saltcrclean(img, img, '', crtype='edge', thresh=5, mbox=11, bthresh=5.0,
          #      flux_ratio=0.2, bbox=25, gain=1.0, rdnoise=5.0, fthresh=5.0, bfactor=2,
          #      gbox=3, maxiter=5, multithread=True,  clobber=True, logfile=logfile, verbose=True)

    #mosaic the data
    if geomfile is None: geomfile=iraf.osfn("pysalt$data/rss/RSSgeom.dat")
    try:
       saltmosaic('fxgbpP*fits', '', 'm', geomfile, interp='linear', cleanup=True, geotran=True, clobber=True, logfile=logfile, verbose=True)
    except:
       saltmosaic('fxgbpP*fits', '', 'm', geomfile, interp='linear', cleanup=True, geotran=True, clobber=True, logfile=logfile, verbose=True)

    #add needed header columns and make a better mask
    for img in infile_list:
        filename = 'mxgbp'+os.path.basename(img)
        hdu = pyfits.open(filename, 'update')
        hdu[2].header.update('EXTNAME','VAR')
        hdu[3].header.update('EXTNAME','BPM')
        bpm_rc = (hdu[3].data>0).astype('uint8')
        zeroscicol = hdu['SCI'].data.sum(axis=0) == 0
        bpmgapcol = bpm_rc.mean(axis=0) == 1
        addbpmcol = zeroscicol & ~bpmgapcol
        addbpmcol[np.argmax(addbpmcol)-4:np.argmax(addbpmcol)] = True    # allow for chip tilt
        bpm_rc[:,addbpmcol] = 1
        hdu[3].data = bpm_rc
        hdu.writeto(filename,clobber=True)

    #clean up the images
    if cleanup:
           for f in glob.glob('p*fits'): os.remove(f)
           for f in glob.glob('bp*fits'): os.remove(f)
           for f in glob.glob('gbp*fits'): os.remove(f)
           for f in glob.glob('xgbp*fits'): os.remove(f)
           for f in glob.glob('fxgbp*fits'): os.remove(f)

def add_variance(filenames, bpmfile):
    file_list=glob.glob(filenames)
    badpixelstruct = fits.open(bpmfile)
    for f in file_list:
        struct = fits.open(f)
        nsciext=len(struct)-1
        nextend=nsciext
        for i in range(1, nsciext+1):
            hdu=CreateVariance(struct[i], i, nextend+i)
            hdu.header.update('EXTNAME','VAR')
            struct[i].header['VAREXT'] = (nextend+i, 'Extension for Variance Frame')
            struct.append(hdu)
        nextend+=nsciext
        for i in range(1, nsciext+1):
            if os.path.basename(bpmfile)=='bpm_rss_11.fits':
                hdu=masterbadpixel(struct, badpixelstruct, i, nextend+i)
            else:
                hdu=createbadpixel(struct, badpixelstruct, i, nextend+i)
            struct[i].header['BPMEXT']=(nextend+i, 'Extension for Bad Pixel Mask')
            hdu.header.update('EXTNAME','BPM')
            struct.append(hdu)
        nextend+=nsciext
        struct[0].header['NEXTEND'] = nextend
        if os.path.isfile(f): os.remove(f)
        struct.writeto(f)

def masterbadpixel(inhdu, bphdu, sci_ext, bp_ext):
    """Create the bad pixel hdu bp_ext for inhdu[sci_ext] from a master, bphdu
    """

    if bphdu is None:
        data=np.zeros_like(inhdu[sci_ext].data).astype("uint8")
    else:
        infile=inhdu.fileinfo(0)['filename']
        bpfile=bphdu.fileinfo(0)['filename']
        masternext = len(bphdu)-1
        masterext = (sci_ext-1) % masternext + 1        # allow for windows

        if not saltkey.compare(inhdu[0], bphdu[0], 'INSTRUME', infile, bpfile):
            message = '%s and %s are not the same %s' % (infile,bpfile, 'INSTRUME')
            raise SaltError(message)
        else:
            rows,cols = inhdu[sci_ext].data.shape
            cbin,rbin = np.array(inhdu[sci_ext].header["CCDSUM"].split(" ")).astype(int)
            masterrows,mastercols = bphdu[masterext].data.shape
            master_rc = np.ones((masterrows+(masterrows % rbin),mastercols+(mastercols % cbin)))
            master_rc[:masterrows,:mastercols] = bphdu[masterext].data
            masterrows,mastercols=(masterrows+(masterrows % rbin),mastercols+(mastercols % cbin))
            ampsec = inhdu[sci_ext].header["AMPSEC"].strip("[]").split(",")
            r1,r2 = (np.array(ampsec[1].split(":")).astype(int) / rbin) * rbin
            c1,c2 = (np.array(ampsec[0].split(":")).astype(int) / cbin) * cbin
            if c1 > c2: c1,c2 = c2,c1
            bin_rc = (master_rc.reshape(masterrows/rbin,rbin,mastercols/cbin,cbin).sum(axis=3).sum(axis=1) > 0)
            data = bin_rc[ r1:r2, c1:c2 ].astype('uint8')

    header=inhdu[sci_ext].header.copy()
    header.update('EXTVER',bp_ext)
    header.update('SCIEXT',sci_ext,comment='Extension of science frame')

    return pyfits.ImageHDU(data=data, header=header, name='BPM')

if __name__=='__main__':
   raw_files=glob.glob(sys.argv[1]+'P*fits')
   bpmfile = sys.argv[2]
   prodir=os.path.curdir+'/'
   imred(raw_files, prodir, cleanup=True, bpmfile=bpmfile)
<commit_msg>working version<commit_after>
"""
IMRED

Reduction script for SALT data -- this is
for science level reductions with variance frames

This includes step that are not yet included in the pipeline
and can be used for extended reductions of SALT data.

It does require the pysalt package to be installed
and up to date.

"""

import os, sys, glob, shutil

import numpy as np
from astropy.io import fits
from scipy.ndimage.filters import median_filter

from pyraf import iraf
from iraf import pysalt

from saltobslog import obslog
from saltprepare import  *
from saltbias import saltbias
from saltgain import saltgain
from saltxtalk import saltxtalk
from saltcrclean import saltcrclean
from saltcombine import saltcombine
from saltflat import saltflat
from saltmosaic import saltmosaic
from saltillum import saltillum

def imred(infile_list, prodir, bpmfile=None, gaindb = None, geomfile = None, cleanup=True):

    #get the name of the files
    infiles=','.join(['%s' % x for x in infile_list])

    #get the current date for the files
    obsdate=os.path.basename(infile_list[0])[1:9]
    print obsdate

    #set up some files that will be needed
    logfile='spec'+obsdate+'.log'
    flatimage='FLAT%s.fits' % (obsdate)
    dbfile='spec%s.db' % obsdate

    #create the observation log
    obs_dict=obslog(infile_list)

    #prepare the data
    saltprepare(infiles, '', 'p', createvar=False, badpixelimage='', clobber=True, logfile=logfile, verbose=True)

    #bias subtract the data
    saltbias('pP*fits', '', 'b', subover=True, trim=True, subbias=False, masterbias='',
              median=False, function='polynomial', order=5, rej_lo=3.0, rej_hi=5.0,
              niter=10, plotover=False, turbo=False,
              clobber=True, logfile=logfile, verbose=True)

    add_variance('bpP*fits', bpmfile)

    #gain correct the data
    usedb = False
    if gaindb: usedb = True
    saltgain('bpP*fits', '', 'g', gaindb=gaindb, usedb=usedb, mult=True, clobber=True, logfile=logfile, verbose=True)

    #cross talk correct the data
    saltxtalk('gbpP*fits', '', 'x', xtalkfile = "", usedb=False, clobber=True, logfile=logfile, verbose=True)

    #flat field correct the data
    flat_imgs=''
    for i in range(len(infile_list)):
        if obs_dict['CCDTYPE'][i].count('FLAT'):
           if flat_imgs: flat_imgs += ','
           flat_imgs += 'xgbp'+os.path.basename(infile_list[i])

    if 0: #len(flat_imgs)!=0:
         saltcombine(flat_imgs,flatimage, method='median', reject=None, mask=False,    \
                weight=False, blank=0, scale=None, statsec='[200:300, 600:800]', lthresh=3,    \
                hthresh=3, clobber=True, logfile=logfile, verbose=True)
         saltillum(flatimage, flatimage, '', mbox=11, clobber=True, logfile=logfile, verbose=True)

         saltflat('xgbpP*fits', '', 'f', flatimage, minflat=0.8, allext=False, clobber=True, logfile=logfile, verbose=True)
    else:
         flats=None
         imfiles=glob.glob('xgbpP*fits')
         for f in imfiles:
             shutil.copy(f, 'f'+f)

    #cosmic ray clean the data
    #only clean the object data
    for i in range(len(infile_list)):
        if obs_dict['CCDTYPE'][i].count('OBJECT') and obs_dict['INSTRUME'][i].count('RSS'):
          img='fxgbp'+os.path.basename(infile_list[i])
          saltcrclean(img, img, '', crtype='edge', thresh=5, mbox=11, bthresh=5.0,
                flux_ratio=0.2, bbox=25, gain=1.0, rdnoise=5.0, fthresh=5.0, bfactor=2,
                gbox=3, maxiter=5, multithread=True,  clobber=True, logfile=logfile, verbose=True)

    #mosaic the data
    if geomfile is None: geomfile=iraf.osfn("pysalt$data/rss/RSSgeom.dat")
    try:
       saltmosaic('fxgbpP*fits', '', 'm', geomfile, interp='linear', cleanup=True, geotran=True, clobber=True, logfile=logfile, verbose=True)
    except:
       saltmosaic('fxgbpP*fits', '', 'm', geomfile, interp='linear', cleanup=True, geotran=True, clobber=True, logfile=logfile, verbose=True)

    #add needed header columns and make a better mask
    for img in infile_list:
        filename = 'mfxgbp'+os.path.basename(img)
        hdu = fits.open(filename, 'update')
        hdu[2].header.update('EXTNAME','VAR')
        hdu[3].header.update('EXTNAME','BPM')
        bpm_rc = (hdu[3].data>0).astype('uint8')
        zeroscicol = hdu['SCI'].data.sum(axis=0) == 0
        bpmgapcol = bpm_rc.mean(axis=0) == 1
        addbpmcol = zeroscicol & ~bpmgapcol
        addbpmcol[np.argmax(addbpmcol)-4:np.argmax(addbpmcol)] = True    # allow for chip tilt
        bpm_rc[:,addbpmcol] = 1
        hdu[3].data = bpm_rc
        hdu.writeto(filename,clobber=True)

    #clean up the images
    if cleanup:
           for f in glob.glob('p*fits'): os.remove(f)
           for f in glob.glob('bp*fits'): os.remove(f)
           for f in glob.glob('gbp*fits'): os.remove(f)
           for f in glob.glob('xgbp*fits'): os.remove(f)
           for f in glob.glob('fxgbp*fits'): os.remove(f)

def add_variance(filenames, bpmfile):
    file_list=glob.glob(filenames)
    badpixelstruct = fits.open(bpmfile)
    for f in file_list:
        struct = fits.open(f)
        nsciext=len(struct)-1
        nextend=nsciext
        for i in range(1, nsciext+1):
            hdu=CreateVariance(struct[i], i, nextend+i)
            hdu.header.update('EXTNAME','VAR')
            struct[i].header['VAREXT'] = (nextend+i, 'Extension for Variance Frame')
            struct.append(hdu)
        nextend+=nsciext
        for i in range(1, nsciext+1):
            if os.path.basename(bpmfile)=='bpm_rss_11.fits':
                hdu=masterbadpixel(struct, badpixelstruct, i, nextend+i)
            else:
                hdu=createbadpixel(struct, badpixelstruct, i, nextend+i)
            struct[i].header['BPMEXT']=(nextend+i, 'Extension for Bad Pixel Mask')
            hdu.header.update('EXTNAME','BPM')
            struct.append(hdu)
        nextend+=nsciext
        struct[0].header['NEXTEND'] = nextend
        if os.path.isfile(f): os.remove(f)
        struct.writeto(f)

def masterbadpixel(inhdu, bphdu, sci_ext, bp_ext):
    """Create the bad pixel hdu bp_ext for inhdu[sci_ext] from a master, bphdu
    """

    if bphdu is None:
        data=np.zeros_like(inhdu[sci_ext].data).astype("uint8")
    else:
        infile=inhdu.fileinfo(0)['filename']
        bpfile=bphdu.fileinfo(0)['filename']
        masternext = len(bphdu)-1
        masterext = (sci_ext-1) % masternext + 1        # allow for windows

        if not saltkey.compare(inhdu[0], bphdu[0], 'INSTRUME', infile, bpfile):
            message = '%s and %s are not the same %s' % (infile,bpfile, 'INSTRUME')
            raise SaltError(message)
        else:
            rows,cols = inhdu[sci_ext].data.shape
            cbin,rbin = np.array(inhdu[sci_ext].header["CCDSUM"].split(" ")).astype(int)
            masterrows,mastercols = bphdu[masterext].data.shape
            master_rc = np.ones((masterrows+(masterrows % rbin),mastercols+(mastercols % cbin)))
            master_rc[:masterrows,:mastercols] = bphdu[masterext].data
            masterrows,mastercols=(masterrows+(masterrows % rbin),mastercols+(mastercols % cbin))
            ampsec = inhdu[sci_ext].header["AMPSEC"].strip("[]").split(",")
            r1,r2 = (np.array(ampsec[1].split(":")).astype(int) / rbin) * rbin
            c1,c2 = (np.array(ampsec[0].split(":")).astype(int) / cbin) * cbin
            if c1 > c2: c1,c2 = c2,c1
            bin_rc = (master_rc.reshape(masterrows/rbin,rbin,mastercols/cbin,cbin).sum(axis=3).sum(axis=1) > 0)
            data = bin_rc[ r1:r2, c1:c2 ].astype('uint8')

    header=inhdu[sci_ext].header.copy()
    header.update('EXTVER',bp_ext)
    header.update('SCIEXT',sci_ext,comment='Extension of science frame')

    return fits.ImageHDU(data=data, header=header, name='BPM')

if __name__=='__main__':
   raw_files=glob.glob(sys.argv[1]+'P*fits')
   bpmfile = sys.argv[2]
   prodir=os.path.curdir+'/'
   imred(raw_files, prodir, cleanup=True, bpmfile=bpmfile)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

import os
import random

class Period:
    def __init__(self, name):
        self.name = name

class Company:
    def __init__(self, partner_id):
        self.partner_id = partner_id

class Partner:
    def __init__(self, name, nif):
        self.name = name
        self.vat = nif

class Journal:
    def __init__(self, name):
        self.name = name

class FiscalPosition:
    def __init__(self, name, cre_in_invoice, cre_out_invoice):
        self.name = name
        self.sii_in_clave_regimen_especial = cre_in_invoice
        self.sii_out_clave_regimen_especial = cre_out_invoice

class Tax:
    def __init__(self, name, amount):
        self.name = name
        self.amount = amount

class InvoiceTax:
    def __init__(self, name, base, tax_amount, tax_id):
        self.name = name
        self.base = base  # base imponible
        self.tax_amount = tax_amount
        self.tax_id = tax_id

class InvoiceLine:
    def __init__(self, price_subtotal, invoice_line_tax_id):
        self.price_subtotal = price_subtotal
        self.invoice_line_tax_id = invoice_line_tax_id

class Invoice:
    def __init__(self, journal_id, number, type, partner_id, company_id,
                 amount_total, period_id, date_invoice, tax_line, sii_sent,
                 rectificative_type, fiscal_position, invoice_line):
        self.journal_id = journal_id
        self.number = number
        self.type = type
        self.partner_id = partner_id
        self.company_id = company_id
        self.period_id = period_id
        self.amount_total = amount_total
        self.date_invoice = date_invoice
        self.tax_line = tax_line
        self.invoice_line = invoice_line
        self.fiscal_position = fiscal_position
        self.sii_sent = sii_sent
        self.rectificative_type = rectificative_type
        # RECTIFICATIVE_TYPE_SELECTION = [
        #     ('N', 'Normal'),
        #     ('R', 'Rectificative'),
        #     ('A', 'Nullifier'),
        #     ('B', 'Nullifier with substitution')
        # ]

class DataGenerator:
    def __init__(self):
        self.sii_sent = False
        self.period = Period(name='12/2016')
        name_iva_21 = 'IVA 21%'
        name_iva_4 = 'IVA 4%'
        name_ibi = 'IBI 15%'
        tax_ibi = Tax(name=name_ibi, amount=0.15)
        tax_iva_21 = Tax(name=name_iva_21, amount=0.21)
        tax_iva_4 = Tax(name=name_iva_21, amount=0.04)
        self.invoice_line = [
            InvoiceLine(price_subtotal=100, invoice_line_tax_id=[tax_iva_21]),
            InvoiceLine(price_subtotal=200,
                        invoice_line_tax_id=[tax_iva_21, tax_ibi]),
            InvoiceLine(price_subtotal=400, invoice_line_tax_id=[tax_iva_4]),
            InvoiceLine(price_subtotal=800, invoice_line_tax_id=[tax_ibi])
        ]

        base_iva_21 = sum(
            [line.price_subtotal
             for line in self.invoice_line
             if tax_iva_21.amount
             in [tax.amount for tax in line.invoice_line_tax_id]]
        )
        base_iva_4 = sum(
            [line.price_subtotal
             for line in self.invoice_line
             if tax_iva_4.amount
             in [tax.amount for tax in line.invoice_line_tax_id]]
        )
        base_ibi = sum(
            [line.price_subtotal
             for line in self.invoice_line
             if tax_ibi.amount
             in [tax.amount for tax in line.invoice_line_tax_id]]
        )
        invoice_tax_iva_21 = InvoiceTax(  # TODO les tax_line són una per cada tipus d'impost repetit i suma
            name=name_iva_21, base=base_iva_21,
            tax_amount=base_iva_21 * tax_iva_21.amount, tax_id=tax_iva_21
        )
        invoice_tax_iva_4 = InvoiceTax(
            name=name_iva_4, base=base_iva_4,
            tax_amount=base_iva_4 * tax_iva_4.amount, tax_id=tax_iva_4
        )
        invoice_tax_ibi = InvoiceTax(
            name=name_ibi, base=base_ibi,
            tax_amount=base_ibi * tax_ibi.amount, tax_id=tax_ibi
        )
        self.tax_line = [invoice_tax_iva_21, invoice_tax_iva_4, invoice_tax_ibi]  # No hi ha impostos repetits

        self.partner_invoice = Partner(
            name=os.environ.get('NOMBRE_TITULAR', u'Francisco García'),
            nif=os.environ.get('NIF_TITULAR', u'12345678T')
        )
        partner_company = Partner(
            name=os.environ.get(
                'NOMBRE_CONTRAPARTE', u'Compañía Eléctrica S.A.'
            ),
            nif=os.environ.get('NIF_CONTRAPARTE', '55555555T')
        )
        self.company = Company(partner_id=partner_company)

        self.invoice_number = 'F012345'
        self.date_invoice = '2016-12-31'
        taxes_amount = sum([tax.tax_amount for tax in self.tax_line])
        base_amount = sum([line.price_subtotal for line in self.invoice_line])
        self.amount_total = taxes_amount + base_amount
        cre_in_invoice = '01'
        cre_out_invoice = '01'
        self.fiscal_position = FiscalPosition(
            name=u'Régimen Islas Canarias', cre_in_invoice=cre_in_invoice,
            cre_out_invoice=cre_out_invoice
        )

    def get_in_invoice(self):
        journal = Journal(name='Factura de Energía Recibida')

        invoice = Invoice(
            type='in_invoice',
            journal_id=journal,
            rectificative_type='N',
            number=self.invoice_number,
            partner_id=self.partner_invoice,
            company_id=self.company,
            amount_total=self.amount_total,
            period_id=self.period,
            date_invoice=self.date_invoice,
            tax_line=self.tax_line,
            invoice_line=self.invoice_line,
            sii_sent=self.sii_sent,
            fiscal_position=self.fiscal_position
        )
        return invoice

    def get_out_invoice(self):
        journal = Journal(name='Factura de Energía Emitida')

        invoice = Invoice(
            type='out_invoice',
            journal_id=journal,
            rectificative_type='N',
            number=self.invoice_number,
            partner_id=self.partner_invoice,
            company_id=self.company,
            amount_total=self.amount_total,
            period_id=self.period,
            date_invoice=self.date_invoice,
            tax_line=self.tax_line,
            invoice_line=self.invoice_line,
            sii_sent=self.sii_sent,
            fiscal_position=self.fiscal_position
        )
        return invoice

    def get_in_refund_invoice(self):
        journal = Journal(name='Factura de Energía Rectificativa Recibida')

        invoice = Invoice(
            type='in_refund',
            journal_id=journal,
            rectificative_type='R',
            number=self.invoice_number,
            partner_id=self.partner_invoice,
            company_id=self.company,
            amount_total=self.amount_total,
            period_id=self.period,
            date_invoice=self.date_invoice,
            tax_line=self.tax_line,
            invoice_line=self.invoice_line,
            sii_sent=self.sii_sent,
            fiscal_position=self.fiscal_position
        )
        return invoice

    def get_out_refund_invoice(self):
        journal = Journal(name='Factura de Energía Rectificativa Emitida')

        invoice = Invoice(
            type='out_refund',
            journal_id=journal,
            rectificative_type='R',
            number=self.invoice_number,
            partner_id=self.partner_invoice,
            company_id=self.company,
            amount_total=self.amount_total,
            period_id=self.period,
            date_invoice=self.date_invoice,
            tax_line=self.tax_line,
            invoice_line=self.invoice_line,
            sii_sent=self.sii_sent,
            fiscal_position=self.fiscal_position
        )
        return invoice
<commit_msg>Generate random invoice numbers<commit_after># -*- coding: utf-8 -*-

import os
import random

class Period:
    def __init__(self, name):
        self.name = name

class Company:
    def __init__(self, partner_id):
        self.partner_id = partner_id

class Partner:
    def __init__(self, name, nif):
        self.name = name
        self.vat = nif

class Journal:
    def __init__(self, name):
        self.name = name

class FiscalPosition:
    def __init__(self, name, cre_in_invoice, cre_out_invoice):
        self.name = name
        self.sii_in_clave_regimen_especial = cre_in_invoice
        self.sii_out_clave_regimen_especial = cre_out_invoice

class Tax:
    def __init__(self, name, amount):
        self.name = name
        self.amount = amount

class InvoiceTax:
    def __init__(self, name, base, tax_amount, tax_id):
        self.name = name
        self.base = base  # base imponible
        self.tax_amount = tax_amount
        self.tax_id = tax_id

class InvoiceLine:
    def __init__(self, price_subtotal, invoice_line_tax_id):
        self.price_subtotal = price_subtotal
        self.invoice_line_tax_id = invoice_line_tax_id

class Invoice:
    def __init__(self, journal_id, number, type, partner_id, company_id,
                 amount_total, period_id, date_invoice, tax_line, sii_sent,
                 rectificative_type, fiscal_position, invoice_line):
        self.journal_id = journal_id
        self.number = number
        self.type = type
        self.partner_id = partner_id
        self.company_id = company_id
        self.period_id = period_id
        self.amount_total = amount_total
        self.date_invoice = date_invoice
        self.tax_line = tax_line
        self.invoice_line = invoice_line
        self.fiscal_position = fiscal_position
        self.sii_sent = sii_sent
        self.rectificative_type = rectificative_type
        # RECTIFICATIVE_TYPE_SELECTION = [
        #     ('N', 'Normal'),
        #     ('R', 'Rectificative'),
        #     ('A', 'Nullifier'),
        #     ('B', 'Nullifier with substitution')
        # ]

class DataGenerator:
    def __init__(self):
        self.sii_sent = False
        self.period = Period(name='12/2016')
        name_iva_21 = 'IVA 21%'
        name_iva_4 = 'IVA 4%'
        name_ibi = 'IBI 15%'
        tax_ibi = Tax(name=name_ibi, amount=0.15)
        tax_iva_21 = Tax(name=name_iva_21, amount=0.21)
        tax_iva_4 = Tax(name=name_iva_21, amount=0.04)
        self.invoice_line = [
            InvoiceLine(price_subtotal=100, invoice_line_tax_id=[tax_iva_21]),
            InvoiceLine(price_subtotal=200,
                        invoice_line_tax_id=[tax_iva_21, tax_ibi]),
            InvoiceLine(price_subtotal=400, invoice_line_tax_id=[tax_iva_4]),
            InvoiceLine(price_subtotal=800, invoice_line_tax_id=[tax_ibi])
        ]

        base_iva_21 = sum(
            [line.price_subtotal
             for line in self.invoice_line
             if tax_iva_21.amount
             in [tax.amount for tax in line.invoice_line_tax_id]]
        )
        base_iva_4 = sum(
            [line.price_subtotal
             for line in self.invoice_line
             if tax_iva_4.amount
             in [tax.amount for tax in line.invoice_line_tax_id]]
        )
        base_ibi = sum(
            [line.price_subtotal
             for line in self.invoice_line
             if tax_ibi.amount
             in [tax.amount for tax in line.invoice_line_tax_id]]
        )
        invoice_tax_iva_21 = InvoiceTax(  # TODO les tax_line són una per cada tipus d'impost repetit i suma
            name=name_iva_21, base=base_iva_21,
            tax_amount=base_iva_21 * tax_iva_21.amount, tax_id=tax_iva_21
        )
        invoice_tax_iva_4 = InvoiceTax(
            name=name_iva_4, base=base_iva_4,
            tax_amount=base_iva_4 * tax_iva_4.amount, tax_id=tax_iva_4
        )
        invoice_tax_ibi = InvoiceTax(
            name=name_ibi, base=base_ibi,
            tax_amount=base_ibi * tax_ibi.amount, tax_id=tax_ibi
        )
        self.tax_line = [invoice_tax_iva_21, invoice_tax_iva_4, invoice_tax_ibi]  # No hi ha impostos repetits

        self.partner_invoice = Partner(
            name=os.environ.get('NOMBRE_TITULAR', u'Francisco García'),
            nif=os.environ.get('NIF_TITULAR', u'12345678T')
        )
        partner_company = Partner(
            name=os.environ.get(
                'NOMBRE_CONTRAPARTE', u'Compañía Eléctrica S.A.'
            ),
            nif=os.environ.get('NIF_CONTRAPARTE', '55555555T')
        )
        self.company = Company(partner_id=partner_company)

        self.invoice_number = str(random.randrange(0, 100000)).zfill(5)
        self.date_invoice = '2016-12-31'
        taxes_amount = sum([tax.tax_amount for tax in self.tax_line])
        base_amount = sum([line.price_subtotal for line in self.invoice_line])
        self.amount_total = taxes_amount + base_amount
        cre_in_invoice = '01'
        cre_out_invoice = '01'
        self.fiscal_position = FiscalPosition(
            name=u'Régimen Islas Canarias', cre_in_invoice=cre_in_invoice,
            cre_out_invoice=cre_out_invoice
        )

    def get_in_invoice(self):
        journal = Journal(name='Factura de Energía Recibida')

        invoice = Invoice(
            type='in_invoice',
            journal_id=journal,
            rectificative_type='N',
            number='FRecib}'.format(self.invoice_number),
            partner_id=self.partner_invoice,
            company_id=self.company,
            amount_total=self.amount_total,
            period_id=self.period,
            date_invoice=self.date_invoice,
            tax_line=self.tax_line,
            invoice_line=self.invoice_line,
            sii_sent=self.sii_sent,
            fiscal_position=self.fiscal_position
        )
        return invoice

    def get_out_invoice(self):
        journal = Journal(name='Factura de Energía Emitida')

        invoice = Invoice(
            type='out_invoice',
            journal_id=journal,
            rectificative_type='N',
            number='FEmit}'.format(self.invoice_number),
            partner_id=self.partner_invoice,
            company_id=self.company,
            amount_total=self.amount_total,
            period_id=self.period,
            date_invoice=self.date_invoice,
            tax_line=self.tax_line,
            invoice_line=self.invoice_line,
            sii_sent=self.sii_sent,
            fiscal_position=self.fiscal_position
        )
        return invoice

    def get_in_refund_invoice(self):
        journal = Journal(name='Factura de Energía Rectificativa Recibida')

        invoice = Invoice(
            type='in_refund',
            journal_id=journal,
            rectificative_type='R',
            number='FRectRecib}'.format(self.invoice_number),
            partner_id=self.partner_invoice,
            company_id=self.company,
            amount_total=self.amount_total,
            period_id=self.period,
            date_invoice=self.date_invoice,
            tax_line=self.tax_line,
            invoice_line=self.invoice_line,
            sii_sent=self.sii_sent,
            fiscal_position=self.fiscal_position
        )
        return invoice

    def get_out_refund_invoice(self):
        journal = Journal(name='Factura de Energía Rectificativa Emitida')

        invoice = Invoice(
            type='out_refund',
            journal_id=journal,
            rectificative_type='R',
            number='FRectEmit{}'.format(self.invoice_number),
            partner_id=self.partner_invoice,
            company_id=self.company,
            amount_total=self.amount_total,
            period_id=self.period,
            date_invoice=self.date_invoice,
            tax_line=self.tax_line,
            invoice_line=self.invoice_line,
            sii_sent=self.sii_sent,
            fiscal_position=self.fiscal_position
        )
        return invoice
<|endoftext|>


<commit_before># This file is part of wger Workout Manager.
#
# wger Workout Manager is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# wger Workout Manager is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License

from django.core.cache import cache
from django.core.urlresolvers import reverse

from wger.exercises.models import ExerciseCategory
from wger.utils.cache import get_template_cache_name

from wger.manager.tests.testcase import WorkoutManagerDeleteTestCase
from wger.manager.tests.testcase import WorkoutManagerTestCase
from wger.manager.tests.testcase import WorkoutManagerEditTestCase
from wger.manager.tests.testcase import WorkoutManagerAddTestCase
from wger.manager.tests.testcase import ApiBaseResourceTestCase

class DeleteExerciseCategoryTestCase(WorkoutManagerDeleteTestCase):
    '''
    Exercise category delete test case
    '''

    object_class = ExerciseCategory
    url = 'exercisecategory-delete'
    pk = 4
    user_success = 'admin'
    user_fail = 'test'

class EditExerciseCategoryTestCase(WorkoutManagerEditTestCase):
    '''
    Tests editing an exercise category
    '''

    object_class = ExerciseCategory
    url = 'exercisecategory-edit'
    pk = 3
    data = {'name': 'A different name'}

class AddExerciseCategoryTestCase(WorkoutManagerAddTestCase):
    '''
    Tests adding an exercise category
    '''

    object_class = ExerciseCategory
    url = 'exercisecategory-add'
    pk = 5
    data = {'name': 'A new category'}

class ExerciseCategoryCacheTestCase(WorkoutManagerTestCase):
    '''
    Cache test case
    '''

    def test_overview_cache_update(self):
        '''
        Test that the template cache for the overview is correctly reseted when
        performing certain operations
        '''

        self.client.get(reverse('exercise-overview'))
        self.client.get(reverse('exercise-view', kwargs={'id': 2}))

        old_exercise_overview = cache.get(get_template_cache_name('exercise-overview', 2))
        old_exercise_overview_mobile = cache.get(get_template_cache_name('exercise-overview-mobile',
                                                                         2))
        old_exercise_overview_search = cache.get(get_template_cache_name('exercise-overview-search',
                                                                         2))

        category = ExerciseCategory.objects.get(pk=2)
        category.name = 'Cool category'
        category.save()

        self.assertFalse(cache.get(get_template_cache_name('exercise-overview', 2)))
        self.assertFalse(cache.get(get_template_cache_name('exercise-overview-mobile', 2)))
        self.assertFalse(cache.get(get_template_cache_name('exercise-overview-search', 2)))

        self.client.get(reverse('exercise-overview'))
        self.client.get(reverse('muscle-overview'))
        self.client.get(reverse('exercise-view', kwargs={'id': 2}))

        new_exercise_overview = cache.get(get_template_cache_name('exercise-overview', 2))
        new_exercise_overview_mobile = cache.get(get_template_cache_name('exercise-overview-mobile',
                                                                         2))
        new_exercise_overview_search = cache.get(get_template_cache_name('exercise-overview-search',
                                                                         2))

        if not self.is_mobile:
            self.assertNotEqual(old_exercise_overview, new_exercise_overview)
        else:
            self.assertNotEqual(old_exercise_overview_mobile, new_exercise_overview_mobile)
            self.assertNotEqual(old_exercise_overview_search, new_exercise_overview_search)

class ExerciseCategoryApiTestCase(ApiBaseResourceTestCase):
    '''
    Tests the exercise category overview resource
    '''
    resource = 'exercisecategory'
    user = None
    resource_updatable = False

class ExerciseCategoryDetailApiTestCase(ApiBaseResourceTestCase):
    '''
    Tests accessing a specific exercise category
    '''
    resource = 'exercisecategory/2'
    user = None
    resource_updatable = False
<commit_msg>Update category test<commit_after># This file is part of wger Workout Manager.
#
# wger Workout Manager is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# wger Workout Manager is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License

from django.core.cache import cache
from django.core.urlresolvers import reverse

from wger.exercises.models import ExerciseCategory
from wger.utils.cache import get_template_cache_name

from wger.manager.tests.testcase import WorkoutManagerDeleteTestCase
from wger.manager.tests.testcase import WorkoutManagerTestCase
from wger.manager.tests.testcase import WorkoutManagerEditTestCase
from wger.manager.tests.testcase import WorkoutManagerAddTestCase
from wger.manager.tests.testcase import ApiBaseResourceTestCase

class DeleteExerciseCategoryTestCase(WorkoutManagerDeleteTestCase):
    '''
    Exercise category delete test case
    '''

    object_class = ExerciseCategory
    url = 'exercisecategory-delete'
    pk = 4
    user_success = 'admin'
    user_fail = 'test'

class EditExerciseCategoryTestCase(WorkoutManagerEditTestCase):
    '''
    Tests editing an exercise category
    '''

    object_class = ExerciseCategory
    url = 'exercisecategory-edit'
    pk = 3
    data = {'name': 'A different name'}

class AddExerciseCategoryTestCase(WorkoutManagerAddTestCase):
    '''
    Tests adding an exercise category
    '''

    object_class = ExerciseCategory
    url = 'exercisecategory-add'
    pk = 5
    data = {'name': 'A new category'}

class ExerciseCategoryCacheTestCase(WorkoutManagerTestCase):
    '''
    Cache test case
    '''

    def test_overview_cache_update(self):
        '''
        Test that the template cache for the overview is correctly reseted when
        performing certain operations
        '''

        self.client.get(reverse('exercise-overview'))
        self.client.get(reverse('exercise-view', kwargs={'id': 2}))

        old_exercise_overview = cache.get(get_template_cache_name('exercise-overview', 2))
        old_exercise_overview_mobile = cache.get(get_template_cache_name('exercise-overview-mobile',
                                                                         2))

        category = ExerciseCategory.objects.get(pk=2)
        category.name = 'Cool category'
        category.save()

        self.assertFalse(cache.get(get_template_cache_name('exercise-overview', 2)))
        self.assertFalse(cache.get(get_template_cache_name('exercise-overview-mobile', 2)))
        self.assertFalse(cache.get(get_template_cache_name('exercise-overview-search', 2)))

        self.client.get(reverse('exercise-overview'))
        self.client.get(reverse('muscle-overview'))
        self.client.get(reverse('exercise-view', kwargs={'id': 2}))

        new_exercise_overview = cache.get(get_template_cache_name('exercise-overview', 2))
        new_exercise_overview_mobile = cache.get(get_template_cache_name('exercise-overview-mobile',
                                                                         2))

        if not self.is_mobile:
            self.assertNotEqual(old_exercise_overview, new_exercise_overview)
        else:
            self.assertNotEqual(old_exercise_overview_mobile, new_exercise_overview_mobile)

class ExerciseCategoryApiTestCase(ApiBaseResourceTestCase):
    '''
    Tests the exercise category overview resource
    '''
    resource = 'exercisecategory'
    user = None
    resource_updatable = False

class ExerciseCategoryDetailApiTestCase(ApiBaseResourceTestCase):
    '''
    Tests accessing a specific exercise category
    '''
    resource = 'exercisecategory/2'
    user = None
    resource_updatable = False
<|endoftext|>


<commit_before>
class Parser():
    sentences = []

    def get_next(self):
        for sentence in self.sentences:
            yield sentence

    def __len__(self):
        return len(self.sentences)

class Sentence():
    def __init__(self, text, char):
        self.text = text
        self.char = char

class ProgressBar():
    def __init__(self, length, name="Progress", width=50):
        self.bar = "[" + " "*width + "] 0%"
        self.value = 0
        self.name = name
        self.print_name = name + ":" + " "*8
        self.length = length
        self.width = width

    def update(self, new_length=None):
        if not new_length:
            new_length = self.value + 1

        self.value = new_length

        percent = int(100 * new_length / self.length)
        marked = int(percent * self.width / 100)
        self.bar = self.print_name
        self.bar += "[" + "=" * marked + " " * (self.width - marked) + "] "
        self.bar += str(percent) + "%"

        print("\r" + self.bar, end="")

<commit_msg>handle overflow in progress bar<commit_after>
class Parser():
    sentences = []

    def get_next(self):
        for sentence in self.sentences:
            yield sentence

    def __len__(self):
        return len(self.sentences)

class Sentence():
    def __init__(self, text, char):
        self.text = text
        self.char = char

class ProgressBar():
    def __init__(self, length, name="Progress", width=50):
        self.bar = "[" + " "*width + "] 0%"
        self.value = 0
        self.name = name
        self.print_name = name + ":" + " "*8
        self.length = length
        self.width = width

    def update(self, new_length=None):
        if not new_length:
            new_length = self.value + 1

        if new_length > self.length:
            new_length = self.length

        self.value = new_length

        percent = int(100 * new_length / self.length)
        marked = int(percent * self.width / 100)
        self.bar = self.print_name
        self.bar += "[" + "=" * marked + " " * (self.width - marked) + "] "
        self.bar += str(percent) + "%"

        print("\r" + self.bar, end="")

<|endoftext|>


<commit_before>__title__ = 'Django Spectator'
__version__ = '3.0.0'
__author__ = 'Phil Gyford'
__author_email__ = 'phil@gyford.com'
__license__ = 'MIT'

VERSION = __version__  # synonym
TITLE = __title__  # synonym

<commit_msg>V3.1.0<commit_after>__title__ = 'Django Spectator'
__version__ = '3.1.0'
__author__ = 'Phil Gyford'
__author_email__ = 'phil@gyford.com'
__license__ = 'MIT'

VERSION = __version__  # synonym
TITLE = __title__  # synonym

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from __future__ import absolute_import
import abc
import itertools
import six

import lupa

from splash.exceptions import ScriptError
from splash.lua import parse_error_message, PyResult
from splash.utils import truncated, ensure_tuple

class AsyncCommand(object):
    # Dispatcher should call .bind method to fill these attributes.
    dispatcher = None
    id = None

    def __init__(self, name, kwargs):
        self.name = name
        self.kwargs = kwargs

    def bind(self, dispatcher, id):
        self.dispatcher = dispatcher
        self.id = id

    def return_result(self, *args):
        """ Return result and resume the dispatcher. """
        self.dispatcher.dispatch(self.id, PyResult.return_(*args))

    def raise_error(self, msg):
        self.dispatcher.dispatch(self.id, PyResult.raise_(msg))

    def yield_result(self, *args):
        self.dispatcher.dispatch(self.id, PyResult.yield_(*args))

class BaseScriptRunner(six.with_metaclass(abc.ABCMeta, object)):
    """
    An utility class for running Lua coroutines.
    """
    _START_CMD = '__START__'

    def __init__(self, lua, log, sandboxed):
        """
        :param splash.lua_runtime.SplashLuaRuntime lua: Lua runtime wrapper
        :param log: log function
        :param bool sandboxed: True if the execution should use sandbox
        """
        self.log = log
        self.sandboxed = sandboxed
        self.lua = lua
        self.coro = None
        self.result = None
        self._command_ids = itertools.count()
        self._waiting_for_result_id = None
        self._is_stopped = False
        self._is_first_iter = True

    def start(self, coro_func, coro_args=None):
        """
        Run the script.

        :param callable coro_func: Lua coroutine to start
        :param list coro_args: arguments to pass to coro_func
        """
        self.coro = coro_func(*(coro_args or []))
        self.result = ''
        self._waiting_for_result_id = self._START_CMD
        self.dispatch(self._waiting_for_result_id)

    def stop(self):
        self._is_stopped = True

    @abc.abstractmethod
    def on_result(self, result):
        """ This method is called when the coroutine exits. """
        pass

    @abc.abstractmethod
    def on_async_command(self, cmd):
        """ This method is called when AsyncCommand instance is received. """
        pass

    def on_lua_error(self, lua_exception):
        """
        This method is called when an exception happens in a Lua script.
        It is called with a lupa.LuaError instance and can raise a custom
        ScriptError.
        """
        pass

    def dispatch(self, cmd_id, *args):
        """ Execute the script """
        args = args or ()

        def truncated_repr(x):
            return truncated("{!r}".format(x),
                             max_length=400,
                             msg="...[long arguments truncated]")
        self.log("[lua_runner] dispatch cmd_id={}".format(cmd_id))

        self.log(
            "[lua_runner] arguments are for command %s, waiting for result of %s" % (cmd_id, self._waiting_for_result_id),
            min_level=3,
        )
        if cmd_id != self._waiting_for_result_id:
            self.log("[lua_runner] skipping an out-of-order result {}".format(truncated_repr(args)), min_level=1)
            return

        while True:
            self.log('[lua_runner] entering dispatch/loop body, args={}'.format(truncated_repr(args)))
            try:
                if self._is_first_iter:
                    args = None
                else:
                    is_python_result = (len(args) == 1 and
                                        isinstance(args[0], PyResult))
                    if is_python_result:
                        args = args[0]
                    else:
                        args = PyResult(*args)

                if self._is_stopped:
                    raise StopIteration

                # Got arguments from an async command; send them to coroutine
                # and wait for the next async command.
                self.log("[lua_runner] send %s" % truncated_repr(args))
                as_lua = self.lua.python2lua(args)
                self.log("[lua_runner] send (lua) %s" % truncated_repr(as_lua))

                cmd = self.coro.send(as_lua)  # cmd is a next async command
                if self._is_first_iter:
                    self._is_first_iter = False

                # If cmd is a synchronous result, prepare it to be passed into
                # the next coroutine step.
                args = ensure_tuple(cmd)
                cmd_repr = truncated(repr(cmd), max_length=400, msg='...[long result truncated]')
                self.log("[lua_runner] got {}".format(cmd_repr))
                self._print_instructions_used()

            except StopIteration:
                # "main" coroutine is stopped;
                # previous result is a final result returned from "main"
                self.log("[lua_runner] returning result")
                try:
                    res = self.lua.lua2python(self.result)
                except ValueError as e:
                    # can't convert result to a Python object
                    raise ScriptError({
                        "type": ScriptError.BAD_MAIN_ERROR,
                        "message": "'main' returned bad result. {!s}".format(
                            e.args[0]
                        )
                    })
                except lupa.LuaError as lua_ex:
                    # Error converting result to Python
                    # This may happen e.g. if conversion hit sandbox limits
                    self.log("[lua_runner] caught LuaError %r" % lua_ex)
                    info = parse_error_message(lua_ex.args[0])
                    error = info.get('error', '?')
                    raise ScriptError({
                        "type": ScriptError.LUA_CONVERT_ERROR,
                        "error": error,
                        "message": "Lua error: {!s}".format(error)
                    })

                self._print_instructions_used()
                self.on_result(res)
                return
            except lupa.LuaError as lua_ex:
                # import traceback
                # print(traceback.format_exc())

                # Lua script raised an error
                self._print_instructions_used()
                self.log("[lua_runner] caught LuaError %r" % lua_ex)

                # this can raise a ScriptError
                self.on_lua_error(lua_ex)

                # ScriptError is not raised, construct it ourselves
                info = parse_error_message(lua_ex.args[0])
                info.update({
                    "type": ScriptError.LUA_ERROR,
                    "message": "Lua error: {!s}".format(lua_ex)
                })
                raise ScriptError(info)

            if isinstance(cmd, AsyncCommand):
                cmd.bind(self, next(self._command_ids))
                self.log("[lua_runner] executing {!r}".format(cmd))
                self._waiting_for_result_id = cmd.id
                self.on_async_command(cmd)
                return

            if isinstance(cmd, PyResult):
                self.log("[lua_runner] got result {!r}".format(cmd))
            else:
                self.log("[lua_runner] got non-command")
                self.result = cmd

    def _print_instructions_used(self):
        if self.sandboxed:
            self.log("[lua_runner] instructions used: %d" % self.lua.instruction_count())
<commit_msg>Allow to restart ScriptRunner. Fixes GH-525.<commit_after># -*- coding: utf-8 -*-
from __future__ import absolute_import
import abc
import itertools
import six

import lupa

from splash.exceptions import ScriptError
from splash.lua import parse_error_message, PyResult
from splash.utils import truncated, ensure_tuple

class AsyncCommand(object):
    # Dispatcher should call .bind method to fill these attributes.
    dispatcher = None
    id = None

    def __init__(self, name, kwargs):
        self.name = name
        self.kwargs = kwargs

    def bind(self, dispatcher, id):
        self.dispatcher = dispatcher
        self.id = id

    def return_result(self, *args):
        """ Return result and resume the dispatcher. """
        self.dispatcher.dispatch(self.id, PyResult.return_(*args))

    def raise_error(self, msg):
        self.dispatcher.dispatch(self.id, PyResult.raise_(msg))

    def yield_result(self, *args):
        self.dispatcher.dispatch(self.id, PyResult.yield_(*args))

class BaseScriptRunner(six.with_metaclass(abc.ABCMeta, object)):
    """
    An utility class for running Lua coroutines.
    """
    _START_CMD = '__START__'

    def __init__(self, lua, log, sandboxed):
        """
        :param splash.lua_runtime.SplashLuaRuntime lua: Lua runtime wrapper
        :param log: log function
        :param bool sandboxed: True if the execution should use sandbox
        """
        self.log = log
        self.sandboxed = sandboxed
        self.lua = lua
        self.coro = None
        self.result = None
        self._command_ids = itertools.count()
        self._waiting_for_result_id = None
        self._is_stopped = False
        self._is_first_iter = True

    def start(self, coro_func, coro_args=None):
        """
        Run the script.

        :param callable coro_func: Lua coroutine to start
        :param list coro_args: arguments to pass to coro_func
        """
        self.coro = coro_func(*(coro_args or []))
        self.result = ''
        self._waiting_for_result_id = self._START_CMD
        self._is_first_iter = True
        self._is_stopped = False
        self.dispatch(self._waiting_for_result_id)

    def stop(self):
        self._is_stopped = True

    @abc.abstractmethod
    def on_result(self, result):
        """ This method is called when the coroutine exits. """
        pass

    @abc.abstractmethod
    def on_async_command(self, cmd):
        """ This method is called when AsyncCommand instance is received. """
        pass

    def on_lua_error(self, lua_exception):
        """
        This method is called when an exception happens in a Lua script.
        It is called with a lupa.LuaError instance and can raise a custom
        ScriptError.
        """
        pass

    def dispatch(self, cmd_id, *args):
        """ Execute the script """
        args = args or ()

        def truncated_repr(x):
            return truncated("{!r}".format(x),
                             max_length=400,
                             msg="...[long arguments truncated]")
        self.log("[lua_runner] dispatch cmd_id={}".format(cmd_id))

        self.log(
            "[lua_runner] arguments are for command %s, waiting for result of %s" % (cmd_id, self._waiting_for_result_id),
            min_level=3,
        )
        if cmd_id != self._waiting_for_result_id:
            self.log("[lua_runner] skipping an out-of-order result {}".format(truncated_repr(args)), min_level=1)
            return

        while True:
            self.log('[lua_runner] entering dispatch/loop body, args={}'.format(truncated_repr(args)))
            try:
                if self._is_first_iter:
                    args = None
                else:
                    is_python_result = (len(args) == 1 and
                                        isinstance(args[0], PyResult))
                    if is_python_result:
                        args = args[0]
                    else:
                        args = PyResult(*args)

                if self._is_stopped:
                    raise StopIteration

                # Got arguments from an async command; send them to coroutine
                # and wait for the next async command.
                self.log("[lua_runner] send %s" % truncated_repr(args))
                as_lua = self.lua.python2lua(args)
                self.log("[lua_runner] send (lua) %s" % truncated_repr(as_lua))

                cmd = self.coro.send(as_lua)  # cmd is a next async command
                if self._is_first_iter:
                    self._is_first_iter = False

                # If cmd is a synchronous result, prepare it to be passed into
                # the next coroutine step.
                args = ensure_tuple(cmd)
                cmd_repr = truncated(repr(cmd), max_length=400, msg='...[long result truncated]')
                self.log("[lua_runner] got {}".format(cmd_repr))
                self._print_instructions_used()

            except StopIteration:
                # "main" coroutine is stopped;
                # previous result is a final result returned from "main"
                self.log("[lua_runner] returning result")
                try:
                    res = self.lua.lua2python(self.result)
                except ValueError as e:
                    # can't convert result to a Python object
                    raise ScriptError({
                        "type": ScriptError.BAD_MAIN_ERROR,
                        "message": "'main' returned bad result. {!s}".format(
                            e.args[0]
                        )
                    })
                except lupa.LuaError as lua_ex:
                    # Error converting result to Python
                    # This may happen e.g. if conversion hit sandbox limits
                    self.log("[lua_runner] caught LuaError %r" % lua_ex)
                    info = parse_error_message(lua_ex.args[0])
                    error = info.get('error', '?')
                    raise ScriptError({
                        "type": ScriptError.LUA_CONVERT_ERROR,
                        "error": error,
                        "message": "Lua error: {!s}".format(error)
                    })

                self._print_instructions_used()
                self.on_result(res)
                return
            except lupa.LuaError as lua_ex:
                # import traceback
                # print(traceback.format_exc())

                # Lua script raised an error
                self._print_instructions_used()
                self.log("[lua_runner] caught LuaError %r" % lua_ex)

                # this can raise a ScriptError
                self.on_lua_error(lua_ex)

                # ScriptError is not raised, construct it ourselves
                info = parse_error_message(lua_ex.args[0])
                info.update({
                    "type": ScriptError.LUA_ERROR,
                    "message": "Lua error: {!s}".format(lua_ex)
                })
                raise ScriptError(info)

            if isinstance(cmd, AsyncCommand):
                cmd.bind(self, next(self._command_ids))
                self.log("[lua_runner] executing {!r}".format(cmd))
                self._waiting_for_result_id = cmd.id
                self.on_async_command(cmd)
                return

            if isinstance(cmd, PyResult):
                self.log("[lua_runner] got result {!r}".format(cmd))
            else:
                self.log("[lua_runner] got non-command")
                self.result = cmd

    def _print_instructions_used(self):
        if self.sandboxed:
            self.log("[lua_runner] instructions used: %d" % self.lua.instruction_count())
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
import requests

class SpeedCurveSession(requests.Session):

    def __init__(self, api_key=None):
        if api_key is None:
            raise Exception("API Key Required")

        self.api_key = api_key
        self.basic_authentication = (str(self.api_key), 'x')
        super(SpeedCurveSession, self).__init__()
        self.headers.update({
            'Content-Type': 'application/json'
        })
        self.base_url = 'https://api.speedcurve.com/v1'

    def build_url(self, *args, **kwargs):
        parts = [kwargs.get('base_url') or self.base_url]
        parts.extend(args)
        url = '/'.join(parts)
        return url

    def get(self, *args, **kwargs):
        kwargs['auth'] = self.basic_authentication
        return super(SpeedCurveSession, self).get(*args, **kwargs)
<commit_msg>Added post method to session<commit_after># -*- coding: utf-8 -*-
import requests

class SpeedCurveSession(requests.Session):

    def __init__(self, api_key=None):
        if api_key is None:
            raise Exception("API Key Required")

        self.api_key = api_key
        self.basic_authentication = (str(self.api_key), 'x')
        super(SpeedCurveSession, self).__init__()
        self.headers.update({
            'Content-Type': 'application/json'
        })
        self.base_url = 'https://api.speedcurve.com/v1'

    def build_url(self, *args, **kwargs):
        parts = [kwargs.get('base_url') or self.base_url]
        parts.extend(args)
        url = '/'.join(parts)
        return url

    def get(self, *args, **kwargs):
        kwargs['auth'] = self.basic_authentication
        return super(SpeedCurveSession, self).get(*args, **kwargs)

    def post(self, *args, **kwargs):
        kwargs['auth'] = self.basic_authentication
        return super(SpeedCurveSession, self).post(*args, **kwargs)
<|endoftext|>


<commit_before><commit_msg>flow-accounting: T4437: also install rule to IPv6 VYOS_CT_PREROUTING_HOOK<commit_after><|endoftext|>


<commit_before>"""
URL generation functions.

All functions return a tuple of `method (str), url (str), params (dict), payload (dict)`
in that order (`params` and `payload` are optional).
ex. ('GET', '/me/tracks', {'limit': 40})

All functions defined here are decorated to convert the return value to a dict with keys {method, url, params, payload}.
"""
from decorator import decorator as _deco
import sys as _sys
import inspect as _inspect

def album(id, market=None):
    return 'GET', '/albums/{}'.format(id), {'market': market}

def albums(ids, market=None):
    ids = ','.join(ids)
    return 'GET', '/albums', dict(ids=ids, market=market)

def album_tracks(id, limit=50, offset=0, market=None):
    return 'GET', '/albums/{}/tracks'.format(id), dict(limit=limit, offset=offset, market=market)

def artist(id):
    return 'GET', '/artists/{}'.format(id),

def artists(ids):
    ids = ','.join(ids)
    return 'GET', '/artists', {'ids': ids}

def artist_albums(id, album_type=None, market=None, limit=50, offset=0):
    return (
        'GET', '/artists/{}/albums'.format(id),
        dict(album_type=album_type, market=market, limit=limit, offset=offset)
    )

def track(id, market=None):
    return 'GET', '/tracks/{}'.format(id), {'market': market}

def track_audio_features(track_id):
    return 'GET', '/audio-features/{}'.format(track_id)

def tracks(ids, market=None):
    return 'GET', '/tracks', {'market': market, 'ids': ','.join(ids)}

def tracks_audio_features(track_ids):
    return 'GET', '/audio-features', dict(ids=track_ids)

def artist_top_tracks(id, country):
    return 'GET', '/artists/{}/top-tracks'.format(id), dict(country=country)

def artist_related_artists(id):
    return 'GET', '/artists/{}/related-artists'.format(id),

def browse_featured_playlists(locale=None, country=None, timestamp=None, limit=50, offset=0):
    return (
        'GET', '/browse/features-playlists',
        dict(locale=locale, country=country,
             timestamp=timestamp, limit=limit, offset=offset)
    )

def browse_new_releases(country=None, limit=50, offset=0):
    return (
        'GET', '/browse/new-releases',
        dict(country=country, limit=limit, offset=offset)
    )

def browse_categories(locale=None, country=None, limit=50, offset=0):
    return (
        'GET', '/browse/categories',
        dict(locale=locale, country=country, limit=limit, offset=offset)
    )

def browse_category(id, locale=None, country=None):
    return 'GET', '/browse/categories/{}'.format(id), dict(locale=locale, country=country)

def browse_category_playlists(id, country=None, limit=50, offset=0):
    return (
        'GET', '/browse/categories/{}/playlists'.format(id),
        dict(country=country, limit=limit, offset=offset)
    )

def recommendations(seed_artists=None, seed_tracks=None, seed_genres=None, market=None, limit=100, **tuneables):
    params = {'limit': limit}
    if seed_artists:
        params['seed_artists'] = ','.join(seed_artists)
    if seed_tracks:
        params['seed_tracks'] = ','.join(seed_tracks)
    if seed_genres:
        params['seed_genres'] = ','.join(seed_genres)
    if market:
        params['market'] = market
    params.update(tuneables)
    return 'GET', '/recommendations', params

def me():
    """
    Current user's profile
    """
    return 'GET', '/me'

def me_following(type='artist', limit=50, after=None):
    """
    Followed artists of current user.
    """
    return 'GET', '/me/following', dict(type=type, limit=limit, after=after)

def me_follow(type, ids):
    """
    Follow artists or users. Max 50 ids
    """
    return 'PUT', '/me/following', {'type': type}, {'ids': ids}

def me_unfollow(type, ids):
    return 'DELETE', '/me/following', {'type': type}, {'ids': ids}

def me_following_contains(type, ids):
    return 'GET', '/me/following/contains', {'type': type, 'ids': ids},

def me_follow_playlist(owner_id, playlist_id, public=True):
    return (
        'PUT', '/users/{}/playlists/{}/followers'.format(owner_id, playlist_id),
        {'public': public}
    )

def me_unfollow_playlist(owner_id, playlist_id):
    return 'DELETE', '/users/{}/playlists/{}/followers'.format(owner_id, playlist_id),

def users_following_contains_playlists(owner_id, playlist_id, user_ids):
    return (
        'GET', '/users/{}/playlists/{}/followers/contains'.format(
            owner_id, playlist_id),
        {'ids': ','.join(user_ids)}
    )

def me_tracks_add(ids):
    return 'PUT', '/me/tracks', {'ids': ','.join(ids)}

def me_tracks(limit=50, offset=0, market=None):
    return 'GET', '/me/tracks', dict(limit=limit, offset=offset, market=market)

def me_tracks_remove(ids):
    return 'DELETE', '/me/tracks', dict(ids=ids)

def me_tracks_contains(ids):
    return 'GET', '/me/tracks/contains', dict(ids=ids)

def me_albums_add(ids):
    return 'PUT', '/me/albums', {'ids': ','.join(ids)}

def me_albums(limit=50, offset=0, market=None):
    return 'GET', '/me/albums', dict(limit=limit, offset=offset, market=market)

def me_albums_remove(ids):
    return 'DELETE', '/me/albums', dict(ids=ids)

def me_albums_contains(ids):
    return 'GET', '/me/albums/contains', dict(ids=ids)

def me_top(type, limit=50, offset=0, time_range='medium_term'):
    return (
        'GET', '/me/top/{}'.format(type),
        dict(limit=limit, offset=offset, time_range=time_range)
    )

def me_player_recently_played(limit=50, before=None, after=None):
    return (
        'GET', '/me/player/recently-played',
        dict(limit=limit, before=before, after=after)
    )

# TODO: /player endpoints

def user_playlists(user_id, limit=50, offset=0):
    return 'GET', '/users/{}/playlists'.format(user_id), dict(limit=limit, offset=offset)

def me_playlists(limit=50, offset=0):
    return 'GET', '/me/playlists', dict(limit=limit, offset=offset)

def user_playlist(user_id, playlist_id, fields=None, market=None):
    return (
        'GET', '/users/{}/playlists/{}'.format(user_id, playlist_id),
        dict(fields=fields, market=market)
    )

def user_playlist_tracks(user_id, playlist_id, fields=None, limit=100, offset=0, market=None):
    return (
        'GET', '/users/{}/playlists/{}/tracks'.format(user_id, playlist_id),
        dict(fields=fields, limit=limit, offset=offset, market=market)
    )

def user_playlist_create(user_id, name, public=True, collaborative=False, description=None):
    return (
        'POST', '/users/{}/playlists'.format(user_id), {},
        dict(name=name, public=public,
             collaborative=collaborative, description=description)
    )

def user_playlist_tracks_add(user_id, playlist_id, track_uris, position=None):
    payload = {'uris': track_uris}
    if position is not None:
        payload['position'] = position
    return (
        'POST', '/users/{}/playlists/{}/tracks'.format(user_id, playlist_id), {}, payload
    )

def user_playlist_tracks_remove_all_occurences(user_id, playlist_id, track_uris, snapshot_id=None):
    payload = {'tracks': [{'uri': uri} for uri in track_uris]}
    if snapshot_id:
        payload['snapshot_id'] = snapshot_id
    return (
        'DELETE', '/users/{}/playlists/{}/tracks'.format(user_id, playlist_id), {}, payload
    )

def user_playlist_tracks_remove_specific_occurences(user_id, playlist_id, tracks, snapshot_id=None):
    """
    tracks: list of {'uri': 'something', positions: [0,4,6]} objects
    """
    payload = {'tracks': tracks}
    if snapshot_id:
        payload['snapshot_id'] = snapshot_id
    return (
        'DELETE', '/users/{}/playlists/{}/tracks'.format(user_id, playlist_id), {}, payload
    )

def search(q, type, limit=50, offset=0, market=None):
    return 'GET', '/search', dict(q=q, type=type, limit=limit, offset=offset, market=market)

def me_player_currently_playing(market=None):
    return 'GET', '/me/player/currently-playing', {'market': market}

def me_player_play(device_id=None, context_uri=None, uris=None, offset=None):
    return (
        'PUT', '/me/player/play', {'device_id': device_id},
        {'context_uri': context_uri, 'uris': uris, 'offset': offset}
    )

def me_player_pause(device_id=None):
    return 'PUT', '/me/player/pause', {'device_id': device_id}

def me_player_next(device_id=None):
    return 'POST', '/me/player/next', {'device_id': device_id}

def me_player_previous(device_id=None):
    return 'POST', '/me/player/previous', {'device_id': device_id}

def me_player_volume(volume_percent, device_id=None):
    return 'PUT', '/me/player/volume', {
        'volume_percent': volume_percent, 'device_id': device_id
    }

@_deco
def _clear_none_params(function, *args, **kwargs):
    """
    Decorator to clear any None value query and payload params from
    endpoint function results.
    """
    result = function(*args, **kwargs)
    if 'params' in result:
        result['params'] = {k: v for k,
                            v in result['params'].items() if v is not None}
    if 'payload' in result:
        result['payload'] = {k: v for k,
                             v in result['payload'].items() if v is not None}
    return result

@_deco
def _tuple_to_dict(function, *args, **kwargs):
    rtuple = function(*args, **kwargs)
    result = {}
    keys = ('method', 'url', 'params', 'payload')
    for i, value in enumerate(rtuple):
        result[keys[i]] = value
    return result

# Apply _clear_none_params decorator to all endpoint functions in this module
_current_module = _sys.modules[__name__]

def _is_resource(obj):
    return (
        _inspect.isfunction(obj)
        and obj.__module__ == __name__
        and not obj.__name__.startswith('_')
    )

_endpoints = {}

for name, function in _inspect.getmembers(_current_module, _is_resource):
    function = _clear_none_params(_tuple_to_dict(function))
    _endpoints[name] = function
    setattr(_current_module, name, function)
<commit_msg>fix audio features endpoint, str join track ids<commit_after>"""
URL generation functions.

All functions return a tuple of `method (str), url (str), params (dict), payload (dict)`
in that order (`params` and `payload` are optional).
ex. ('GET', '/me/tracks', {'limit': 40})

All functions defined here are decorated to convert the return value to a dict with keys {method, url, params, payload}.
"""
from decorator import decorator as _deco
import sys as _sys
import inspect as _inspect

def album(id, market=None):
    return 'GET', '/albums/{}'.format(id), {'market': market}

def albums(ids, market=None):
    ids = ','.join(ids)
    return 'GET', '/albums', dict(ids=ids, market=market)

def album_tracks(id, limit=50, offset=0, market=None):
    return 'GET', '/albums/{}/tracks'.format(id), dict(limit=limit, offset=offset, market=market)

def artist(id):
    return 'GET', '/artists/{}'.format(id),

def artists(ids):
    ids = ','.join(ids)
    return 'GET', '/artists', {'ids': ids}

def artist_albums(id, album_type=None, market=None, limit=50, offset=0):
    return (
        'GET', '/artists/{}/albums'.format(id),
        dict(album_type=album_type, market=market, limit=limit, offset=offset)
    )

def track(id, market=None):
    return 'GET', '/tracks/{}'.format(id), {'market': market}

def track_audio_features(track_id):
    return 'GET', '/audio-features/{}'.format(track_id)

def tracks(ids, market=None):
    return 'GET', '/tracks', {'market': market, 'ids': ','.join(ids)}

def tracks_audio_features(track_ids):
    return 'GET', '/audio-features', dict(ids=','.join(track_ids))

def artist_top_tracks(id, country):
    return 'GET', '/artists/{}/top-tracks'.format(id), dict(country=country)

def artist_related_artists(id):
    return 'GET', '/artists/{}/related-artists'.format(id),

def browse_featured_playlists(locale=None, country=None, timestamp=None, limit=50, offset=0):
    return (
        'GET', '/browse/features-playlists',
        dict(locale=locale, country=country,
             timestamp=timestamp, limit=limit, offset=offset)
    )

def browse_new_releases(country=None, limit=50, offset=0):
    return (
        'GET', '/browse/new-releases',
        dict(country=country, limit=limit, offset=offset)
    )

def browse_categories(locale=None, country=None, limit=50, offset=0):
    return (
        'GET', '/browse/categories',
        dict(locale=locale, country=country, limit=limit, offset=offset)
    )

def browse_category(id, locale=None, country=None):
    return 'GET', '/browse/categories/{}'.format(id), dict(locale=locale, country=country)

def browse_category_playlists(id, country=None, limit=50, offset=0):
    return (
        'GET', '/browse/categories/{}/playlists'.format(id),
        dict(country=country, limit=limit, offset=offset)
    )

def recommendations(seed_artists=None, seed_tracks=None, seed_genres=None, market=None, limit=100, **tuneables):
    params = {'limit': limit}
    if seed_artists:
        params['seed_artists'] = ','.join(seed_artists)
    if seed_tracks:
        params['seed_tracks'] = ','.join(seed_tracks)
    if seed_genres:
        params['seed_genres'] = ','.join(seed_genres)
    if market:
        params['market'] = market
    params.update(tuneables)
    return 'GET', '/recommendations', params

def me():
    """
    Current user's profile
    """
    return 'GET', '/me'

def me_following(type='artist', limit=50, after=None):
    """
    Followed artists of current user.
    """
    return 'GET', '/me/following', dict(type=type, limit=limit, after=after)

def me_follow(type, ids):
    """
    Follow artists or users. Max 50 ids
    """
    return 'PUT', '/me/following', {'type': type}, {'ids': ids}

def me_unfollow(type, ids):
    return 'DELETE', '/me/following', {'type': type}, {'ids': ids}

def me_following_contains(type, ids):
    return 'GET', '/me/following/contains', {'type': type, 'ids': ids},

def me_follow_playlist(owner_id, playlist_id, public=True):
    return (
        'PUT', '/users/{}/playlists/{}/followers'.format(owner_id, playlist_id),
        {'public': public}
    )

def me_unfollow_playlist(owner_id, playlist_id):
    return 'DELETE', '/users/{}/playlists/{}/followers'.format(owner_id, playlist_id),

def users_following_contains_playlists(owner_id, playlist_id, user_ids):
    return (
        'GET', '/users/{}/playlists/{}/followers/contains'.format(
            owner_id, playlist_id),
        {'ids': ','.join(user_ids)}
    )

def me_tracks_add(ids):
    return 'PUT', '/me/tracks', {'ids': ','.join(ids)}

def me_tracks(limit=50, offset=0, market=None):
    return 'GET', '/me/tracks', dict(limit=limit, offset=offset, market=market)

def me_tracks_remove(ids):
    return 'DELETE', '/me/tracks', dict(ids=ids)

def me_tracks_contains(ids):
    return 'GET', '/me/tracks/contains', dict(ids=ids)

def me_albums_add(ids):
    return 'PUT', '/me/albums', {'ids': ','.join(ids)}

def me_albums(limit=50, offset=0, market=None):
    return 'GET', '/me/albums', dict(limit=limit, offset=offset, market=market)

def me_albums_remove(ids):
    return 'DELETE', '/me/albums', dict(ids=ids)

def me_albums_contains(ids):
    return 'GET', '/me/albums/contains', dict(ids=ids)

def me_top(type, limit=50, offset=0, time_range='medium_term'):
    return (
        'GET', '/me/top/{}'.format(type),
        dict(limit=limit, offset=offset, time_range=time_range)
    )

def me_player_recently_played(limit=50, before=None, after=None):
    return (
        'GET', '/me/player/recently-played',
        dict(limit=limit, before=before, after=after)
    )

# TODO: /player endpoints

def user_playlists(user_id, limit=50, offset=0):
    return 'GET', '/users/{}/playlists'.format(user_id), dict(limit=limit, offset=offset)

def me_playlists(limit=50, offset=0):
    return 'GET', '/me/playlists', dict(limit=limit, offset=offset)

def user_playlist(user_id, playlist_id, fields=None, market=None):
    return (
        'GET', '/users/{}/playlists/{}'.format(user_id, playlist_id),
        dict(fields=fields, market=market)
    )

def user_playlist_tracks(user_id, playlist_id, fields=None, limit=100, offset=0, market=None):
    return (
        'GET', '/users/{}/playlists/{}/tracks'.format(user_id, playlist_id),
        dict(fields=fields, limit=limit, offset=offset, market=market)
    )

def user_playlist_create(user_id, name, public=True, collaborative=False, description=None):
    return (
        'POST', '/users/{}/playlists'.format(user_id), {},
        dict(name=name, public=public,
             collaborative=collaborative, description=description)
    )

def user_playlist_tracks_add(user_id, playlist_id, track_uris, position=None):
    payload = {'uris': track_uris}
    if position is not None:
        payload['position'] = position
    return (
        'POST', '/users/{}/playlists/{}/tracks'.format(user_id, playlist_id), {}, payload
    )

def user_playlist_tracks_remove_all_occurences(user_id, playlist_id, track_uris, snapshot_id=None):
    payload = {'tracks': [{'uri': uri} for uri in track_uris]}
    if snapshot_id:
        payload['snapshot_id'] = snapshot_id
    return (
        'DELETE', '/users/{}/playlists/{}/tracks'.format(user_id, playlist_id), {}, payload
    )

def user_playlist_tracks_remove_specific_occurences(user_id, playlist_id, tracks, snapshot_id=None):
    """
    tracks: list of {'uri': 'something', positions: [0,4,6]} objects
    """
    payload = {'tracks': tracks}
    if snapshot_id:
        payload['snapshot_id'] = snapshot_id
    return (
        'DELETE', '/users/{}/playlists/{}/tracks'.format(user_id, playlist_id), {}, payload
    )

def search(q, type, limit=50, offset=0, market=None):
    return 'GET', '/search', dict(q=q, type=type, limit=limit, offset=offset, market=market)

def me_player_currently_playing(market=None):
    return 'GET', '/me/player/currently-playing', {'market': market}

def me_player_play(device_id=None, context_uri=None, uris=None, offset=None):
    return (
        'PUT', '/me/player/play', {'device_id': device_id},
        {'context_uri': context_uri, 'uris': uris, 'offset': offset}
    )

def me_player_pause(device_id=None):
    return 'PUT', '/me/player/pause', {'device_id': device_id}

def me_player_next(device_id=None):
    return 'POST', '/me/player/next', {'device_id': device_id}

def me_player_previous(device_id=None):
    return 'POST', '/me/player/previous', {'device_id': device_id}

def me_player_volume(volume_percent, device_id=None):
    return 'PUT', '/me/player/volume', {
        'volume_percent': volume_percent, 'device_id': device_id
    }

@_deco
def _clear_none_params(function, *args, **kwargs):
    """
    Decorator to clear any None value query and payload params from
    endpoint function results.
    """
    result = function(*args, **kwargs)
    if 'params' in result:
        result['params'] = {k: v for k,
                            v in result['params'].items() if v is not None}
    if 'payload' in result:
        result['payload'] = {k: v for k,
                             v in result['payload'].items() if v is not None}
    return result

@_deco
def _tuple_to_dict(function, *args, **kwargs):
    rtuple = function(*args, **kwargs)
    result = {}
    keys = ('method', 'url', 'params', 'payload')
    for i, value in enumerate(rtuple):
        result[keys[i]] = value
    return result

# Apply _clear_none_params decorator to all endpoint functions in this module
_current_module = _sys.modules[__name__]

def _is_resource(obj):
    return (
        _inspect.isfunction(obj)
        and obj.__module__ == __name__
        and not obj.__name__.startswith('_')
    )

_endpoints = {}

for name, function in _inspect.getmembers(_current_module, _is_resource):
    function = _clear_none_params(_tuple_to_dict(function))
    _endpoints[name] = function
    setattr(_current_module, name, function)
<|endoftext|>


<commit_before>
import logging
logging.basicConfig(format='%(levelname)s:%(name)s | %(message)s')
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
#logger.setLevel(logging.DEBUG)

from spimagine.config import config

from spimagine.models.data_model import DataModel,DemoData, SpimData, TiffData, CZIData, TiffFolderData, NumpyData

from spimagine.utils.imgutils import read3dTiff, write3dTiff

from spimagine.gui.volshow import volshow, volfig, qt_exec

from spimagine.gui.mesh import Mesh, SphericalMesh, EllipsoidMesh

from spimagine.utils import *<commit_msg>add __version__ field<commit_after>__version__ = None

try:
    from pkg_resources import get_distribution, DistributionNotFound
    __version__ = get_distribution("spimagine").version
except Exception as e:
    print e

import logging
logging.basicConfig(format='%(levelname)s:%(name)s | %(message)s')
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
#logger.setLevel(logging.DEBUG)

from spimagine.config import config

from spimagine.models.data_model import DataModel,DemoData, SpimData, TiffData, CZIData, TiffFolderData, NumpyData

from spimagine.utils.imgutils import read3dTiff, write3dTiff

from spimagine.gui.volshow import volshow, volfig, qt_exec

from spimagine.gui.mesh import Mesh, SphericalMesh, EllipsoidMesh

from spimagine.utils import *<|endoftext|>