<commit_before>from binstar_client.utils import parse_specs, get_binstar, bool_input,\
    get_config
import tarfile
import json
from warnings import warn
from binstar_client import BinstarError, NotFound, Conflict
from os.path import exists
import sys
import time
import yaml
from os.path import basename
from email.parser import Parser
from os import path
import logging

log = logging.getLogger('binstar.updload')

def detect_yaml_attrs(filename):
    tar = tarfile.open(filename)
    obj = tar.extractfile('info/recipe/meta.yaml')
    attrs = yaml.load(obj)
    try:
        description = attrs['about']['home']
    except KeyError:
        description = None
    try:
        license = attrs['about']['license']
    except KeyError:
        license = None

    return description, license

def detect_pypi_attrs(filename):

    with tarfile.open(filename) as tf:
        pkg_info = next(name for name in tf.getnames() if name.endswith('/PKG-INFO'))
        fd = tf.extractfile(pkg_info)
        attrs = dict(Parser().parse(fd).items())

    name = attrs.pop('Name')
    version = attrs.pop('Version')
    summary = attrs.pop('Summary')
    description = attrs.pop('Description')
    license = attrs.pop('License')
    attrs = {'dist':'sdist'}

    filename = basename(filename)
    return filename, name, version, attrs, summary, description, license

arch_map = {('osx', 'x86_64'):'osx-64',
            ('win', 'x86'):'win-32',
            ('win', 'x86_64'):'win-64',
            ('linux', 'x86'):'linux-32',
            ('linux', 'x86_64'):'linux-64',
           }

def detect_conda_attrs(filename):

    tar = tarfile.open(filename)
    obj = tar.extractfile('info/index.json')
    attrs = json.loads(obj.read())

    description, license = detect_yaml_attrs(filename)
    os_arch = arch_map[(attrs['platform'], attrs['arch'])]
    filename = path.join(os_arch, basename(filename))
    return filename, attrs['name'], attrs['version'], attrs, description, description, license

detectors = {'conda':detect_conda_attrs,
             'pypi': detect_pypi_attrs,
             }

def detect_package_type(filename):

    if filename.endswith('.tar.bz2'):  # Could be a conda package
        try:
            with tarfile.open(filename) as tf:
                tf.getmember('info/index.json')
        except KeyError:
            pass
        else:
            return 'conda'

    if filename.endswith('.tar.gz'):  # Could be a setuptools sdist
        with tarfile.open(filename) as tf:
            if any(name.endswith('/PKG-INFO') for name in tf.getnames()):
                return 'pypi'

    raise BinstarError('Could not autodetect the package type of file %s' % filename)

def create_package(binstar, username, package_name, summary, license, public=True, publish=True):
    binstar.add_package(username, package_name,
                        summary,
                        license,
                        public=public,
                        publish=publish)

def create_release(binstar, username, package_name, version, description, announce=None):
    binstar.add_release(username, package_name, version, [],
                        announce, description)

def create_package_interactive(binstar, username, package_name, public=True, publish=True):

    log.info('\nThe package %s/%s does not exist' % (username, package_name))
    if not bool_input('Would you lke to create it now?'):
        log.info('goodbbye')
        raise SystemExit(-1)

    summary = raw_input('Enter a short description of the package\nsummary: ')
    license = raw_input('Enter the name of the license (default:BSD)\nlicense: ')
    license_url = raw_input('Enter the url of the license (optional)\nlicense url: ')
    public = bool_input('\nDo you want to make this package public?', public)
    if public:
        publish = bool_input('\nDo you want to make publish this package?\n'
                             'When published it will be added to the global public repositories.',
                             public)
    else:
        publish = False

    binstar.add_package(username, package_name,
                    summary,
                    license,
                    license_url,
                    public,
                    public=public,
                    publish=publish)

def create_release_interactive(binstar, username, package_name, version):

    log.info('\nThe release %s/%s/%s does not exist' % (username, package_name, version))
    if not bool_input('Would you like to create it now?'):
        log.info('good-bye')
        raise SystemExit(-1)

    description = raw_input('Enter a short description of the release:\n')
    log.info("\nAnnouncements are emailed to your package followers.")
    make_announcement = bool_input('Would you like to make an announcement to the package followers?', False)
    if make_announcement:
        announce = raw_input('Markdown Announcement:\n')
    else:
        announce = ''

    binstar.add_release(username, package_name, version, [],
                        announce, description)

def upload_print_callback():
    start_time = time.time()
    def callback(curr, total):
        curr_time = time.time()
        time_delta = curr_time - start_time

        remain = total - curr
        if curr and remain:
            eta = 1.0 * time_delta / curr * remain / 60.0
        else:
            eta = 0

        curr_kb = curr // 1024
        total_kb = total // 1024
        perc = 100.0 * curr / total if total else 0

        msg = '\r uploaded %(curr_kb)i of %(total_kb)iKb: %(perc).2f%% ETA: %(eta).1f minutes'
        sys.stderr.write(msg % locals())
        sys.stderr.flush()
        if curr == total:
            sys.stderr.write('\n')

    return callback

def main(args):

    binstar = get_binstar(args)

    if args.user:
        username = args.user
    else:
        user = binstar.user()
        username = user ['login']

    uploaded_packages = []

    for filename in args.files:

        if not exists(filename):
            raise BinstarError('file %s does not exist' % (filename))

        if args.package_type:
            package_type = args.package_type
        else:
            log.info('detecting package type ...')
            sys.stdout.flush()
            package_type = detect_package_type(filename)
            log.info(package_type)

        get_attrs = detectors[package_type]

        if args.metadata:
            attrs = json.loads(args.metadata)
            package_name = args.package
            version = args.version
        else:
            log.info('extracting package attributes for upload ...')
            sys.stdout.flush()
            basefilename, package_name, version, attrs, summary, description, license = get_attrs(filename)
            log.info('done')

        if args.package:
            package_name = args.package

        if args.version:
            version = args.version

        try:
            binstar.package(username, package_name)
        except NotFound:
            if args.mode == 'interactive':
                create_package_interactive(binstar, username, package_name,
                                           public=args.public,
                                           publish=args.publish)
            else:
                create_package(binstar, username, package_name, summary, license,
                               public=args.public,
                               publish=args.publish)

        try:
            binstar.release(username, package_name, version)
        except NotFound:
            if args.mode == 'interactive':
                create_release_interactive(binstar, username, package_name, version)
            else:
                create_release(binstar, username, package_name, version, description)

        with open(filename, 'rb') as fd:
            log.info('\nUploading file %s/%s/%s/%s ... ' % (username, package_name, version, basefilename))
            sys.stdout.flush()
            try:
                binstar.distribution(username, package_name, version, basefilename)
            except NotFound:
                pass
            else:
                if args.mode == 'interactive':
                    if bool_input('Distribution %s already exists. Would you like to replace it?' % (basefilename,)):
                        binstar.remove_dist(username, package_name, version, basefilename)
                    else:
                        log.info('Not replacing distribution %s' % (basefilename,))
                        continue
            try:
                binstar.upload(username, package_name, version, basefilename, fd, package_type, args.description, attrs=attrs,
                           callback=upload_print_callback())
            except Conflict:
                full_name = '%s/%s/%s/%s' % (username, package_name, version, basefilename)
                log.info('Distribution already exists. Please use the -i/--interactive option or `binstar delete %s`' % full_name)
                raise

            uploaded_packages.append(package_name)
            log.info("\n\nUpload(s) Complete\n")

    for package in uploaded_packages:
        log.info("Package located at:\nhttps://binstar.org/%s/%s\n" % (username, package))

def add_parser(subparsers):

    config = get_config()

    parser = subparsers.add_parser('upload',
                                      help='Upload a file to binstar',
                                      description=__doc__)

    parser.add_argument('files', nargs='*', help='Distributions to upload', default=[])

    parser.add_argument('-u', '--user', help='User account, defaults to the current user')
    parser.add_argument('-p', '--package', help='Defaults to the packge name in the uploaded file')
    parser.add_argument('-v', '--version', help='Defaults to the packge version in the uploaded file')
    parser.add_argument('-t', '--package-type', help='Set the package type, defaults to autodetect')
    parser.add_argument('-d', '--description', help='description of the file(s)')
    parser.add_argument('-m', '--metadata', help='json encoded metadata default is to autodetect')

    perms = parser.add_mutually_exclusive_group()
    perms.desciption = 'The package permissions'
    perms.add_argument('--public', action='store_true', default=config.get('public') or config.get('publish', True),
                       help='Set the permissions of the package to public (if it does not exist) (default %(default)s)')
    perms.add_argument('--private', action='store_false', dest='public',
                       help='Set the permissions of the package to private (if it does not exist)')
    perms.add_argument('--publish', action='store_true', default=config.get('publish', True),
                       help=('Set the permissions of the package to public and '
                             'publish this package to the global public repositories - if it does not exist. '
                            '(default %(default)s)'))
    perms.add_argument('--personal', action='store_false', dest='publish',
                       help=('Set the permissions of the package to public. '
                             'Do not publish this to the global public repo. This package will be kept in you user repository.'))
    group = parser.add_mutually_exclusive_group()
    group.add_argument('-i', '--interactive', action='store_const', help='Run an interactive prompt if any packages are missing',
                        dest='mode', const='interactive')
    group.add_argument('-f', '--fail', help='Fail if a package or release does not exist (default)',
                                        action='store_const', dest='mode', const='fail')

    parser.set_defaults(main=main)

<commit_msg>The command should be "binstar remove", not "binstar delete"<commit_after>from binstar_client.utils import parse_specs, get_binstar, bool_input,\
    get_config
import tarfile
import json
from warnings import warn
from binstar_client import BinstarError, NotFound, Conflict
from os.path import exists
import sys
import time
import yaml
from os.path import basename
from email.parser import Parser
from os import path
import logging

log = logging.getLogger('binstar.updload')

def detect_yaml_attrs(filename):
    tar = tarfile.open(filename)
    obj = tar.extractfile('info/recipe/meta.yaml')
    attrs = yaml.load(obj)
    try:
        description = attrs['about']['home']
    except KeyError:
        description = None
    try:
        license = attrs['about']['license']
    except KeyError:
        license = None

    return description, license

def detect_pypi_attrs(filename):

    with tarfile.open(filename) as tf:
        pkg_info = next(name for name in tf.getnames() if name.endswith('/PKG-INFO'))
        fd = tf.extractfile(pkg_info)
        attrs = dict(Parser().parse(fd).items())

    name = attrs.pop('Name')
    version = attrs.pop('Version')
    summary = attrs.pop('Summary')
    description = attrs.pop('Description')
    license = attrs.pop('License')
    attrs = {'dist':'sdist'}

    filename = basename(filename)
    return filename, name, version, attrs, summary, description, license

arch_map = {('osx', 'x86_64'):'osx-64',
            ('win', 'x86'):'win-32',
            ('win', 'x86_64'):'win-64',
            ('linux', 'x86'):'linux-32',
            ('linux', 'x86_64'):'linux-64',
           }

def detect_conda_attrs(filename):

    tar = tarfile.open(filename)
    obj = tar.extractfile('info/index.json')
    attrs = json.loads(obj.read())

    description, license = detect_yaml_attrs(filename)
    os_arch = arch_map[(attrs['platform'], attrs['arch'])]
    filename = path.join(os_arch, basename(filename))
    return filename, attrs['name'], attrs['version'], attrs, description, description, license

detectors = {'conda':detect_conda_attrs,
             'pypi': detect_pypi_attrs,
             }

def detect_package_type(filename):

    if filename.endswith('.tar.bz2'):  # Could be a conda package
        try:
            with tarfile.open(filename) as tf:
                tf.getmember('info/index.json')
        except KeyError:
            pass
        else:
            return 'conda'

    if filename.endswith('.tar.gz'):  # Could be a setuptools sdist
        with tarfile.open(filename) as tf:
            if any(name.endswith('/PKG-INFO') for name in tf.getnames()):
                return 'pypi'

    raise BinstarError('Could not autodetect the package type of file %s' % filename)

def create_package(binstar, username, package_name, summary, license, public=True, publish=True):
    binstar.add_package(username, package_name,
                        summary,
                        license,
                        public=public,
                        publish=publish)

def create_release(binstar, username, package_name, version, description, announce=None):
    binstar.add_release(username, package_name, version, [],
                        announce, description)

def create_package_interactive(binstar, username, package_name, public=True, publish=True):

    log.info('\nThe package %s/%s does not exist' % (username, package_name))
    if not bool_input('Would you lke to create it now?'):
        log.info('goodbbye')
        raise SystemExit(-1)

    summary = raw_input('Enter a short description of the package\nsummary: ')
    license = raw_input('Enter the name of the license (default:BSD)\nlicense: ')
    license_url = raw_input('Enter the url of the license (optional)\nlicense url: ')
    public = bool_input('\nDo you want to make this package public?', public)
    if public:
        publish = bool_input('\nDo you want to make publish this package?\n'
                             'When published it will be added to the global public repositories.',
                             public)
    else:
        publish = False

    binstar.add_package(username, package_name,
                    summary,
                    license,
                    license_url,
                    public,
                    public=public,
                    publish=publish)

def create_release_interactive(binstar, username, package_name, version):

    log.info('\nThe release %s/%s/%s does not exist' % (username, package_name, version))
    if not bool_input('Would you like to create it now?'):
        log.info('good-bye')
        raise SystemExit(-1)

    description = raw_input('Enter a short description of the release:\n')
    log.info("\nAnnouncements are emailed to your package followers.")
    make_announcement = bool_input('Would you like to make an announcement to the package followers?', False)
    if make_announcement:
        announce = raw_input('Markdown Announcement:\n')
    else:
        announce = ''

    binstar.add_release(username, package_name, version, [],
                        announce, description)

def upload_print_callback():
    start_time = time.time()
    def callback(curr, total):
        curr_time = time.time()
        time_delta = curr_time - start_time

        remain = total - curr
        if curr and remain:
            eta = 1.0 * time_delta / curr * remain / 60.0
        else:
            eta = 0

        curr_kb = curr // 1024
        total_kb = total // 1024
        perc = 100.0 * curr / total if total else 0

        msg = '\r uploaded %(curr_kb)i of %(total_kb)iKb: %(perc).2f%% ETA: %(eta).1f minutes'
        sys.stderr.write(msg % locals())
        sys.stderr.flush()
        if curr == total:
            sys.stderr.write('\n')

    return callback

def main(args):

    binstar = get_binstar(args)

    if args.user:
        username = args.user
    else:
        user = binstar.user()
        username = user ['login']

    uploaded_packages = []

    for filename in args.files:

        if not exists(filename):
            raise BinstarError('file %s does not exist' % (filename))

        if args.package_type:
            package_type = args.package_type
        else:
            log.info('detecting package type ...')
            sys.stdout.flush()
            package_type = detect_package_type(filename)
            log.info(package_type)

        get_attrs = detectors[package_type]

        if args.metadata:
            attrs = json.loads(args.metadata)
            package_name = args.package
            version = args.version
        else:
            log.info('extracting package attributes for upload ...')
            sys.stdout.flush()
            basefilename, package_name, version, attrs, summary, description, license = get_attrs(filename)
            log.info('done')

        if args.package:
            package_name = args.package

        if args.version:
            version = args.version

        try:
            binstar.package(username, package_name)
        except NotFound:
            if args.mode == 'interactive':
                create_package_interactive(binstar, username, package_name,
                                           public=args.public,
                                           publish=args.publish)
            else:
                create_package(binstar, username, package_name, summary, license,
                               public=args.public,
                               publish=args.publish)

        try:
            binstar.release(username, package_name, version)
        except NotFound:
            if args.mode == 'interactive':
                create_release_interactive(binstar, username, package_name, version)
            else:
                create_release(binstar, username, package_name, version, description)

        with open(filename, 'rb') as fd:
            log.info('\nUploading file %s/%s/%s/%s ... ' % (username, package_name, version, basefilename))
            sys.stdout.flush()
            try:
                binstar.distribution(username, package_name, version, basefilename)
            except NotFound:
                pass
            else:
                if args.mode == 'interactive':
                    if bool_input('Distribution %s already exists. Would you like to replace it?' % (basefilename,)):
                        binstar.remove_dist(username, package_name, version, basefilename)
                    else:
                        log.info('Not replacing distribution %s' % (basefilename,))
                        continue
            try:
                binstar.upload(username, package_name, version, basefilename, fd, package_type, args.description, attrs=attrs,
                           callback=upload_print_callback())
            except Conflict:
                full_name = '%s/%s/%s/%s' % (username, package_name, version, basefilename)
                log.info('Distribution already exists. Please use the -i/--interactive option or `binstar remove %s`' % full_name)
                raise

            uploaded_packages.append(package_name)
            log.info("\n\nUpload(s) Complete\n")

    for package in uploaded_packages:
        log.info("Package located at:\nhttps://binstar.org/%s/%s\n" % (username, package))

def add_parser(subparsers):

    config = get_config()

    parser = subparsers.add_parser('upload',
                                      help='Upload a file to binstar',
                                      description=__doc__)

    parser.add_argument('files', nargs='*', help='Distributions to upload', default=[])

    parser.add_argument('-u', '--user', help='User account, defaults to the current user')
    parser.add_argument('-p', '--package', help='Defaults to the packge name in the uploaded file')
    parser.add_argument('-v', '--version', help='Defaults to the packge version in the uploaded file')
    parser.add_argument('-t', '--package-type', help='Set the package type, defaults to autodetect')
    parser.add_argument('-d', '--description', help='description of the file(s)')
    parser.add_argument('-m', '--metadata', help='json encoded metadata default is to autodetect')

    perms = parser.add_mutually_exclusive_group()
    perms.desciption = 'The package permissions'
    perms.add_argument('--public', action='store_true', default=config.get('public') or config.get('publish', True),
                       help='Set the permissions of the package to public (if it does not exist) (default %(default)s)')
    perms.add_argument('--private', action='store_false', dest='public',
                       help='Set the permissions of the package to private (if it does not exist)')
    perms.add_argument('--publish', action='store_true', default=config.get('publish', True),
                       help=('Set the permissions of the package to public and '
                             'publish this package to the global public repositories - if it does not exist. '
                            '(default %(default)s)'))
    perms.add_argument('--personal', action='store_false', dest='publish',
                       help=('Set the permissions of the package to public. '
                             'Do not publish this to the global public repo. This package will be kept in you user repository.'))
    group = parser.add_mutually_exclusive_group()
    group.add_argument('-i', '--interactive', action='store_const', help='Run an interactive prompt if any packages are missing',
                        dest='mode', const='interactive')
    group.add_argument('-f', '--fail', help='Fail if a package or release does not exist (default)',
                                        action='store_const', dest='mode', const='fail')

    parser.set_defaults(main=main)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# Copyright (C) 2014-Today GRAP (http://www.grap.coop)
# Copyright (C) 2016-Today La Louve (<http://www.lalouve.net/>)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from lxml import etree

from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
from odoo.osv.orm import setup_modifiers

class ProductTemplate(models.Model):
    _inherit = 'product.template'

    # Field Section
    fiscal_classification_id = fields.Many2one(
        comodel_name='account.product.fiscal.classification',
        string='Fiscal Classification',
        help="Specify the combination of taxes for this product."
        " This field is required. If you dont find the correct Fiscal"
        " Classification, Please create a new one or ask to your account"
        " manager if you don't have the access right.")

    # Overload Section
    @api.model
    def create(self, vals):
        res = super(ProductTemplate, self).create(vals)
        res.write_taxes_setting(vals)
        return res

    @api.multi
    def write(self, vals):
        res = super(ProductTemplate, self).write(vals)
        self.write_taxes_setting(vals)
        return res

    # Constraint Section
    @api.multi
    @api.constrains('fiscal_classification_id', 'categ_id')
    def _check_classification_categ(self):
        for template in self:
            if template.categ_id.fiscal_restriction and\
                    template.fiscal_classification_id not in\
                    template.categ_id.fiscal_classification_ids:
                raise ValidationError(_(
                    "The category '%s' of the product '%s'"
                    " doesn't not allow to set the classification '%s'.\n"
                    " Please, change the classification of the product, or"
                    " remove the constraint on the product category.\n\n"
                    " Allowed Classifications for '%s': %s") % (
                    template.categ_id.complete_name, template.name,
                    template.fiscal_classification_id.name,
                    template.categ_id.complete_name,
                    ''.join(
                        ['\n - ' + x.name for x in
                            template.categ_id.fiscal_classification_ids])))

    # View Section
    @api.onchange('categ_id', 'fiscal_classification_id')
    def _onchange_categ_fiscal_classification_id(self):
        if self.categ_id and self.categ_id.fiscal_restriction:
            if len(self.categ_id.fiscal_classification_ids) == 1:
                # Set classification if category allows only one
                self.fiscal_classification_id =\
                    self.categ_id.fiscal_classification_ids[0]
            elif self.fiscal_classification_id not in\
                    self.categ_id.fiscal_classification_ids:
                # Remove classification if category and classification are not
                # compatible
                self.fiscal_classification_id = None

    def fields_view_get(
            self, cr, uid, view_id=None, view_type='form', context=None,
            toolbar=False, submenu=False):
        """Set 'fiscal_classification_id' as required by fields_view_get:
        We don't set it by fields declaration in python file, to avoid
        incompatibility with other modules that could have demo data
        without fiscal_classification_id (the bugs will occur depending
        of the order in which the modules are loaded);
        We don't set it by view inheritance in xml file to impact all views
        (form / tree) that could define the model 'product.template';"""
        res = super(ProductTemplate, self).fields_view_get(
            cr, uid, view_id=view_id, view_type=view_type, context=context,
            toolbar=toolbar, submenu=submenu)
        if view_type == 'form':
            doc = etree.XML(res['arch'])
            nodes = doc.xpath("//field[@name='fiscal_classification_id']")
            if nodes:
                nodes[0].set('required', '1')
                setup_modifiers(
                    nodes[0], res['fields']['fiscal_classification_id'])
                res['arch'] = etree.tostring(doc)
        return res

    # Custom Section
    @api.multi
    def write_taxes_setting(self, vals):
        """If Fiscal Classification is defined, set the according taxes
        to the product(s); Otherwise, find the correct Fiscal classification,
        depending of the taxes, or create a new one, if no one are found."""
        for template in self:
            if vals.get('fiscal_classification_id', False):
                # update or replace 'taxes_id' and 'supplier_taxes_id'
                classification = template.fiscal_classification_id
                tax_vals = {
                    'supplier_taxes_id': [[6, 0, [
                        x.id for x in classification.purchase_tax_ids]]],
                    'taxes_id': [[6, 0, [
                        x.id for x in classification.sale_tax_ids]]],
                    }
                super(ProductTemplate, template.sudo()).write(tax_vals)
            elif ('supplier_taxes_id' in vals.keys() or
                    'taxes_id' in vals.keys()):
                # product template Single update mode
                fc_obj = self.env['account.product.fiscal.classification']
                if len(self) != 1:
                    raise ValidationError(
                        _("You cannot change Taxes for many Products."))
                purchase_tax_ids = [
                    x.id for x in template.sudo().supplier_taxes_id]
                sale_tax_ids = [
                    x.id for x in template.sudo().taxes_id]
                fc_id = fc_obj.find_or_create(
                    template.company_id.id, sale_tax_ids, purchase_tax_ids)
                super(ProductTemplate, template.sudo()).write(
                    {'fiscal_classification_id': fc_id})
<commit_msg>[MIGR] product.template object<commit_after># -*- coding: utf-8 -*-
# Copyright (C) 2014-Today GRAP (http://www.grap.coop)
# Copyright (C) 2016-Today La Louve (<http://www.lalouve.net/>)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from lxml import etree

from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
from odoo.osv.orm import setup_modifiers

class ProductTemplate(models.Model):
    _inherit = 'product.template'

    # Field Section
    fiscal_classification_id = fields.Many2one(
        comodel_name='account.product.fiscal.classification',
        string='Fiscal Classification',
        help="Specify the combination of taxes for this product."
        " This field is required. If you dont find the correct Fiscal"
        " Classification, Please create a new one or ask to your account"
        " manager if you don't have the access right.")

    # Overload Section
    @api.model
    def create(self, vals):
        res = super(ProductTemplate, self).create(vals)
        res.write_taxes_setting(vals)
        return res

    @api.multi
    def write(self, vals):
        res = super(ProductTemplate, self).write(vals)
        self.write_taxes_setting(vals)
        return res

    # Constraint Section
    @api.multi
    @api.constrains('fiscal_classification_id', 'categ_id')
    def _check_classification_categ(self):
        for template in self:
            if template.categ_id.fiscal_restriction and\
                    template.fiscal_classification_id not in\
                    template.categ_id.fiscal_classification_ids:
                raise ValidationError(_(
                    "The category '%s' of the product '%s'"
                    " doesn't not allow to set the classification '%s'.\n"
                    " Please, change the classification of the product, or"
                    " remove the constraint on the product category.\n\n"
                    " Allowed Classifications for '%s': %s") % (
                    template.categ_id.complete_name, template.name,
                    template.fiscal_classification_id.name,
                    template.categ_id.complete_name,
                    ''.join(
                        ['\n - ' + x.name for x in
                            template.categ_id.fiscal_classification_ids])))

    # View Section
    @api.onchange('categ_id', 'fiscal_classification_id')
    def _onchange_categ_fiscal_classification_id(self):
        if self.categ_id and self.categ_id.fiscal_restriction:
            if len(self.categ_id.fiscal_classification_ids) == 1:
                # Set classification if category allows only one
                self.fiscal_classification_id =\
                    self.categ_id.fiscal_classification_ids[0]
            elif self.fiscal_classification_id not in\
                    self.categ_id.fiscal_classification_ids:
                # Remove classification if category and classification are not
                # compatible
                self.fiscal_classification_id = None

    @api.model
    def fields_view_get(self, view_id=None, view_type='form',
                        toolbar=False, submenu=False):
        """Set 'fiscal_classification_id' as required by fields_view_get:
        We don't set it by fields declaration in python file, to avoid
        incompatibility with other modules that could have demo data
        without fiscal_classification_id (the bugs will occur depending
        of the order in which the modules are loaded);
        We don't set it by view inheritance in xml file to impact all views
        (form / tree) that could define the model 'product.template';"""
        result = super(ProductTemplate, self).fields_view_get(
            view_id, view_type, toolbar, submenu)
        if view_type == 'form':
            doc = etree.XML(result['arch'])
            nodes = doc.xpath("//field[@name='fiscal_classification_id']")
            if nodes:
                nodes[0].set('required', '1')
                setup_modifiers(
                    nodes[0], result['fields']['fiscal_classification_id'])
                result['arch'] = etree.tostring(doc)
        return result

    # Custom Section
    @api.multi
    def write_taxes_setting(self, vals):
        """If Fiscal Classification is defined, set the according taxes
        to the product(s); Otherwise, find the correct Fiscal classification,
        depending of the taxes, or create a new one, if no one are found."""
        for template in self:
            if vals.get('fiscal_classification_id', False):
                # update or replace 'taxes_id' and 'supplier_taxes_id'
                classification = template.fiscal_classification_id
                tax_vals = {
                    'supplier_taxes_id': [[6, 0, [
                        x.id for x in classification.purchase_tax_ids]]],
                    'taxes_id': [[6, 0, [
                        x.id for x in classification.sale_tax_ids]]],
                    }
                super(ProductTemplate, template.sudo()).write(tax_vals)
            elif ('supplier_taxes_id' in vals.keys() or
                    'taxes_id' in vals.keys()):
                # product template Single update mode
                fc_obj = self.env['account.product.fiscal.classification']
                if len(self) != 1:
                    raise ValidationError(
                        _("You cannot change Taxes for many Products."))
                purchase_tax_ids = [
                    x.id for x in template.sudo().supplier_taxes_id]
                sale_tax_ids = [
                    x.id for x in template.sudo().taxes_id]
                fc_id = fc_obj.find_or_create(
                    template.company_id.id, sale_tax_ids, purchase_tax_ids)
                super(ProductTemplate, template.sudo()).write(
                    {'fiscal_classification_id': fc_id})
<|endoftext|>


<commit_before>#
#
#  Copyright (c) 2014, 2015, 2016, 2017 Psyop Media Company, LLC
#  See license.txt
#
#
import tests
import os
import json

def get_all_cryptomatte_tests():
    return [Cryptomatte000, Cryptomatte001, Cryptomatte010, Cryptomatte020]

#############################################
# Cryptomatte test base class
#############################################

class CryptomatteTestBase(tests.KickAndCompareTestCase):
    ass = ""

    def setUp(self):
        self.result_images = []
        for file_name in self.correct_file_names:
            img, correct_img = self.load_images(file_name)
            if img and correct_img:
                self.result_images.append((img, correct_img))

    def cryptomatte_metadata(self, ibuf):
        """Returns dictionary of key, value of cryptomatte metadata"""
        metadata = {
            a.name: a.value
            for a in ibuf.spec().extra_attribs if a.name.startswith("cryptomatte")
        }

        for key in metadata.keys():
            if key.endswith("/manif_file"):
                sidecar_path = os.path.join(os.path.dirname(ibuf.name), metadata[key])
                with open(sidecar_path) as f:
                    metadata[key.replace("manif_file", "manifest")] = f.read()

        return metadata

    def sorted_cryptomatte_metadata(self, img):
        """
        Gets a dictionary of the cryptomatte metadata, interleved by cryptomatte stream.

        for example:
            {"crypto_object": {"name": crypto_object", ... }}

        Also includes ID coverage pairs in subkeys, "ch_pair_idxs" and "ch_pair_names".
        """
        img_md = self.cryptomatte_metadata(img)
        cryptomatte_streams = {}
        for key, value in img_md.iteritems():
            prefix, cryp_key, cryp_md_key = key.split("/")
            name = img_md["/".join((prefix, cryp_key, "name"))]
            cryptomatte_streams[name] = cryptomatte_streams.get(name, {})
            cryptomatte_streams[name][cryp_md_key] = value

        for cryp_key in cryptomatte_streams:
            name = cryptomatte_streams[cryp_key]["name"]
            ch_id_coverages = []
            ch_id_coverage_names = []
            channels_dict = {ch: i for i, ch in enumerate(img.spec().channelnames)}
            for i, ch in enumerate(img.spec().channelnames):
                if not ch.startswith(name):
                    continue
                if ch.startswith("%s." % name):
                    continue
                if ch.endswith(".R"):
                    red_name = ch
                    green_name = "%s.G" % ch[:-2]
                    blue_name = "%s.B" % ch[:-2]
                    alpha_name = "%s.A" % ch[:-2]

                    red_idx = i
                    green_idx = channels_dict[green_name]
                    blue_idx = channels_dict[blue_name]
                    alpha_idx = channels_dict[alpha_name]

                    ch_id_coverages.append((red_idx, green_idx))
                    ch_id_coverages.append((blue_idx, alpha_idx))
                    ch_id_coverage_names.append((red_name, green_name))
                    ch_id_coverage_names.append((blue_name, alpha_name))
            cryptomatte_streams[cryp_key]["ch_pair_idxs"] = ch_id_coverages
            cryptomatte_streams[cryp_key]["ch_pair_names"] = ch_id_coverage_names
        return cryptomatte_streams

    def assertManifestsAreValidAndMatch(self, result_md, correct_md, key):
        """ Does a comparison between two manifests. Order is not important, but contents are.
        Checks both are parsable with json
        Checks that there are no extra names in either manifest
        """
        try:
            correct_manifest = json.loads(correct_md[key])
        except Exception, e:
            raise RuntimeError("Correct manifest could not be loaded. %s" % e)
        try:
            result_manifest = json.loads(result_md[key])
        except Exception, e:
            self.fail("Result manifest could not be loaded. %s" % e)

        # test manifest hashes?
        correct_names = set(correct_manifest.keys())
        result_names = set(result_manifest.keys())

        if not result_manifest:
            self.fail("%s - Result manifest is empty. " % key)
        extra_in_correct = correct_names - result_names
        extra_in_result = result_names - correct_names
        if extra_in_correct or extra_in_result:
            self.fail("%s - Missing manifest names: %s, Extra manifest names: %s" %
                      (key, extra_in_correct, extra_in_result))

    def assertAllManifestsValidAndMatch(self):
        """
        Tests manifests match and are valid, and tests that all other cryptomatte
        metadata is equal.
        """
        for result_img, correct_img in self.result_images:
            self.assertSameChannels(result_img, correct_img)
            result_md = self.cryptomatte_metadata(result_img)
            correct_md = self.cryptomatte_metadata(correct_img)

            for key in correct_md:
                self.assertIn(key, result_md, "Result missing metadata key: %s" % key)
            for key in result_md:
                self.assertIn(key, correct_md, "Result has extra metadata key: %s" % key)

            found_manifest = False
            for key in correct_md:
                if key.endswith("/manifest"):
                    self.assertManifestsAreValidAndMatch(result_md, correct_md, key)
                    found_manifest = True
                else:
                    self.assertEqual(correct_md[key], result_md[key],
                                     "Metadata doesn't match: %s vs %s " % (result_md[key],
                                                                            correct_md[key]))
            self.assertTrue(found_manifest, "No manifest found")

    def assertCryptomattePixelsMatch(self,
                                     rms_tolerance=0.01,
                                     very_different_num_tolerance=4,
                                     print_result=False):
        """
        Tests pixels match in terms of coverage per ID. Normal image diff doesn't work here with any
        tolerance, because reshuffled IDs (for different sampling) cause giant errors. As a result,
        comparison is more costly, but better geared for Cryptomatte.
        """
        import math

        def get_id_coverage_dict(pixel_values, ch_pair_idxs):
            return {
                pixel_values[x]: pixel_values[y]
                for x, y, in ch_pair_idxs if (x != 0.0 or y != 0.0)
            }

        big_dif_tolerance = 0.3

        for result_img, correct_img in self.result_images:
            result_nested_md = self.sorted_cryptomatte_metadata(result_img)
            correct_nested_md = self.sorted_cryptomatte_metadata(correct_img)

            total_count = 0
            very_different_count = 0
            squared_error = 0.0
            for row in range(0, 128):
                for column in range(0, 128):
                    result_pixel = result_img.getpixel(row, column)
                    correct_pixel = correct_img.getpixel(row, column)

                    for cryp_key in result_nested_md:
                        result_id_cov = get_id_coverage_dict(
                            result_pixel, result_nested_md[cryp_key]["ch_pair_idxs"])
                        correct_id_cov = get_id_coverage_dict(
                            correct_pixel, correct_nested_md[cryp_key]["ch_pair_idxs"])
                        for id_val, cov in correct_id_cov.iteritems():
                            total_count += 1
                            delta = abs(cov - (result_id_cov.get(id_val, 0.0)))
                            squared_error += delta * delta
                            if delta > big_dif_tolerance:
                                very_different_count += 1
                        for id_val, cov in result_id_cov.iteritems():
                            if id_val not in correct_id_cov:
                                total_count += 1
                                delta = cov
                                squared_error += delta * delta
                                if delta > big_dif_tolerance:
                                    very_different_count += 1

            rms = math.sqrt(squared_error / float(total_count))
            if print_result:
                print(self.id(), "Root mean square error: ", rms,
                      "Number of very different pixels: ", very_different_count)

            self.assertTrue(very_different_count < very_different_num_tolerance,
                            "%s matte pixels were very different (max tolerated: %s). " %
                            (very_different_count, very_different_num_tolerance))
            self.assertTrue(rms < 0.01,
                            "Root mean square error was greater than %s. " % rms_tolerance)

#############################################
# Cryptomatte test cases themselves
#############################################

class Cryptomatte000(CryptomatteTestBase):
    """
    A typical Mtoa configuration, (except with mayaShadingEngines removed)
    Some face assignments, some opacity, namespaces, some default namespaces, some
    overrides on namespaces.

    Settings:
        naming style: maya
        exr: single
        manifest: embedded
        strip namespaces: on
        overrides:
            Some face assignments
            crypto_asset_override
            per-face crypto_object_override
    """
    ass = "cryptomatte/000_mtoa_basic.ass"

    def test_manifests_valid_and_match(self):
        self.assertAllManifestsValidAndMatch()

    def test_results_all_present(self):
        self.assertAllResultFilesPresent()

    def test_cryptomatte_pixels(self):
        self.assertCryptomattePixelsMatch(print_result=True)

class Cryptomatte001(CryptomatteTestBase):
    """
    Same as 000, but with sidecar manifests.
    """
    ass = "cryptomatte/001_sidecars.ass"

    def test_manifests_valid_and_match(self):
        self.assertAllManifestsValidAndMatch()

    def test_results_all_present(self):
        self.assertAllResultFilesPresent()

    def test_cryptomatte_pixels(self):
        self.assertCryptomattePixelsMatch(print_result=True)

class Cryptomatte010(CryptomatteTestBase):
    """
    Lots of instances, in a typical HtoA configuration.

    Settings:
        naming style: houdini
        exr: multi
        manifest: embedded
        strip namespaces: off
        overrides:
            crypto_asset on instances and instance masters
            crypto_object_offset on instance masters
            crypto_material_offset on instance masters
    """
    ass = "cryptomatte/010_htoa_instances.ass"

    def test_manifests_valid_and_match(self):
        self.assertAllManifestsValidAndMatch()

    def test_results_all_present(self):
        self.assertAllResultFilesPresent()

    def test_cryptomatte_pixels(self):
        self.assertCryptomattePixelsMatch(print_result=True)

class Cryptomatte020(CryptomatteTestBase):
    """
    Has some custom cryptomattes. Some objects have values set, others do not.
    Some per-face user data as well.

    Settings:
        naming style: maya
        exr: single
        manifest: embedded
        strip namespaces: N/A
    Something has strings per polygon.
    """
    ass = "cryptomatte/020_custom_cryptomattes.ass"

    def test_manifests_valid_and_match(self):
        self.assertAllManifestsValidAndMatch()

    def test_results_all_present(self):
        self.assertAllResultFilesPresent()

    def test_cryptomatte_pixels(self):
        self.assertCryptomattePixelsMatch(print_result=True)
<commit_msg>Minor improvement to incorrect manifest reporting<commit_after>#
#
#  Copyright (c) 2014, 2015, 2016, 2017 Psyop Media Company, LLC
#  See license.txt
#
#
import tests
import os
import json

def get_all_cryptomatte_tests():
    return [Cryptomatte000, Cryptomatte001, Cryptomatte010, Cryptomatte020]

#############################################
# Cryptomatte test base class
#############################################

class CryptomatteTestBase(tests.KickAndCompareTestCase):
    ass = ""

    def setUp(self):
        self.result_images = []
        for file_name in self.correct_file_names:
            img, correct_img = self.load_images(file_name)
            if img and correct_img:
                self.result_images.append((img, correct_img))

    def cryptomatte_metadata(self, ibuf):
        """Returns dictionary of key, value of cryptomatte metadata"""
        metadata = {
            a.name: a.value
            for a in ibuf.spec().extra_attribs if a.name.startswith("cryptomatte")
        }

        for key in metadata.keys():
            if key.endswith("/manif_file"):
                sidecar_path = os.path.join(os.path.dirname(ibuf.name), metadata[key])
                with open(sidecar_path) as f:
                    metadata[key.replace("manif_file", "manifest")] = f.read()

        return metadata

    def sorted_cryptomatte_metadata(self, img):
        """
        Gets a dictionary of the cryptomatte metadata, interleved by cryptomatte stream.

        for example:
            {"crypto_object": {"name": crypto_object", ... }}

        Also includes ID coverage pairs in subkeys, "ch_pair_idxs" and "ch_pair_names".
        """
        img_md = self.cryptomatte_metadata(img)
        cryptomatte_streams = {}
        for key, value in img_md.iteritems():
            prefix, cryp_key, cryp_md_key = key.split("/")
            name = img_md["/".join((prefix, cryp_key, "name"))]
            cryptomatte_streams[name] = cryptomatte_streams.get(name, {})
            cryptomatte_streams[name][cryp_md_key] = value

        for cryp_key in cryptomatte_streams:
            name = cryptomatte_streams[cryp_key]["name"]
            ch_id_coverages = []
            ch_id_coverage_names = []
            channels_dict = {ch: i for i, ch in enumerate(img.spec().channelnames)}
            for i, ch in enumerate(img.spec().channelnames):
                if not ch.startswith(name):
                    continue
                if ch.startswith("%s." % name):
                    continue
                if ch.endswith(".R"):
                    red_name = ch
                    green_name = "%s.G" % ch[:-2]
                    blue_name = "%s.B" % ch[:-2]
                    alpha_name = "%s.A" % ch[:-2]

                    red_idx = i
                    green_idx = channels_dict[green_name]
                    blue_idx = channels_dict[blue_name]
                    alpha_idx = channels_dict[alpha_name]

                    ch_id_coverages.append((red_idx, green_idx))
                    ch_id_coverages.append((blue_idx, alpha_idx))
                    ch_id_coverage_names.append((red_name, green_name))
                    ch_id_coverage_names.append((blue_name, alpha_name))
            cryptomatte_streams[cryp_key]["ch_pair_idxs"] = ch_id_coverages
            cryptomatte_streams[cryp_key]["ch_pair_names"] = ch_id_coverage_names
        return cryptomatte_streams

    def assertManifestsAreValidAndMatch(self, result_md, correct_md, key):
        """ Does a comparison between two manifests. Order is not important, but contents are.
        Checks both are parsable with json
        Checks that there are no extra names in either manifest
        """
        try:
            correct_manifest = json.loads(correct_md[key])
        except Exception, e:
            raise RuntimeError("Correct manifest could not be loaded. %s" % e)
        try:
            result_manifest = json.loads(result_md[key])
        except Exception, e:
            self.fail("Result manifest could not be loaded. %s" % e)

        # test manifest hashes?
        correct_names = set(correct_manifest.keys())
        result_names = set(result_manifest.keys())

        if not result_manifest:
            self.fail("%s - Result manifest is empty. " % key)
        extra_in_correct = correct_names - result_names
        extra_in_result = result_names - correct_names
        if extra_in_correct or extra_in_result:
            self.fail("%s - Missing manifest names: %s, Extra manifest names: %s" %
                      (key, list(extra_in_correct), list(extra_in_result)))

    def assertAllManifestsValidAndMatch(self):
        """
        Tests manifests match and are valid, and tests that all other cryptomatte
        metadata is equal.
        """
        for result_img, correct_img in self.result_images:
            self.assertSameChannels(result_img, correct_img)
            result_md = self.cryptomatte_metadata(result_img)
            correct_md = self.cryptomatte_metadata(correct_img)

            for key in correct_md:
                self.assertIn(key, result_md, "Result missing metadata key: %s" % key)
            for key in result_md:
                self.assertIn(key, correct_md, "Result has extra metadata key: %s" % key)

            found_manifest = False
            for key in correct_md:
                if key.endswith("/manifest"):
                    self.assertManifestsAreValidAndMatch(result_md, correct_md, key)
                    found_manifest = True
                else:
                    self.assertEqual(correct_md[key], result_md[key],
                                     "Metadata doesn't match: %s vs %s " % (result_md[key],
                                                                            correct_md[key]))
            self.assertTrue(found_manifest, "No manifest found")

    def assertCryptomattePixelsMatch(self,
                                     rms_tolerance=0.01,
                                     very_different_num_tolerance=4,
                                     print_result=False):
        """
        Tests pixels match in terms of coverage per ID. Normal image diff doesn't work here with any
        tolerance, because reshuffled IDs (for different sampling) cause giant errors. As a result,
        comparison is more costly, but better geared for Cryptomatte.
        """
        import math

        def get_id_coverage_dict(pixel_values, ch_pair_idxs):
            return {
                pixel_values[x]: pixel_values[y]
                for x, y, in ch_pair_idxs if (x != 0.0 or y != 0.0)
            }

        big_dif_tolerance = 0.3

        for result_img, correct_img in self.result_images:
            result_nested_md = self.sorted_cryptomatte_metadata(result_img)
            correct_nested_md = self.sorted_cryptomatte_metadata(correct_img)

            total_count = 0
            very_different_count = 0
            squared_error = 0.0
            for row in range(0, 128):
                for column in range(0, 128):
                    result_pixel = result_img.getpixel(row, column)
                    correct_pixel = correct_img.getpixel(row, column)

                    for cryp_key in result_nested_md:
                        result_id_cov = get_id_coverage_dict(
                            result_pixel, result_nested_md[cryp_key]["ch_pair_idxs"])
                        correct_id_cov = get_id_coverage_dict(
                            correct_pixel, correct_nested_md[cryp_key]["ch_pair_idxs"])
                        for id_val, cov in correct_id_cov.iteritems():
                            total_count += 1
                            delta = abs(cov - (result_id_cov.get(id_val, 0.0)))
                            squared_error += delta * delta
                            if delta > big_dif_tolerance:
                                very_different_count += 1
                        for id_val, cov in result_id_cov.iteritems():
                            if id_val not in correct_id_cov:
                                total_count += 1
                                delta = cov
                                squared_error += delta * delta
                                if delta > big_dif_tolerance:
                                    very_different_count += 1

            rms = math.sqrt(squared_error / float(total_count))
            if print_result:
                print(self.id(), "Root mean square error: ", rms,
                      "Number of very different pixels: ", very_different_count)

            self.assertTrue(very_different_count < very_different_num_tolerance,
                            "%s matte pixels were very different (max tolerated: %s). " %
                            (very_different_count, very_different_num_tolerance))
            self.assertTrue(rms < 0.01,
                            "Root mean square error was greater than %s. " % rms_tolerance)

#############################################
# Cryptomatte test cases themselves
#############################################

class Cryptomatte000(CryptomatteTestBase):
    """
    A typical Mtoa configuration, (except with mayaShadingEngines removed)
    Some face assignments, some opacity, namespaces, some default namespaces, some
    overrides on namespaces.

    Settings:
        naming style: maya
        exr: single
        manifest: embedded
        strip namespaces: on
        overrides:
            Some face assignments
            crypto_asset_override
            per-face crypto_object_override
    """
    ass = "cryptomatte/000_mtoa_basic.ass"

    def test_manifests_valid_and_match(self):
        self.assertAllManifestsValidAndMatch()

    def test_results_all_present(self):
        self.assertAllResultFilesPresent()

    def test_cryptomatte_pixels(self):
        self.assertCryptomattePixelsMatch(print_result=True)

class Cryptomatte001(CryptomatteTestBase):
    """
    Same as 000, but with sidecar manifests.
    """
    ass = "cryptomatte/001_sidecars.ass"

    def test_manifests_valid_and_match(self):
        self.assertAllManifestsValidAndMatch()

    def test_results_all_present(self):
        self.assertAllResultFilesPresent()

    def test_cryptomatte_pixels(self):
        self.assertCryptomattePixelsMatch(print_result=True)

class Cryptomatte010(CryptomatteTestBase):
    """
    Lots of instances, in a typical HtoA configuration.

    Settings:
        naming style: houdini
        exr: multi
        manifest: embedded
        strip namespaces: off
        overrides:
            crypto_asset on instances and instance masters
            crypto_object_offset on instance masters
            crypto_material_offset on instance masters
    """
    ass = "cryptomatte/010_htoa_instances.ass"

    def test_manifests_valid_and_match(self):
        self.assertAllManifestsValidAndMatch()

    def test_results_all_present(self):
        self.assertAllResultFilesPresent()

    def test_cryptomatte_pixels(self):
        self.assertCryptomattePixelsMatch(print_result=True)

class Cryptomatte020(CryptomatteTestBase):
    """
    Has some custom cryptomattes. Some objects have values set, others do not.
    Some per-face user data as well.

    Settings:
        naming style: maya
        exr: single
        manifest: embedded
        strip namespaces: N/A
    Something has strings per polygon.
    """
    ass = "cryptomatte/020_custom_cryptomattes.ass"

    def test_manifests_valid_and_match(self):
        self.assertAllManifestsValidAndMatch()

    def test_results_all_present(self):
        self.assertAllResultFilesPresent()

    def test_cryptomatte_pixels(self):
        self.assertCryptomattePixelsMatch(print_result=True)
<|endoftext|>


<commit_before># file model.py
# allows the definition of different models to be trained
# for initialization: Lasagne/lasagne/init.py
# for nonlinearities: Lasagne/lasagne/nonlinearities.py
# for layers: Lasagne/lasagne/layers/

from lasagne import layers
from lasagne.layers import cuda_convnet
from lasagne import nonlinearities
from lasagne import init

# use cuda_convnet for a speed improvement
# will not be available without a GPU
Conv2DLayer = cuda_convnet.Conv2DCCLayer
MaxPool2DLayer = cuda_convnet.MaxPool2DCCLayer

def build_model(batch_size, input_width, input_height, input_channels, output_dims):
    l_in = layers.InputLayer(
        # variable batch size (None), channel, width, height
        shape=(None, input_channels, input_width, input_height)
    )

    l_noise = layers.GaussianNoiseLayer(
        l_in,
    )

    l_conv1 = Conv2DLayer(
        l_noise,
        num_filters=32,
        filter_size=(5, 5),
        # nonlinearity=nonlinearities.rectify,
        nonlinearity=nonlinearities.LeakyRectify,
        W=init.GlorotUniform(),
    )

    l_pool1 = MaxPool2DLayer(
        l_conv1,
        ds=(2, 2),
        strides=(2, 2),
    )

    l_conv2 = Conv2DLayer(
        l_pool1,
        num_filters=64,
        filter_size=(3, 3),
        # nonlinearity=nonlinearities.rectify,
        nonlinearity=nonlinearities.LeakyRectify,
        W=init.GlorotUniform(),
    )

    l_pool2 = MaxPool2DLayer(
        l_conv2,
        ds=(2, 2),
        strides=(2, 2),
    )

    l_conv3 = Conv2DLayer(
        l_pool2,
        num_filters=128,
        filter_size=(3, 3),
        # nonlinearity=nonlinearities.rectify,
        nonlinearity=nonlinearities.LeakyRectify,
        W=init.GlorotUniform(),
    )

    l_pool3 = MaxPool2DLayer(
        l_conv3,
        ds=(2, 2),
        strides=(2, 2),
    )

    l_hidden1 = layers.DenseLayer(
        l_pool3,
        num_units=1024,
        # nonlinearity=nonlinearities.rectify,
        nonlinearity=nonlinearities.LeakyRectify,
        W=init.GlorotUniform(),
    )

    l_hidden1_maxout = layers.FeaturePoolLayer(
        l_hidden1,
        ds=2,
    )

    l_hidden1_dropout = layers.DropoutLayer(l_hidden1_maxout, p=0.5)

    l_hidden2 = layers.DenseLayer(
        l_hidden1_dropout,
        num_units=1024,
        # nonlinearity=nonlinearities.rectify,
        nonlinearity=nonlinearities.LeakyRectify,
        W=init.GlorotUniform(),
    )

    l_hidden2_maxout = layers.FeaturePoolLayer(
        l_hidden2,
        ds=2,
    )

    l_hidden2_dropout = layers.DropoutLayer(l_hidden2_maxout, p=0.5)

    l_out = layers.DenseLayer(
        l_hidden2_dropout,
        num_units=output_dims,
        nonlinearity=nonlinearities.softmax,
        W=init.GlorotUniform(),
    )

    return l_out
<commit_msg>Updates for better regularization<commit_after># file model.py
# allows the definition of different models to be trained
# for initialization: Lasagne/lasagne/init.py
# for nonlinearities: Lasagne/lasagne/nonlinearities.py
# for layers: Lasagne/lasagne/layers/

from lasagne import layers
from lasagne.layers import cuda_convnet
from lasagne import nonlinearities
from lasagne import init

# use cuda_convnet for a speed improvement
# will not be available without a GPU
Conv2DLayer = cuda_convnet.Conv2DCCLayer
MaxPool2DLayer = cuda_convnet.MaxPool2DCCLayer

def build_model(batch_size, input_width, input_height, input_channels, output_dims):
    l_in = layers.InputLayer(
        # variable batch size (None), channel, width, height
        shape=(None, input_channels, input_width, input_height)
    )

    l_noise = layers.GaussianNoiseLayer(
        l_in,
    )

    l_conv1 = Conv2DLayer(
        l_noise,
        num_filters=32,
        filter_size=(5, 5),
        nonlinearity=nonlinearities.rectify,
        # nonlinearity=nonlinearities.LeakyRectify,
        W=init.GlorotUniform(),
    )

    l_pool1 = MaxPool2DLayer(
        l_conv1,
        ds=(2, 2),
        strides=(2, 2),
    )

    l_conv2 = Conv2DLayer(
        l_pool1,
        num_filters=64,
        filter_size=(3, 3),
        nonlinearity=nonlinearities.rectify,
        # nonlinearity=nonlinearities.LeakyRectify,
        W=init.GlorotUniform(),
    )

    l_pool2 = MaxPool2DLayer(
        l_conv2,
        ds=(2, 2),
        strides=(2, 2),
    )

    l_conv3 = Conv2DLayer(
        l_pool2,
        num_filters=128,
        filter_size=(3, 3),
        nonlinearity=nonlinearities.rectify,
        # nonlinearity=nonlinearities.LeakyRectify,
        W=init.GlorotUniform(),
    )

    l_pool3 = MaxPool2DLayer(
        l_conv3,
        ds=(2, 2),
        strides=(2, 2),
    )

    l_hidden1 = layers.DenseLayer(
        l_pool3,
        num_units=1024,
        nonlinearity=nonlinearities.rectify,
        # nonlinearity=nonlinearities.LeakyRectify,
        W=init.GlorotUniform(),
    )

    l_hidden1_maxout = layers.FeaturePoolLayer(
        l_hidden1,
        ds=2,
    )

    l_hidden1_dropout = layers.DropoutLayer(l_hidden1_maxout, p=0.5)

    l_hidden2 = layers.DenseLayer(
        l_hidden1_dropout,
        num_units=1024,
        nonlinearity=nonlinearities.rectify,
        # nonlinearity=nonlinearities.LeakyRectify,
        W=init.GlorotUniform(),
    )

    l_hidden2_maxout = layers.FeaturePoolLayer(
        l_hidden2,
        ds=2,
    )

    l_hidden2_dropout = layers.DropoutLayer(l_hidden2_maxout, p=0.5)

    l_out = layers.DenseLayer(
        l_hidden2_dropout,
        num_units=output_dims,
        nonlinearity=nonlinearities.softmax,
        W=init.GlorotUniform(),
    )

    return l_out
<|endoftext|>


<commit_before>import os
import subprocess
import sys
import time

from twitter.common import app
from twitter.mesos.clusters import Cluster
from twitter.mesos.deploy import (
  Builder,
  HDFSDeployer)

class ThermosBuilder(Builder):
  @property
  def project(self):
    return 'thermos'

  @property
  def commands(self):
    return [
      './pants src/python/twitter/mesos/executor:thermos_executor',
      './pants src/python/twitter/mesos/executor:thermos_runner',
      './pants src/python/twitter/mesos/executor:gc_executor',
    ]

  @property
  def artifacts(self):
    return {
      'dist/thermos_executor.pex': '$cluster/thermos_executor.pex',
      'dist/gc_executor.pex': '$cluster/gc_executor.pex',
    }

  def preprocess(self):
    self.check_call('rm -f pants.pex')

  def postprocess(self):
    import contextlib
    import zipfile
    with contextlib.closing(zipfile.ZipFile('dist/thermos_executor.pex', 'a')) as zf:
      zf.writestr('twitter/mesos/executor/resources/__init__.py', '')
      zf.write('dist/thermos_runner.pex', 'twitter/mesos/executor/resources/thermos_runner.pex')

app.set_usage('%prog [options] tag')

cluster_list = Cluster.get_list()
app.add_option('--cluster', type = 'choice', choices = cluster_list, dest='cluster',
               help='Cluster to deploy the scheduler in (one of: %s)' % ', '.join(cluster_list))

app.add_option('-v', dest='verbose', default=False, action='store_true',
               help='Verbose logging.')

app.add_option('--really_push', dest='really_push', default=False, action='store_true',
               help='Safeguard to prevent fat-fingering.  When false, only show commands but do '
                    'not run them.')

app.add_option('--hotfix', dest='hotfix', default=False, action='store_true',
               help='Indicates this is a hotfix deploy from the current tree.')

app.add_option('--release', dest='release', default=None, type=int,
               help='Specify a release number to deploy. If none specified, it uses the latest '
                    'release assigned to the cluster environment.  If specified, it must have '
                    'been assigned as a release for this environment.')

def main(_, options):
  if not options.cluster:
    cluster_list = Cluster.get_list()
    print ('Please specify the cluster you would like to deploy to with\n\t--cluster %s'
           % cluster_list)
    return

  builder = ThermosBuilder(options.cluster, options.release, options.hotfix, options.verbose)
  builder.build()

  deployer = HDFSDeployer(options.cluster, not options.really_push, options.verbose)
  deployer.stage(builder)

app.main()
<commit_msg>add test commands to thermos deploy script<commit_after>import os
import subprocess
import sys
import time

from twitter.common import app
from twitter.mesos.clusters import Cluster
from twitter.mesos.deploy import (
  Builder,
  HDFSDeployer)

class ThermosBuilder(Builder):
  @property
  def project(self):
    return 'thermos'

  @property
  def test_commands(self):
    return [
      './pants tests/python/twitter/thermos:all',
      './pants tests/python/twitter/mesos/executor:all',
    ]

  @property
  def commands(self):
    return [
      './pants src/python/twitter/mesos/executor:thermos_executor',
      './pants src/python/twitter/mesos/executor:thermos_runner',
      './pants src/python/twitter/mesos/executor:gc_executor',
    ]

  @property
  def artifacts(self):
    return {
      'dist/thermos_executor.pex': '$cluster/thermos_executor.pex',
      'dist/gc_executor.pex': '$cluster/gc_executor.pex',
    }

  def preprocess(self):
    self.check_call('rm -f pants.pex')

  def postprocess(self):
    import contextlib
    import zipfile
    with contextlib.closing(zipfile.ZipFile('dist/thermos_executor.pex', 'a')) as zf:
      zf.writestr('twitter/mesos/executor/resources/__init__.py', '')
      zf.write('dist/thermos_runner.pex', 'twitter/mesos/executor/resources/thermos_runner.pex')

app.set_usage('%prog [options] tag')

cluster_list = Cluster.get_list()
app.add_option('--cluster', type = 'choice', choices = cluster_list, dest='cluster',
               help='Cluster to deploy the scheduler in (one of: %s)' % ', '.join(cluster_list))

app.add_option('-v', dest='verbose', default=False, action='store_true',
               help='Verbose logging.')

app.add_option('--really_push', dest='really_push', default=False, action='store_true',
               help='Safeguard to prevent fat-fingering.  When false, only show commands but do '
                    'not run them.')

app.add_option('--hotfix', dest='hotfix', default=False, action='store_true',
               help='Indicates this is a hotfix deploy from the current tree.')

app.add_option('--release', dest='release', default=None, type=int,
               help='Specify a release number to deploy. If none specified, it uses the latest '
                    'release assigned to the cluster environment.  If specified, it must have '
                    'been assigned as a release for this environment.')

def main(_, options):
  if not options.cluster:
    cluster_list = Cluster.get_list()
    print ('Please specify the cluster you would like to deploy to with\n\t--cluster %s'
           % cluster_list)
    return

  builder = ThermosBuilder(options.cluster, options.release, options.hotfix, options.verbose)
  builder.build()

  deployer = HDFSDeployer(options.cluster, not options.really_push, options.verbose)
  deployer.stage(builder)

app.main()
<|endoftext|>


<commit_before># coding=utf-8
# Copyright 2018 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).

from __future__ import absolute_import, division, print_function, unicode_literals

import functools
import os
import time
from contextlib import contextmanager

import psutil
from colors import bold, cyan, magenta

from pants.pantsd.process_manager import ProcessManager
from pants.util.collections import recursively_update
from pants_test.pants_run_integration_test import PantsRunIntegrationTest, read_pantsd_log
from pants_test.testutils.process_test_util import no_lingering_process_by_command

def banner(s):
  print(cyan('=' * 63))
  print(cyan('- {} {}'.format(s, '-' * (60 - len(s)))))
  print(cyan('=' * 63))

class PantsDaemonMonitor(ProcessManager):
  def __init__(self, runner_process_context, metadata_base_dir=None):
    """
    :param runner_process_context: A TrackedProcessContext that can be used to inspect live
      pantsd-runner instances created in this context.
    """
    super(PantsDaemonMonitor, self).__init__(name='pantsd', metadata_base_dir=metadata_base_dir)
    self.runner_process_context = runner_process_context

  def _log(self):
    print(magenta(
      'PantsDaemonMonitor: pid is {} is_alive={}'.format(self._pid, self.is_alive()))
    )

  # TODO(#7330): Determine why pantsd takes so long to start! Waiting for
  # 'testprojects/src/python/coordinated_runs:waiter' specifically seems to require this 16-second
  # timeout.
  def assert_started(self, timeout=16):
    self._process = None
    self._pid = self.await_pid(timeout)
    self._check_pantsd_is_alive()
    return self._pid

  def assert_pantsd_runner_started(self, client_pid, timeout=4):
    return self.await_metadata_by_name(
      name='nailgun-client',
      metadata_key=str(client_pid),
      timeout=timeout,
      caster=int,
    )

  def _check_pantsd_is_alive(self):
    self._log()
    assert self._pid is not None and self.is_alive(), 'cannot assert that pantsd is running. Try calling assert_started before calling this method.'
    return self._pid

  def current_memory_usage(self):
    """Return the current memory usage of the pantsd process (which must be running)

    :return: memory usage in bytes
    """
    self.assert_running()
    return psutil.Process(self._pid).memory_info()[0]

  def assert_running(self):
    if not self._pid:
      return self.assert_started()
    else:
      return self._check_pantsd_is_alive()

  def assert_stopped(self):
    self._log()
    assert self._pid is not None, 'cannot assert pantsd stoppage. Try calling assert_started before calling this method.'
    assert self.is_dead(), 'pantsd should be stopped!'
    return self._pid

class PantsDaemonIntegrationTestBase(PantsRunIntegrationTest):

  @classmethod
  def use_pantsd_env_var(cls):
    """We set our own ad-hoc pantsd configuration in most of these tests"""
    return False

  @contextmanager
  def pantsd_test_context(self, log_level='info', extra_config=None):
    with no_lingering_process_by_command('pantsd-runner') as runner_process_context:
      with self.temporary_workdir() as workdir_base:
        pid_dir = os.path.join(workdir_base, '.pids')
        workdir = os.path.join(workdir_base, '.workdir.pants.d')
        print('\npantsd log is {}/pantsd/pantsd.log'.format(workdir))
        pantsd_config = {
          'GLOBAL': {
            'enable_pantsd': True,
            'shutdown_pantsd_after_run': False,
            # The absolute paths in CI can exceed the UNIX socket path limitation
            # (>104-108 characters), so we override that here with a shorter path.
            'watchman_socket_path': '/tmp/watchman.{}.sock'.format(os.getpid()),
            'level': log_level,
            'pants_subprocessdir': pid_dir,
          }
        }

        if extra_config:
          recursively_update(pantsd_config, extra_config)
        print('>>> config: \n{}\n'.format(pantsd_config))

        checker = PantsDaemonMonitor(runner_process_context, pid_dir)
        self.assert_runner(workdir, pantsd_config, ['kill-pantsd'], expected_runs=1)
        try:
          yield workdir, pantsd_config, checker
          self.assert_runner(
            workdir,
            pantsd_config,
            ['kill-pantsd'],
            expected_runs=1,
          )
          checker.assert_stopped()
        finally:
          banner('BEGIN pantsd.log')
          for line in read_pantsd_log(workdir):
            print(line)
          banner('END pantsd.log')

  @contextmanager
  def pantsd_successful_run_context(self, *args, **kwargs):
    with self.pantsd_run_context(*args, success=True, **kwargs) as context:
      yield context

  @contextmanager
  def pantsd_run_context(self, log_level='info', extra_config=None, extra_env=None, success=True,
                         no_track_run_counts=False):
    with self.pantsd_test_context(log_level, extra_config) as (workdir, pantsd_config, checker):
      yield (
        functools.partial(
          self.assert_runner,
          workdir,
          pantsd_config,
          extra_env=extra_env,
          success=success,
        ),
        checker,
        workdir,
        pantsd_config,
      )

  def _run_count(self, workdir):
    run_tracker_dir = os.path.join(workdir, 'run-tracker')
    if os.path.isdir(run_tracker_dir):
      return len([f for f in os.listdir(run_tracker_dir) if f != 'latest'])
    else:
      return 0

  def assert_runner(self, workdir, config, cmd, extra_config={}, extra_env={}, expected_runs=1, success=True):
    combined_config = config.copy()
    recursively_update(combined_config, extra_config)
    print(bold(cyan('\nrunning: ./pants {} (config={}) (extra_env={})'
                    .format(' '.join(cmd), combined_config, extra_env))))
    run_count = self._run_count(workdir)
    start_time = time.time()
    run = self.run_pants_with_workdir(
      cmd,
      workdir,
      combined_config,
      extra_env=extra_env,
      # TODO: With this uncommented, `test_pantsd_run` fails.
      # tee_output=True
    )
    elapsed = time.time() - start_time
    print(bold(cyan('\ncompleted in {} seconds'.format(elapsed))))

    # TODO: uncomment this and add an issue link!
    runs_created = self._run_count(workdir) - run_count
    self.assertEqual(
        runs_created,
        expected_runs,
        'Expected {} RunTracker run(s) to be created per pantsd run: was {}'.format(
          expected_runs,
          runs_created,
        )
    )
    if success:
      self.assert_success(run)
    else:
      self.assert_failure(run)
    return run
<commit_msg>Extend pantsd test timeout (#7527)<commit_after># coding=utf-8
# Copyright 2018 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).

from __future__ import absolute_import, division, print_function, unicode_literals

import functools
import os
import time
from contextlib import contextmanager

import psutil
from colors import bold, cyan, magenta

from pants.pantsd.process_manager import ProcessManager
from pants.util.collections import recursively_update
from pants_test.pants_run_integration_test import PantsRunIntegrationTest, read_pantsd_log
from pants_test.testutils.process_test_util import no_lingering_process_by_command

def banner(s):
  print(cyan('=' * 63))
  print(cyan('- {} {}'.format(s, '-' * (60 - len(s)))))
  print(cyan('=' * 63))

class PantsDaemonMonitor(ProcessManager):
  def __init__(self, runner_process_context, metadata_base_dir=None):
    """
    :param runner_process_context: A TrackedProcessContext that can be used to inspect live
      pantsd-runner instances created in this context.
    """
    super(PantsDaemonMonitor, self).__init__(name='pantsd', metadata_base_dir=metadata_base_dir)
    self.runner_process_context = runner_process_context

  def _log(self):
    print(magenta(
      'PantsDaemonMonitor: pid is {} is_alive={}'.format(self._pid, self.is_alive()))
    )

  # TODO(#7330): Determine why pantsd takes so long to start! Waiting for
  # 'testprojects/src/python/coordinated_runs:waiter' specifically seems to require this 16-second
  # timeout.
  def assert_started(self, timeout=16):
    self._process = None
    self._pid = self.await_pid(timeout)
    self._check_pantsd_is_alive()
    return self._pid

  def assert_pantsd_runner_started(self, client_pid, timeout=12):
    return self.await_metadata_by_name(
      name='nailgun-client',
      metadata_key=str(client_pid),
      timeout=timeout,
      caster=int,
    )

  def _check_pantsd_is_alive(self):
    self._log()
    assert self._pid is not None and self.is_alive(), 'cannot assert that pantsd is running. Try calling assert_started before calling this method.'
    return self._pid

  def current_memory_usage(self):
    """Return the current memory usage of the pantsd process (which must be running)

    :return: memory usage in bytes
    """
    self.assert_running()
    return psutil.Process(self._pid).memory_info()[0]

  def assert_running(self):
    if not self._pid:
      return self.assert_started()
    else:
      return self._check_pantsd_is_alive()

  def assert_stopped(self):
    self._log()
    assert self._pid is not None, 'cannot assert pantsd stoppage. Try calling assert_started before calling this method.'
    assert self.is_dead(), 'pantsd should be stopped!'
    return self._pid

class PantsDaemonIntegrationTestBase(PantsRunIntegrationTest):

  @classmethod
  def use_pantsd_env_var(cls):
    """We set our own ad-hoc pantsd configuration in most of these tests"""
    return False

  @contextmanager
  def pantsd_test_context(self, log_level='info', extra_config=None):
    with no_lingering_process_by_command('pantsd-runner') as runner_process_context:
      with self.temporary_workdir() as workdir_base:
        pid_dir = os.path.join(workdir_base, '.pids')
        workdir = os.path.join(workdir_base, '.workdir.pants.d')
        print('\npantsd log is {}/pantsd/pantsd.log'.format(workdir))
        pantsd_config = {
          'GLOBAL': {
            'enable_pantsd': True,
            'shutdown_pantsd_after_run': False,
            # The absolute paths in CI can exceed the UNIX socket path limitation
            # (>104-108 characters), so we override that here with a shorter path.
            'watchman_socket_path': '/tmp/watchman.{}.sock'.format(os.getpid()),
            'level': log_level,
            'pants_subprocessdir': pid_dir,
          }
        }

        if extra_config:
          recursively_update(pantsd_config, extra_config)
        print('>>> config: \n{}\n'.format(pantsd_config))

        checker = PantsDaemonMonitor(runner_process_context, pid_dir)
        self.assert_runner(workdir, pantsd_config, ['kill-pantsd'], expected_runs=1)
        try:
          yield workdir, pantsd_config, checker
          self.assert_runner(
            workdir,
            pantsd_config,
            ['kill-pantsd'],
            expected_runs=1,
          )
          checker.assert_stopped()
        finally:
          banner('BEGIN pantsd.log')
          for line in read_pantsd_log(workdir):
            print(line)
          banner('END pantsd.log')

  @contextmanager
  def pantsd_successful_run_context(self, *args, **kwargs):
    with self.pantsd_run_context(*args, success=True, **kwargs) as context:
      yield context

  @contextmanager
  def pantsd_run_context(self, log_level='info', extra_config=None, extra_env=None, success=True,
                         no_track_run_counts=False):
    with self.pantsd_test_context(log_level, extra_config) as (workdir, pantsd_config, checker):
      yield (
        functools.partial(
          self.assert_runner,
          workdir,
          pantsd_config,
          extra_env=extra_env,
          success=success,
        ),
        checker,
        workdir,
        pantsd_config,
      )

  def _run_count(self, workdir):
    run_tracker_dir = os.path.join(workdir, 'run-tracker')
    if os.path.isdir(run_tracker_dir):
      return len([f for f in os.listdir(run_tracker_dir) if f != 'latest'])
    else:
      return 0

  def assert_runner(self, workdir, config, cmd, extra_config={}, extra_env={}, expected_runs=1, success=True):
    combined_config = config.copy()
    recursively_update(combined_config, extra_config)
    print(bold(cyan('\nrunning: ./pants {} (config={}) (extra_env={})'
                    .format(' '.join(cmd), combined_config, extra_env))))
    run_count = self._run_count(workdir)
    start_time = time.time()
    run = self.run_pants_with_workdir(
      cmd,
      workdir,
      combined_config,
      extra_env=extra_env,
      # TODO: With this uncommented, `test_pantsd_run` fails.
      # tee_output=True
    )
    elapsed = time.time() - start_time
    print(bold(cyan('\ncompleted in {} seconds'.format(elapsed))))

    # TODO: uncomment this and add an issue link!
    runs_created = self._run_count(workdir) - run_count
    self.assertEqual(
        runs_created,
        expected_runs,
        'Expected {} RunTracker run(s) to be created per pantsd run: was {}'.format(
          expected_runs,
          runs_created,
        )
    )
    if success:
      self.assert_success(run)
    else:
      self.assert_failure(run)
    return run
<|endoftext|>


<commit_before>import logging
from gi.repository import Gst
from enum import Enum

from lib.config import Config
from lib.clock import Clock

class StreamBlanker(object):
    log = logging.getLogger('StreamBlanker')

    def __init__(self):
        self.acaps = Config.get('mix', 'audiocaps')
        self.vcaps = Config.get('mix', 'videocaps')

        self.names = Config.getlist('stream-blanker', 'sources')
        self.log.info('Configuring StreamBlanker video %u Sources',
                      len(self.names))

        pipeline = """
            compositor name=vmix !
            {vcaps} !
            intervideosink channel=video_streamblanker_out

            audiomixer name=amix !
            {acaps} !
            interaudiosink channel=audio_streamblanker_out

            intervideosrc channel=video_mix_streamblanker !
            {vcaps} !
            vmix.

            interaudiosrc channel=audio_mix_streamblanker !
            {acaps} !
            amix.

            interaudiosrc channel=audio_streamblanker !
            {acaps} !
            amix.
        """.format(
            acaps=self.acaps,
            vcaps=self.vcaps
        )

        for name in self.names:
            pipeline += """
                intervideosrc channel=video_{name}_streamblanker !
                {vcaps} !
                vmix.
            """.format(
                name=name,
                vcaps=self.vcaps
            )

        self.log.debug('Creating Mixing-Pipeline:\n%s', pipeline)
        self.mixingPipeline = Gst.parse_launch(pipeline)
        self.mixingPipeline.use_clock(Clock)

        self.log.debug('Binding Error & End-of-Stream-Signal '
                       'on Mixing-Pipeline')
        self.mixingPipeline.bus.add_signal_watch()
        self.mixingPipeline.bus.connect("message::eos", self.on_eos)
        self.mixingPipeline.bus.connect("message::error", self.on_error)

        self.log.debug('Initializing Mixer-State')
        self.blankSource = None
        self.applyMixerState()

        self.log.debug('Launching Mixing-Pipeline')
        self.mixingPipeline.set_state(Gst.State.PLAYING)

    def on_eos(self, bus, message):
        self.log.debug('Received End-of-Stream-Signal on Mixing-Pipeline')

    def on_error(self, bus, message):
        self.log.debug('Received Error-Signal on Mixing-Pipeline')
        (error, debug) = message.parse_error()
        self.log.debug('Error-Details: #%u: %s', error.code, debug)

    def applyMixerState(self):
        self.applyMixerStateAudio()
        self.applyMixerStateVideo()

    def applyMixerStateAudio(self):
        mixpad = (self.mixingPipeline.get_by_name('amix')
                                     .get_static_pad('sink_0'))
        blankpad = (self.mixingPipeline.get_by_name('amix')
                                       .get_static_pad('sink_1'))

        mixpad.set_property('volume', int(self.blankSource is None))
        blankpad.set_property('volume', int(self.blankSource is not None))

    def applyMixerStateVideo(self):
        mixpad = (self.mixingPipeline.get_by_name('vmix')
                                     .get_static_pad('sink_0'))
        mixpad.set_property('alpha', int(self.blankSource is None))

        for idx, name in enumerate(self.names):
            blankpad = (self.mixingPipeline
                            .get_by_name('vmix')
                            .get_static_pad('sink_%u' % (idx + 1)))
            blankpad.set_property('alpha', int(self.blankSource == idx))

    def setBlankSource(self, source):
        self.blankSource = source
        self.applyMixerState()
<commit_msg>Add queue elements to streamblanker pipeline, fixes #86<commit_after>import logging
from gi.repository import Gst
from enum import Enum

from lib.config import Config
from lib.clock import Clock

class StreamBlanker(object):
    log = logging.getLogger('StreamBlanker')

    def __init__(self):
        self.acaps = Config.get('mix', 'audiocaps')
        self.vcaps = Config.get('mix', 'videocaps')

        self.names = Config.getlist('stream-blanker', 'sources')
        self.log.info('Configuring StreamBlanker video %u Sources',
                      len(self.names))

        pipeline = """
            compositor name=vmix !
            {vcaps} !
            queue !
            intervideosink channel=video_streamblanker_out

            audiomixer name=amix !
            {acaps} !
            queue !
            interaudiosink channel=audio_streamblanker_out

            intervideosrc channel=video_mix_streamblanker !
            {vcaps} !
            vmix.

            interaudiosrc channel=audio_mix_streamblanker !
            {acaps} !
            amix.

            interaudiosrc channel=audio_streamblanker !
            {acaps} !
            amix.
        """.format(
            acaps=self.acaps,
            vcaps=self.vcaps
        )

        for name in self.names:
            pipeline += """
                intervideosrc channel=video_{name}_streamblanker !
                {vcaps} !
                vmix.
            """.format(
                name=name,
                vcaps=self.vcaps
            )

        self.log.debug('Creating Mixing-Pipeline:\n%s', pipeline)
        self.mixingPipeline = Gst.parse_launch(pipeline)
        self.mixingPipeline.use_clock(Clock)

        self.log.debug('Binding Error & End-of-Stream-Signal '
                       'on Mixing-Pipeline')
        self.mixingPipeline.bus.add_signal_watch()
        self.mixingPipeline.bus.connect("message::eos", self.on_eos)
        self.mixingPipeline.bus.connect("message::error", self.on_error)

        self.log.debug('Initializing Mixer-State')
        self.blankSource = None
        self.applyMixerState()

        self.log.debug('Launching Mixing-Pipeline')
        self.mixingPipeline.set_state(Gst.State.PLAYING)

    def on_eos(self, bus, message):
        self.log.debug('Received End-of-Stream-Signal on Mixing-Pipeline')

    def on_error(self, bus, message):
        self.log.debug('Received Error-Signal on Mixing-Pipeline')
        (error, debug) = message.parse_error()
        self.log.debug('Error-Details: #%u: %s', error.code, debug)

    def applyMixerState(self):
        self.applyMixerStateAudio()
        self.applyMixerStateVideo()

    def applyMixerStateAudio(self):
        mixpad = (self.mixingPipeline.get_by_name('amix')
                                     .get_static_pad('sink_0'))
        blankpad = (self.mixingPipeline.get_by_name('amix')
                                       .get_static_pad('sink_1'))

        mixpad.set_property('volume', int(self.blankSource is None))
        blankpad.set_property('volume', int(self.blankSource is not None))

    def applyMixerStateVideo(self):
        mixpad = (self.mixingPipeline.get_by_name('vmix')
                                     .get_static_pad('sink_0'))
        mixpad.set_property('alpha', int(self.blankSource is None))

        for idx, name in enumerate(self.names):
            blankpad = (self.mixingPipeline
                            .get_by_name('vmix')
                            .get_static_pad('sink_%u' % (idx + 1)))
            blankpad.set_property('alpha', int(self.blankSource == idx))

    def setBlankSource(self, source):
        self.blankSource = source
        self.applyMixerState()
<|endoftext|>