<commit_before>from mongoengine.base import ValidationError

def class_from_id(type_, _id):
    """
    Return an instantiated class object.

    :param type_: The CRITs top-level object type.
    :type type_: str
    :param _id: The ObjectId to search for.
    :type _id: str
    :returns: class which inherits from
              :class:`crits.core.crits_mongoengine.CritsBaseAttributes`
    """

    # doing this to avoid circular imports
    from crits.campaigns.campaign import Campaign
    from crits.certificates.certificate import Certificate
    from crits.comments.comment import Comment
    from crits.core.crits_mongoengine import RelationshipType
    from crits.core.source_access import SourceAccess
    from crits.core.user_role import UserRole
    from crits.domains.domain import Domain
    from crits.emails.email import Email
    from crits.events.event import Event, EventType
    from crits.indicators.indicator import Indicator, IndicatorAction
    from crits.ips.ip import IP
    from crits.objects.object_type import ObjectType
    from crits.pcaps.pcap import PCAP
    from crits.raw_data.raw_data import RawData, RawDataType
    from crits.samples.backdoor import Backdoor
    from crits.samples.exploit import Exploit
    from crits.samples.sample import Sample
    from crits.screenshots.screenshot import Screenshot
    from crits.targets.target import Target

    if not _id:
        return None

    # make sure it's a string
    _id = str(_id)

    try:
        if type_ == 'Backdoor':
            return Backdoor.objects(id=_id).first()
        if type_ == 'Campaign':
            return Campaign.objects(id=_id).first()
        elif type_ == 'Certificate':
            return Certificate.objects(id=_id).first()
        elif type_ == 'Comment':
            return Comment.objects(id=_id).first()
        elif type_ == 'Domain':
            return Domain.objects(id=_id).first()
        elif type_ == 'Email':
            return Email.objects(id=_id).first()
        elif type_ == 'Event':
            return Event.objects(id=_id).first()
        elif type_ == 'EventType':
            return EventType.objects(id=_id).first()
        elif type_ == 'Exploit':
            return Exploit.objects(id=_id).first()
        elif type_ == 'Indicator':
            return Indicator.objects(id=_id).first()
        elif type_ == 'IndicatorAction':
            return IndicatorAction.objects(id=_id).first()
        elif type_ == 'IP':
            return IP.objects(id=_id).first()
        elif type_ == 'ObjectType':
            return ObjectType.objects(id=_id).first()
        elif type_ == 'PCAP':
            return PCAP.objects(id=_id).first()
        elif type_ == 'RawData':
            return RawData.objects(id=_id).first()
        elif type_ == 'RawDataType':
            return RawDataType.objects(id=_id).first()
        elif type_ == 'RelationshipType':
            return RelationshipType.objects(id=_id).first()
        elif type_ == 'Sample':
            return Sample.objects(id=_id).first()
        elif type_ == 'SourceAccess':
            return SourceAccess.objects(id=_id).first()
        elif type_ == 'Screenshot':
            return Screenshot.objects(id=_id).first()
        elif type_ == 'Target':
            return Target.objects(id=_id).first()
        elif type_ == 'UserRole':
            return UserRole.objects(id=_id).first()
        else:
            return None
    except ValidationError:
        # Mongoengine tries to verify that _id is a valid ObjectID.
        # If it isn't it will raise this exception. This is most commonly
        # seen by passing invalid IDs in API requests.
        return None

def class_from_value(type_, value):
    """
    Return an instantiated class object.

    :param type_: The CRITs top-level object type.
    :type type_: str
    :param value: The value to search for.
    :type value: str
    :returns: class which inherits from
              :class:`crits.core.crits_mongoengine.CritsBaseAttributes`
    """

    # doing this to avoid circular imports
    from crits.campaigns.campaign import Campaign
    from crits.certificates.certificate import Certificate
    from crits.comments.comment import Comment
    from crits.domains.domain import Domain
    from crits.emails.email import Email
    from crits.events.event import Event
    from crits.indicators.indicator import Indicator
    from crits.ips.ip import IP
    from crits.pcaps.pcap import PCAP
    from crits.raw_data.raw_data import RawData
    from crits.samples.sample import Sample
    from crits.screenshots.screenshot import Screenshot
    from crits.targets.target import Target

    if type_ == 'Campaign':
        return Campaign.objects(name=value).first()
    elif type_ == 'Certificate':
        return Certificate.objects(md5=value).first()
    elif type_ == 'Comment':
        try:
            return Comment.objects(id=value).first()
        except ValidationError:
            return None
    elif type_ == 'Domain':
        return Domain.objects(domain=value).first()
    elif type_ == 'Email':
        try:
            return Email.objects(id=value).first()
        except ValidationError:
            return None
    elif type_ == 'Event':
        try:
            return Event.objects(id=value).first()
        except ValidationError:
            return None
    elif type_ == 'Indicator':
        try:
            return Indicator.objects(id=value).first()
        except ValidationError:
            return None
    elif type_ == 'IP':
        return IP.objects(ip=value).first()
    elif type_ == 'PCAP':
        return PCAP.objects(md5=value).first()
    elif type_ == 'RawData':
        return RawData.objects(md5=value).first()
    elif type_ == 'Sample':
        return Sample.objects(md5=value).first()
    elif type_ == 'Screenshot':
        try:
            return Screenshot.objects(id=value).first()
        except ValidationError:
            return None
    elif type_ == 'Target':
        return Target.objects(email_address=value).first()
    else:
        return None

def class_from_type(type_):
    """
    Return a class object.

    :param type_: The CRITs top-level object type.
    :type type_: str
    :returns: class which inherits from
              :class:`crits.core.crits_mongoengine.CritsBaseAttributes`
    """

    # doing this to avoid circular imports
    from crits.campaigns.campaign import Campaign
    from crits.certificates.certificate import Certificate
    from crits.comments.comment import Comment
    from crits.core.crits_mongoengine import RelationshipType
    from crits.core.source_access import SourceAccess
    from crits.core.user_role import UserRole
    from crits.domains.domain import Domain
    from crits.emails.email import Email
    from crits.events.event import Event, EventType
    from crits.indicators.indicator import Indicator, IndicatorAction
    from crits.ips.ip import IP
    from crits.objects.object_type import ObjectType
    from crits.pcaps.pcap import PCAP
    from crits.raw_data.raw_data import RawData, RawDataType
    from crits.samples.backdoor import Backdoor
    from crits.samples.exploit import Exploit
    from crits.samples.sample import Sample
    from crits.screenshots.screenshot import Screenshot
    from crits.targets.target import Target

    if type_ == 'Backdoor':
        return Backdoor
    elif type_ == 'Campaign':
        return Campaign
    elif type_ == 'Certificate':
        return Certificate
    elif type_ == 'Comment':
        return Comment
    elif type_ == 'Domain':
        return Domain
    elif type_ == 'Email':
        return Email
    elif type_ == 'Event':
        return Event
    elif type_ == 'EventType':
        return EventType
    elif type_ == 'Exploit':
        return Exploit
    elif type_ == 'Indicator':
        return Indicator
    elif type_ == 'IndicatorAction':
        return IndicatorAction
    elif type_ == 'IP':
        return IP
    elif type_ == 'ObjectType':
        return ObjectType
    elif type_ == 'PCAP':
        return PCAP
    elif type_ == 'RawData':
        return RawData
    elif type_ == 'RawDataType':
        return RawDataType
    elif type_ == 'RelationshipType':
        return RelationshipType
    elif type_ == 'Sample':
        return Sample
    elif type_ == 'SourceAccess':
        return SourceAccess
    elif type_ == 'Screenshot':
        return Screenshot
    elif type_ == 'Target':
        return Target
    elif type_ == 'UserRole':
        return UserRole
    else:
        return None
<commit_msg>Redo of class_mapper_fixes branch.<commit_after>from bson.objectid import ObjectId

def class_from_id(type_, _id):
    """
    Return an instantiated class object.

    :param type_: The CRITs top-level object type.
    :type type_: str
    :param _id: The ObjectId to search for.
    :type _id: str
    :returns: class which inherits from
              :class:`crits.core.crits_mongoengine.CritsBaseAttributes`
    """

    # doing this to avoid circular imports
    from crits.campaigns.campaign import Campaign
    from crits.certificates.certificate import Certificate
    from crits.comments.comment import Comment
    from crits.core.crits_mongoengine import RelationshipType
    from crits.core.source_access import SourceAccess
    from crits.core.user_role import UserRole
    from crits.domains.domain import Domain
    from crits.emails.email import Email
    from crits.events.event import Event, EventType
    from crits.indicators.indicator import Indicator, IndicatorAction
    from crits.ips.ip import IP
    from crits.objects.object_type import ObjectType
    from crits.pcaps.pcap import PCAP
    from crits.raw_data.raw_data import RawData, RawDataType
    from crits.samples.backdoor import Backdoor
    from crits.samples.exploit import Exploit
    from crits.samples.sample import Sample
    from crits.screenshots.screenshot import Screenshot
    from crits.targets.target import Target

    if not _id:
        return None

    # make sure it's a string
    _id = str(_id)

    # Use bson.ObjectId to make sure this is a valid ObjectId, otherwise
    # the queries below will raise a ValidationError exception.
    if not ObjectId.is_valid(_id):
        return None

    if type_ == 'Backdoor':
        return Backdoor.objects(id=_id).first()
    if type_ == 'Campaign':
        return Campaign.objects(id=_id).first()
    elif type_ == 'Certificate':
        return Certificate.objects(id=_id).first()
    elif type_ == 'Comment':
        return Comment.objects(id=_id).first()
    elif type_ == 'Domain':
        return Domain.objects(id=_id).first()
    elif type_ == 'Email':
        return Email.objects(id=_id).first()
    elif type_ == 'Event':
        return Event.objects(id=_id).first()
    elif type_ == 'EventType':
        return EventType.objects(id=_id).first()
    elif type_ == 'Exploit':
        return Exploit.objects(id=_id).first()
    elif type_ == 'Indicator':
        return Indicator.objects(id=_id).first()
    elif type_ == 'IndicatorAction':
        return IndicatorAction.objects(id=_id).first()
    elif type_ == 'IP':
        return IP.objects(id=_id).first()
    elif type_ == 'ObjectType':
        return ObjectType.objects(id=_id).first()
    elif type_ == 'PCAP':
        return PCAP.objects(id=_id).first()
    elif type_ == 'RawData':
        return RawData.objects(id=_id).first()
    elif type_ == 'RawDataType':
        return RawDataType.objects(id=_id).first()
    elif type_ == 'RelationshipType':
        return RelationshipType.objects(id=_id).first()
    elif type_ == 'Sample':
        return Sample.objects(id=_id).first()
    elif type_ == 'SourceAccess':
        return SourceAccess.objects(id=_id).first()
    elif type_ == 'Screenshot':
        return Screenshot.objects(id=_id).first()
    elif type_ == 'Target':
        return Target.objects(id=_id).first()
    elif type_ == 'UserRole':
        return UserRole.objects(id=_id).first()
    else:
        return None

def class_from_value(type_, value):
    """
    Return an instantiated class object.

    :param type_: The CRITs top-level object type.
    :type type_: str
    :param value: The value to search for.
    :type value: str
    :returns: class which inherits from
              :class:`crits.core.crits_mongoengine.CritsBaseAttributes`
    """

    # doing this to avoid circular imports
    from crits.campaigns.campaign import Campaign
    from crits.certificates.certificate import Certificate
    from crits.comments.comment import Comment
    from crits.domains.domain import Domain
    from crits.emails.email import Email
    from crits.events.event import Event
    from crits.indicators.indicator import Indicator
    from crits.ips.ip import IP
    from crits.pcaps.pcap import PCAP
    from crits.raw_data.raw_data import RawData
    from crits.samples.sample import Sample
    from crits.screenshots.screenshot import Screenshot
    from crits.targets.target import Target

    # Use bson.ObjectId to make sure this is a valid ObjectId, otherwise
    # the queries below will raise a ValidationError exception.
    if (type_ in ['Comment', 'Email', 'Event', 'Indicator', 'Screenshot'] and
       not ObjectId.is_valid(value)):
        return None

    if type_ == 'Campaign':
        return Campaign.objects(name=value).first()
    elif type_ == 'Certificate':
        return Certificate.objects(md5=value).first()
    elif type_ == 'Comment':
        return Comment.objects(id=value).first()
    elif type_ == 'Domain':
        return Domain.objects(domain=value).first()
    elif type_ == 'Email':
        return Email.objects(id=value).first()
    elif type_ == 'Event':
        return Event.objects(id=value).first()
    elif type_ == 'Indicator':
        return Indicator.objects(id=value).first()
    elif type_ == 'IP':
        return IP.objects(ip=value).first()
    elif type_ == 'PCAP':
        return PCAP.objects(md5=value).first()
    elif type_ == 'RawData':
        return RawData.objects(md5=value).first()
    elif type_ == 'Sample':
        return Sample.objects(md5=value).first()
    elif type_ == 'Screenshot':
        return Screenshot.objects(id=value).first()
    elif type_ == 'Target':
        return Target.objects(email_address=value).first()
    else:
        return None

def class_from_type(type_):
    """
    Return a class object.

    :param type_: The CRITs top-level object type.
    :type type_: str
    :returns: class which inherits from
              :class:`crits.core.crits_mongoengine.CritsBaseAttributes`
    """

    # doing this to avoid circular imports
    from crits.campaigns.campaign import Campaign
    from crits.certificates.certificate import Certificate
    from crits.comments.comment import Comment
    from crits.core.crits_mongoengine import RelationshipType
    from crits.core.source_access import SourceAccess
    from crits.core.user_role import UserRole
    from crits.domains.domain import Domain
    from crits.emails.email import Email
    from crits.events.event import Event, EventType
    from crits.indicators.indicator import Indicator, IndicatorAction
    from crits.ips.ip import IP
    from crits.objects.object_type import ObjectType
    from crits.pcaps.pcap import PCAP
    from crits.raw_data.raw_data import RawData, RawDataType
    from crits.samples.backdoor import Backdoor
    from crits.samples.exploit import Exploit
    from crits.samples.sample import Sample
    from crits.screenshots.screenshot import Screenshot
    from crits.targets.target import Target

    if type_ == 'Backdoor':
        return Backdoor
    elif type_ == 'Campaign':
        return Campaign
    elif type_ == 'Certificate':
        return Certificate
    elif type_ == 'Comment':
        return Comment
    elif type_ == 'Domain':
        return Domain
    elif type_ == 'Email':
        return Email
    elif type_ == 'Event':
        return Event
    elif type_ == 'EventType':
        return EventType
    elif type_ == 'Exploit':
        return Exploit
    elif type_ == 'Indicator':
        return Indicator
    elif type_ == 'IndicatorAction':
        return IndicatorAction
    elif type_ == 'IP':
        return IP
    elif type_ == 'ObjectType':
        return ObjectType
    elif type_ == 'PCAP':
        return PCAP
    elif type_ == 'RawData':
        return RawData
    elif type_ == 'RawDataType':
        return RawDataType
    elif type_ == 'RelationshipType':
        return RelationshipType
    elif type_ == 'Sample':
        return Sample
    elif type_ == 'SourceAccess':
        return SourceAccess
    elif type_ == 'Screenshot':
        return Screenshot
    elif type_ == 'Target':
        return Target
    elif type_ == 'UserRole':
        return UserRole
    else:
        return None
<|endoftext|>


<commit_before>"""Definitions for the `Diffusion` class."""
from collections import OrderedDict

import numexpr as ne
import numpy as np
from mosfit.constants import C_CGS, DAY_CGS, FOUR_PI, KM_CGS, M_SUN_CGS
from mosfit.modules.transforms.transform import Transform

# Important: Only define one ``Module`` class per file.

class Diffusion(Transform):
    """Photon diffusion transform."""

    N_INT_TIMES = 1000
    DIFF_CONST = 2.0 * M_SUN_CGS / (13.7 * C_CGS * KM_CGS)
    TRAP_CONST = 3.0 * M_SUN_CGS / (FOUR_PI * KM_CGS ** 2)

    def process(self, **kwargs):
        """Process module."""
        super(Diffusion, self).process(**kwargs)
        self._kappa = kwargs['kappa']
        self._kappa_gamma = kwargs['kappagamma']
        self._m_ejecta = kwargs[self.key('mejecta')]#kwargs['mejecta']
        self._v_ejecta = kwargs['vejecta']

        self._tau_diff = np.sqrt(self.DIFF_CONST * self._kappa *
                                 self._m_ejecta / self._v_ejecta) / DAY_CGS
        self._trap_coeff = (
            self.TRAP_CONST * self._kappa_gamma * self._m_ejecta /
            (self._v_ejecta ** 2)) / DAY_CGS ** 2
        td2, A = self._tau_diff ** 2, self._trap_coeff  # noqa: F841

        new_lum = []
        evaled = False
        lum_cache = OrderedDict()
        min_te = min(self._dense_times_since_exp)
        for te in self._times_to_process:
            if te <= 0.0:
                new_lum.append(0.0)
                continue
            if te in lum_cache:
                new_lum.append(lum_cache[te])
                continue
            te2 = te ** 2  # noqa: F841
            tb = max(0.0, min_te)
            int_times = np.linspace(tb, te, self.N_INT_TIMES)
            dt = int_times[1] - int_times[0]

            int_lums = np.interp(  # noqa: F841
                int_times, self._dense_times_since_exp,
                self._dense_luminosities)

            if not evaled:
                int_arg = ne.evaluate('2.0 * int_lums * int_times / td2 * '
                                      'exp((int_times**2 - te2) / td2) * '
                                      '(1.0 - exp(-A / te2))')
                evaled = True
            else:
                int_arg = ne.re_evaluate()
            # int_arg = [
            #     2.0 * l * t / td2 *
            #     np.exp((t**2 - te**2) / td2) * (1.0 - np.exp(-A / te**2))
            #     for t, l in zip(int_times, int_lums)
            # ]
            int_arg[np.isnan(int_arg)] = 0.0
            lum_val = np.trapz(int_arg, dx=dt)
            lum_cache[te] = lum_val
            new_lum.append(lum_val)
        return {self.output_key('luminosities'): new_lum}
<commit_msg>updating csmni model<commit_after>"""Definitions for the `Diffusion` class."""
from collections import OrderedDict

import numexpr as ne
import numpy as np
from mosfit.constants import C_CGS, DAY_CGS, FOUR_PI, KM_CGS, M_SUN_CGS
from mosfit.modules.transforms.transform import Transform

# Important: Only define one ``Module`` class per file.

class Diffusion(Transform):
    """Photon diffusion transform."""

    N_INT_TIMES = 1000
    DIFF_CONST = 2.0 * M_SUN_CGS / (13.7 * C_CGS * KM_CGS)
    TRAP_CONST = 3.0 * M_SUN_CGS / (FOUR_PI * KM_CGS ** 2)

    def process(self, **kwargs):
        """Process module."""
        super(Diffusion, self).process(**kwargs)
        self._kappa = kwargs['kappa']
        self._kappa_gamma = kwargs['kappagamma']
        self._m_ejecta = kwargs[self.key('mejecta')]
        self._v_ejecta = kwargs['vejecta']

        self._tau_diff = np.sqrt(self.DIFF_CONST * self._kappa *
                                 self._m_ejecta / self._v_ejecta) / DAY_CGS
        self._trap_coeff = (
            self.TRAP_CONST * self._kappa_gamma * self._m_ejecta /
            (self._v_ejecta ** 2)) / DAY_CGS ** 2
        td2, A = self._tau_diff ** 2, self._trap_coeff  # noqa: F841

        new_lum = []
        evaled = False
        lum_cache = OrderedDict()
        min_te = min(self._dense_times_since_exp)
        for te in self._times_to_process:
            if te <= 0.0:
                new_lum.append(0.0)
                continue
            if te in lum_cache:
                new_lum.append(lum_cache[te])
                continue
            te2 = te ** 2  # noqa: F841
            tb = max(0.0, min_te)
            int_times = np.linspace(tb, te, self.N_INT_TIMES)
            dt = int_times[1] - int_times[0]

            int_lums = np.interp(  # noqa: F841
                int_times, self._dense_times_since_exp,
                self._dense_luminosities)

            if not evaled:
                int_arg = ne.evaluate('2.0 * int_lums * int_times / td2 * '
                                      'exp((int_times**2 - te2) / td2) * '
                                      '(1.0 - exp(-A / te2))')
                evaled = True
            else:
                int_arg = ne.re_evaluate()
            # int_arg = [
            #     2.0 * l * t / td2 *
            #     np.exp((t**2 - te**2) / td2) * (1.0 - np.exp(-A / te**2))
            #     for t, l in zip(int_times, int_lums)
            # ]
            int_arg[np.isnan(int_arg)] = 0.0
            lum_val = np.trapz(int_arg, dx=dt)
            lum_cache[te] = lum_val
            new_lum.append(lum_val)
        return {self.output_key('luminosities'): new_lum}
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
import os
import sys
import json
import logging
from optparse import OptionParser

# add jedi too sys.path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))

import jedi
from jedi.api import NotFoundError

# remove it. WHY?
sys.path.pop(0)

is_funcargs_complete_enabled = True
auto_complete_function_params = 'required'

class JsonFormatter(logging.Formatter):
    def format(self, record):
        output = logging.Formatter.format(self, record)
        data = {
            'logging': record.levelname.lower(),
            'content': output
        }
        record = json.dumps(data)
        return record

def getLogger():
    """ Build file logger """
    log = logging.getLogger('Sublime Jedi Daemon')
    log.setLevel(logging.DEBUG)
    formatter = JsonFormatter('%(asctime)s: %(levelname)-8s: %(message)s')
    hdlr = logging.StreamHandler(sys.stderr)
    hdlr.setFormatter(formatter)
    log.addHandler(hdlr)
    return log

logger = getLogger()

def write(data):
    """  Write data to STDOUT """
    if not isinstance(data, str):
        data = json.dumps(data)

    sys.stdout.write(data)

    if not data.endswith('\n'):
        sys.stdout.write('\n')

    try:
        sys.stdout.flush()
    except IOError:
        sys.exit()

def format_completion(complete):
    """ Returns a tuple of the string that would be visible in
    the completion dialogue and the completion word

    :type complete: jedi.api_classes.Completion
    :rtype: (str, str)
    """
    display, insert = complete.name + '\t' + complete.type, complete.name
    return display, insert

def get_function_parameters(callDef):
    """  Return list function parameters, prepared for sublime completion.
    Tuple contains parameter name and default value

    Parameters list excludes: self, *args and **kwargs parameters

    :type callDef: jedi.api_classes.CallDef
    :rtype: list of (str, str or None)
    """
    if not callDef:
        return []

    params = []
    for param in callDef.params:
        # logger.info("%s %s" % (param.name, param.description))

        # when you writing a callable object
        # jedi tring to complete incompleted object
        # and returns "empty" calldefinition
        # in this case we have to skip it
        if not param.name:
            continue

        cleaned_param = param.description.rstrip(',')
        if '*' in cleaned_param or cleaned_param in ['self', '...']:
            continue
        params.append([s.strip() for s in cleaned_param.split('=')])
    return params

class JediFacade:
    """
    Facade to call Jedi API

     Action       | Method
    ===============================
     autocomplete | get_autocomplete
    -------------------------------
     goto         | get_goto
    -------------------------------
     usages       | get_usages
    -------------------------------
     funcargs     | get_funcargs
    --------------------------------

    """
    def __init__(self, source, line, offset, filename='', encoding='utf-8'):
        filename = filename or None
        self.script = jedi.Script(
            source, int(line), int(offset), filename, encoding
        )

    def get(self, action):
        """ Action dispatcher """
        try:
            return getattr(self, 'get_' + action)()
        except:
            logger.exception('`JediFacade.get_{0}` failed'.format(action))

    def get_goto(self):
        """ Jedi "Go To Definition" """
        return self._goto()

    def get_usages(self):
        """ Jedi "Find Usage" """
        return self._usages()

    def get_funcargs(self):
        """ complete callable object parameters with Jedi """
        return self._complete_call_assigments()

    def get_autocomplete(self):
        """ Jedi "completion" """
        data = []

        try:
            data.extend(self._parameters_for_completion())
        except:
            logger.info("params completion failed")

        try:
            data.extend(self._completion() or [])
        except:
            logger.info("general completion failed")

        return data

    def get_docstring(self):
        return self._docstring()

    def get_signature(self):
        return self._docstring(signature=1)

    def _docstring(self, signature=0):
        """ Jedi show doctring or signature

        :rtype: str
        """
        defs = self.script.goto_definitions()
        assert isinstance(defs, list)

        if len(defs) > 0:
            if signature:
                calltip_signature = defs[0].docstring().split('\n\n')[0]
                return calltip_signature.replace('\n', ' ').replace(' = ', '=')
            else:
                return defs[0].docstring()

    def _parameters_for_completion(self):
        """ Get function / class' constructor parameters completions list

        :rtype: list of str
        """
        completions = []
        try:
            in_call = self.script.call_signatures()[0]
        except IndexError:
            in_call = None

        parameters = get_function_parameters(in_call)

        for parameter in parameters:
            try:
                name, value = parameter
            except ValueError:
                name = parameter[0]
                value = None

            if value is None:
                completions.append((name, '${1:%s}' % name))
            else:
                completions.append((name + '\t' + value,
                                   '%s=${1:%s}' % (name, value)))
        return completions

    def _completion(self):
        """ regular completions

        :rtype: list of (str, str)
        """
        completions = self.script.completions()
        return [format_completion(complete) for complete in completions]

    def _goto(self):
        """ Jedi "go to Definitions" functionality

        :rtype: list of (str, int, int) or None
        """
        try:
            definitions = self.script.goto_assignments()
            if all(d.type == 'import' for d in definitions):
                # check if it an import string and if it is get definition
                definitions = self.script.goto_definitions()
        except NotFoundError:
            return
        else:
            return [(i.module_path, i.line, i.column + 1)
                    for i in definitions if not i.in_builtin_module()]

    def _usages(self):
        """ Jedi "find usages" functionality

        :rtype: list of (str, int, int)
        """
        usages = self.script.usages()
        return [(i.module_path, i.line, i.column + 1)
                for i in usages if not i.in_builtin_module()]

    def _complete_call_assigments(self):
        """ Get function or class parameters and build Sublime Snippet string
        for completion

        :rtype: str
        """
        completions = []
        complete_all = auto_complete_function_params == 'all'

        try:
            call_definition = self.script.call_signatures()[0]
        except IndexError:
            call_definition = None

        parameters = get_function_parameters(call_definition)

        for index, parameter in enumerate(parameters):
            try:
                name, value = parameter
            except ValueError:
                name = parameter[0]
                value = None

            if value is None:
                completions.append('${%d:%s}' % (index + 1, name))
            elif complete_all:
                completions.append('%s=${%d:%s}' % (name, index + 1, value))

        return ", ".join(completions)

def process_line(line):
    data = json.loads(line.strip())
    action_type = data['type']

    script = JediFacade(
        source=data['source'],
        line=data['line'],
        offset=data['offset'],
        filename=data.get('filename', '')
    )

    out_data = {
        'uuid': data.get('uuid'),
        'type': action_type,
        action_type: script.get(action_type)
    }

    write(out_data)

if __name__ == '__main__':
    parser = OptionParser()
    parser.add_option(
        "-p", "--project",
        dest="project_name",
        default='',
        help="project name to store jedi's cache"
    )
    parser.add_option(
        "-e", "--extra_folder",
        dest="extra_folders",
        default=[],
        action="append",
        help="extra folders to add to sys.path"
    )
    parser.add_option(
        "-f", "--complete_function_params",
        dest="function_params",
        default='all',
        help='function parameters completion type: "all", "required", or ""'
    )

    options, args = parser.parse_args()

    is_funcargs_complete_enabled = bool(options.function_params)
    auto_complete_function_params = options.function_params

    logger.info(
        'Daemon started. '
        'extra folders - %s, '
        'complete_function_params - %s',
        options.extra_folders,
        options.function_params,
    )

    # append extra paths to sys.path
    for extra_folder in options.extra_folders:
        if extra_folder not in sys.path:
            sys.path.insert(0, extra_folder)

    # call the Jedi
    for line in iter(sys.stdin.readline, ''):
        if line:
            try:
                process_line(line)
            except Exception:
                logger.exception('failed to process line')
<commit_msg>issue #218: fix arguments completion for python3<commit_after># -*- coding: utf-8 -*-
import os
import sys
import json
import logging
from optparse import OptionParser

# add jedi too sys.path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))

import jedi
from jedi.api import NotFoundError

# remove it. WHY?
sys.path.pop(0)

is_funcargs_complete_enabled = True
auto_complete_function_params = 'required'

class JsonFormatter(logging.Formatter):
    def format(self, record):
        output = logging.Formatter.format(self, record)
        data = {
            'logging': record.levelname.lower(),
            'content': output
        }
        record = json.dumps(data)
        return record

def getLogger():
    """ Build file logger """
    log = logging.getLogger('Sublime Jedi Daemon')
    log.setLevel(logging.DEBUG)
    formatter = JsonFormatter('%(asctime)s: %(levelname)-8s: %(message)s')
    hdlr = logging.StreamHandler(sys.stderr)
    hdlr.setFormatter(formatter)
    log.addHandler(hdlr)
    return log

logger = getLogger()

def write(data):
    """  Write data to STDOUT """
    if not isinstance(data, str):
        data = json.dumps(data)

    sys.stdout.write(data)

    if not data.endswith('\n'):
        sys.stdout.write('\n')

    try:
        sys.stdout.flush()
    except IOError:
        sys.exit()

def format_completion(complete):
    """ Returns a tuple of the string that would be visible in
    the completion dialogue and the completion word

    :type complete: jedi.api_classes.Completion
    :rtype: (str, str)
    """
    display, insert = complete.name + '\t' + complete.type, complete.name
    return display, insert

def get_function_parameters(call_signature):
    """  Return list function parameters, prepared for sublime completion.
    Tuple contains parameter name and default value

    Parameters list excludes: self, *args and **kwargs parameters

    :type call_signature: jedi.api.classes.CallSignature
    :rtype: list of (str, str or None)
    """
    if not call_signature:
        return []

    params = []
    for param in call_signature.params:
        param_name = param.name
        param_description = param.description.replace('param ', '')

        # when you writing a callable object
        # jedi tring to complete incompleted object
        # and returns "empty" calldefinition
        # in this case we have to skip it
        if (not param.name or
                param.name in ('self', '...') or
                '*' in param.description):
            continue

        if '=' in param_description:
            default_value = param_description.rsplit('=', 1)[1]
            params.append((param_name, default_value))
        else:
            params.append((param_name, None))

    return params

class JediFacade:
    """
    Facade to call Jedi API

     Action       | Method
    ===============================
     autocomplete | get_autocomplete
    -------------------------------
     goto         | get_goto
    -------------------------------
     usages       | get_usages
    -------------------------------
     funcargs     | get_funcargs
    --------------------------------

    """
    def __init__(self, source, line, offset, filename='', encoding='utf-8'):
        filename = filename or None
        self.script = jedi.Script(
            source, int(line), int(offset), filename, encoding
        )

    def get(self, action):
        """ Action dispatcher """
        try:
            return getattr(self, 'get_' + action)()
        except:
            logger.exception('`JediFacade.get_{0}` failed'.format(action))

    def get_goto(self):
        """ Jedi "Go To Definition" """
        return self._goto()

    def get_usages(self):
        """ Jedi "Find Usage" """
        return self._usages()

    def get_funcargs(self):
        """ complete callable object parameters with Jedi """
        return self._complete_call_assigments()

    def get_autocomplete(self):
        """ Jedi "completion" """
        data = []

        try:
            data.extend(self._parameters_for_completion())
        except:
            logger.info("params completion failed")

        try:
            data.extend(self._completion() or [])
        except:
            logger.info("general completion failed")

        return data

    def get_docstring(self):
        return self._docstring()

    def get_signature(self):
        return self._docstring(signature=1)

    def _docstring(self, signature=0):
        """ Jedi show doctring or signature

        :rtype: str
        """
        defs = self.script.goto_definitions()
        assert isinstance(defs, list)

        if len(defs) > 0:
            if signature:
                calltip_signature = defs[0].docstring().split('\n\n')[0]
                return calltip_signature.replace('\n', ' ').replace(' = ', '=')
            else:
                return defs[0].docstring()

    def _parameters_for_completion(self):
        """ Get function / class' constructor parameters completions list

        :rtype: list of str
        """
        completions = []
        try:
            in_call = self.script.call_signatures()[0]
        except IndexError:
            in_call = None

        parameters = get_function_parameters(in_call)

        for parameter in parameters:
            name, value = parameter

            if value is None:
                completions.append((name, '${1:%s}' % name))
            else:
                completions.append((name + '\t' + value,
                                   '%s=${1:%s}' % (name, value)))
        return completions

    def _completion(self):
        """ regular completions

        :rtype: list of (str, str)
        """
        completions = self.script.completions()
        return [format_completion(complete) for complete in completions]

    def _goto(self):
        """ Jedi "go to Definitions" functionality

        :rtype: list of (str, int, int) or None
        """
        try:
            definitions = self.script.goto_assignments()
            if all(d.type == 'import' for d in definitions):
                # check if it an import string and if it is get definition
                definitions = self.script.goto_definitions()
        except NotFoundError:
            return
        else:
            return [(i.module_path, i.line, i.column + 1)
                    for i in definitions if not i.in_builtin_module()]

    def _usages(self):
        """ Jedi "find usages" functionality

        :rtype: list of (str, int, int)
        """
        usages = self.script.usages()
        return [(i.module_path, i.line, i.column + 1)
                for i in usages if not i.in_builtin_module()]

    def _complete_call_assigments(self):
        """ Get function or class parameters and build Sublime Snippet string
        for completion

        :rtype: str
        """
        completions = []
        complete_all = auto_complete_function_params == 'all'

        try:
            call_definition = self.script.call_signatures()[0]
        except IndexError:
            call_definition = None

        parameters = get_function_parameters(call_definition)

        for index, parameter in enumerate(parameters):
            name, value = parameter

            if value is None:
                completions.append('${%d:%s}' % (index + 1, name))
            elif complete_all:
                completions.append('%s=${%d:%s}' % (name, index + 1, value))

        return ", ".join(completions)

def process_line(line):
    data = json.loads(line.strip())
    action_type = data['type']

    script = JediFacade(
        source=data['source'],
        line=data['line'],
        offset=data['offset'],
        filename=data.get('filename', '')
    )

    out_data = {
        'uuid': data.get('uuid'),
        'type': action_type,
        action_type: script.get(action_type)
    }

    write(out_data)

if __name__ == '__main__':
    parser = OptionParser()
    parser.add_option(
        "-p", "--project",
        dest="project_name",
        default='',
        help="project name to store jedi's cache"
    )
    parser.add_option(
        "-e", "--extra_folder",
        dest="extra_folders",
        default=[],
        action="append",
        help="extra folders to add to sys.path"
    )
    parser.add_option(
        "-f", "--complete_function_params",
        dest="function_params",
        default='all',
        help='function parameters completion type: "all", "required", or ""'
    )

    options, args = parser.parse_args()

    is_funcargs_complete_enabled = bool(options.function_params)
    auto_complete_function_params = options.function_params

    logger.info(
        'Daemon started. '
        'extra folders - %s, '
        'complete_function_params - %s',
        options.extra_folders,
        options.function_params,
    )

    # append extra paths to sys.path
    for extra_folder in options.extra_folders:
        if extra_folder not in sys.path:
            sys.path.insert(0, extra_folder)

    # call the Jedi
    for line in iter(sys.stdin.readline, ''):
        if line:
            try:
                process_line(line)
            except Exception:
                logger.exception('failed to process line')
<|endoftext|>


<commit_before>"""
Created on Wed Aug 12 01:37:16 2015

Author: Richard Tanburn (richard.tanburn@gmail.com)
"""

import re
import sympy
from sympy.abc import _clash1

VAR_RE = '[A-Za-z*][\d_]*'

def matrix_to_tex(matrix_):
    '''
    Given a matrix, write out the TeX.

    Args:
        matrix_ (sympy.Matrix): Matrix to turn into TeX
    Returns:
        str

    Printing is the correct way to use this function, but the docstring looks a bit odd.
    >>> print matrix_to_tex(sympy.eye(2))
    1 & 0 \\\\
    0 & 1 \\\\
    '''
    lines = []
    for line in matrix_.tolist():
        lines.append(' & '.join(map(str, line)) + ' \\\\')
    return '\n'.join(lines)

def _var_repler(var):
    var = var.group()
    if len(var) == 1:
        return var[0]
    var_letter, subscript = var[0], var[1:]
    if subscript[0] == '_':
        subscript = subscript[1:]
    subscript = subscript.replace('_', '')
    return '{}_{{{}}}'.format(var_letter, subscript)

def var_to_tex(var):
    """
    Given a sympy variable, write out the TeX.

    Args:
        var (sympy.Symbol): Variable to turn into TeX
    Returns:
        str

    >>> print map(var_to_tex, sympy.symbols('x y_1 Kw_3 z_{3} k_m1'))
    ['x', 'y_{1}', 'Kw_{3}', 'z_{3}', 'k_{-1}']
    """
    return expr_to_tex(var)

def expr_to_tex(expr):
    """
    Given a sympy expression, write out the TeX.

    Args:
        expr (sympy.Expression): Expression to turn into TeX
    Returns:
        str

    >>> print map(expr_to_tex, map(sympy.sympify, ['(x + y - 1.5)**2', '(x + y_m1)**1', 'k_m1*t']))
    ['\\\\left(x + y - 1.5\\\\right)^{2}', 'x + y_{-1}', 'k_{-1} t']
    """
    tex = sympy.latex(expr)
    # Substitute _{m...} for _{-...}
    tex = re.sub(r'\_\{?m([^\}]+)\}?', r'_{-\1}', tex)
    return tex

def eqn_to_tex(eqn):
    eqn = str(eqn).replace(' ', '')

    expr1, expr2 = eqn.split('==')

    tex = '{} &= {}'.format(expr_to_tex(expr1), expr_to_tex(expr2))
    return tex

def eqns_to_tex(eqns):
    ''' To convert to array environment, copy the output into a lyx LaTeX cell,
        then copy this entire cell into an eqnarray of sufficient size
    '''
    return '\\\\'.join(map(eqn_to_tex, eqns))

def tex_to_sympy(tex):
    """
    Given some TeX, turn it into sympy expressions and equations.
    Each line is parsed seperately.

    Args:
        tex (str): LaTeX

    Returns:
        list

    >>> lines = ['\\frac{dE}{dt} &= - k_1 E S + k_{-1} C + k_2 C \\\\',
    ... '\\frac{dS}{dt} &= - k_1 E S + k_{-1} C \\\\',
    ... '\\frac{dC}{dt} &= k_1 E S - k_{-1} C - k_2 C \\\\',
    ... '\\frac{dP}{dt} &= k_2 C']
    >>> sym = tex_to_sympy('\\n'.join(lines))
    >>> for s in sym: print s
    Eq(Derivative(E, t), C*k_2 + C*k_m1 - E*S*k_1)
    Eq(Derivative(S, t), C*k_m1 - E*S*k_1)
    Eq(Derivative(C, t), -C*k_2 - C*k_m1 + E*S*k_1)
    Eq(Derivative(P, t), C*k_2)
    """
    # Parse each line individually
    split_tex = tex.split('\n')
    if len(split_tex) > 1:
        return map(tex_to_sympy, split_tex)

    # Remove alignment characters
    tex = tex.strip('\s').replace('&', '').replace('\\\\', '')

    # If equality, return a sympy.Eq
    sides = tex.split('=')
    if len(sides) == 2:
        return sympy.Eq(*map(tex_to_sympy, sides))
    elif len(sides) != 1:
        raise ValueError('Too many = in {}.'.format(tex))

    # Turn \frac{d }{d } into sympy.Derivatives
    diff_match = re.match('\s*\\frac\{d(.+)\}\{d(.+)\}', tex)
    if diff_match:
        return sympy.Derivative(*sympy.symbols(' '.join(diff_match.groups())))

    # Turn \frac into ratios
    tex = re.sub(r'\frac{(.*)}{(.*)}', '((\\1) / (\\2))', tex)
    # Turn spaces between variables into *. Do this by matching anything that isn't an operation
    # Use a lookahead assertion to get overlapping instances.
    tex = re.sub('([^\+\-\*\s/]+)\s+(?=[^\+\-\*\s/]+)', '\\1 * ', tex)

    # Change minuses in the subscripts to m's
    tex = re.sub('([a-zA-Z]+)_{\-(.+)}', '\\1_m\\2 ', tex)

    # We want to use all available variables, so sympify with the _clash local dictionary
    return sympy.sympify(tex, _clash1)

if __name__ == '__main__':
    import doctest
    doctest.testmod()<commit_msg>Improve reading of tex<commit_after>"""
Created on Wed Aug 12 01:37:16 2015

Author: Richard Tanburn (richard.tanburn@gmail.com)
"""

import re
import sympy
from sympy.abc import _clash1

VAR_RE = '[A-Za-z*][\d_]*'

def matrix_to_tex(matrix_):
    '''
    Given a matrix, write out the TeX.

    Args:
        matrix_ (sympy.Matrix): Matrix to turn into TeX
    Returns:
        str

    Printing is the correct way to use this function, but the docstring looks a bit odd.
    >>> print matrix_to_tex(sympy.eye(2))
    1 & 0 \\\\
    0 & 1 \\\\
    '''
    lines = []
    for line in matrix_.tolist():
        lines.append(' & '.join(map(str, line)) + ' \\\\')
    return '\n'.join(lines)

def _var_repler(var):
    var = var.group()
    if len(var) == 1:
        return var[0]
    var_letter, subscript = var[0], var[1:]
    if subscript[0] == '_':
        subscript = subscript[1:]
    subscript = subscript.replace('_', '')
    return '{}_{{{}}}'.format(var_letter, subscript)

def var_to_tex(var):
    """
    Given a sympy variable, write out the TeX.

    Args:
        var (sympy.Symbol): Variable to turn into TeX
    Returns:
        str

    >>> print map(var_to_tex, sympy.symbols('x y_1 Kw_3 z_{3} k_m1'))
    ['x', 'y_{1}', 'Kw_{3}', 'z_{3}', 'k_{-1}']
    """
    return expr_to_tex(var)

def expr_to_tex(expr):
    """
    Given a sympy expression, write out the TeX.

    Args:
        expr (sympy.Expression): Expression to turn into TeX
    Returns:
        str

    >>> print map(expr_to_tex, map(sympy.sympify, ['(x + y - 1.5)**2', '(x + y_m1)**1', 'k_m1*t']))
    ['\\\\left(x + y - 1.5\\\\right)^{2}', 'x + y_{-1}', 'k_{-1} t']
    """
    tex = sympy.latex(expr)
    # Substitute _{m...} for _{-...}
    tex = re.sub(r'\_\{?m([^\}]+)\}?', r'_{-\1}', tex)
    return tex

def eqn_to_tex(eqn):
    eqn = str(eqn).replace(' ', '')

    expr1, expr2 = eqn.split('==')

    tex = '{} &= {}'.format(expr_to_tex(expr1), expr_to_tex(expr2))
    return tex

def eqns_to_tex(eqns):
    ''' To convert to array environment, copy the output into a lyx LaTeX cell,
        then copy this entire cell into an eqnarray of sufficient size
    '''
    return '\\\\'.join(map(eqn_to_tex, eqns))

def tex_to_sympy(tex):
    """
    Given some TeX, turn it into sympy expressions and equations.
    Each line is parsed seperately.

    Args:
        tex (str): LaTeX

    Returns:
        list

    >>> lines = ['\\frac{dE}{dt} &= - k_1 E S + k_{-1} C + k_2 C \\\\',
    ... '\\frac{dS}{dt} &= - k_1 E S + k_{-1} C \\\\',
    ... '\\frac{dC}{dt} &= k_1 E S - k_{-1} C - k_2 C \\\\',
    ... '\\frac{dP}{dt} &= k_2 C']
    >>> sym = tex_to_sympy('\\n'.join(lines))
    >>> for s in sym: print s
    Eq(Derivative(E, t), C*k_2 + C*k_m1 - E*S*k_1)
    Eq(Derivative(S, t), C*k_m1 - E*S*k_1)
    Eq(Derivative(C, t), -C*k_2 - C*k_m1 + E*S*k_1)
    Eq(Derivative(P, t), C*k_2)
    """
    # Parse each line individually
    split_tex = tex.split('\n')
    if len(split_tex) > 1:
        return map(tex_to_sympy, split_tex)

    # Remove alignment characters
    tex = tex.strip('\s').replace('&', '').replace('\\\\', '')

    # If equality, return a sympy.Eq
    sides = tex.split('=')
    if len(sides) == 2:
        return sympy.Eq(*map(tex_to_sympy, sides))
    elif len(sides) != 1:
        raise ValueError('Too many = in {}.'.format(tex))

    # Turn \frac{d }{d } into sympy.Derivatives
    diff_match = re.match('\s*\\frac\{d(.+)\}\{d(.+)\}', tex)
    if diff_match:
        return sympy.Derivative(*sympy.symbols(' '.join(diff_match.groups())))

    # Turn \frac into ratios
    tex = re.sub(r'\frac{(.*)}{(.*)}', '((\\1) / (\\2))', tex)
    # Turn spaces between variables into *. Do this by matching anything that isn't an operation
    # Use a lookahead assertion to get overlapping instances.
    tex = re.sub('([^+\-*\s/(]+)\s+(?=[^+\-*\s/)]+)', '\\1 * ', tex)

    # Change minuses in the subscripts to m's
    tex = re.sub('([a-zA-Z]+)_{(.*)\-(.+)}', '\\1_\\2m\\3 ', tex)

    # We want to use all available variables, so sympify with the _clash local dictionary
    return sympy.sympify(tex, _clash1)

if __name__ == '__main__':
    import doctest
    doctest.testmod()<|endoftext|>


<commit_before>import logging
import json
import os
import sys
from os.path import join, abspath, dirname

import settings
import github_api as gh

THIS_DIR = dirname(abspath(__file__))

__log = logging.getLogger("pull_requests")

def poll_pull_requests(api):
    __log.info("looking for PRs")

    # get voting window
    voting_window = gh.voting.get_initial_voting_window()

    # get all ready prs (disregarding of the voting window)
    prs = gh.prs.get_ready_prs(api, settings.URN, 0)

    # This sets up a voting record, with each user having a count of votes
    # that they have cast.
    try:
        fp = open('server/voters.json', 'x')
        fp.close()
    except:
        # file already exists, which is what we want
        pass

    with open('server/voters.json', 'r+') as fp:
        total_votes = {}
        fs = fp.read()
        if fs:
            total_votes = json.loads(fs)

        top_contributors = sorted(gh.repos.get_contributors(api, settings.URN),
                                  key=lambda user: user["total"], reverse=True)
        top_contributors = [item["author"]["login"].lower() for item in top_contributors]
        contributors = set(top_contributors)  # store it while it's still a complete list
        top_contributors = top_contributors[:settings.MERITOCRACY_TOP_CONTRIBUTORS]
        top_contributors = set(top_contributors)
        top_voters = sorted(total_votes, key=total_votes.get, reverse=True)
        top_voters = set([user.lower() for user in top_voters[:settings.MERITOCRACY_TOP_VOTERS]])
        meritocracy = top_voters | top_contributors
        __log.info("generated meritocracy: " + str(meritocracy))

        with open('server/meritocracy.json', 'w') as mfp:
            json.dump(meritocracy, mfp)

        needs_update = False
        for pr in prs:
            pr_num = pr["number"]
            __log.info("processing PR #%d", pr_num)

            # gather all current votes
            votes, meritocracy_satisfied = gh.voting.get_votes(api, settings.URN, pr, meritocracy)

            # is our PR approved or rejected?
            vote_total, variance = gh.voting.get_vote_sum(api, votes, contributors)
            threshold = gh.voting.get_approval_threshold(api, settings.URN)
            is_approved = vote_total >= threshold and meritocracy_satisfied

            # the PR is mitigated or the threshold is not reached ?
            if variance >= threshold or not is_approved:
                voting_window = gh.voting.get_extended_voting_window(api, settings.URN)

            # is our PR in voting window?
            in_window = gh.prs.is_pr_in_voting_window(api, pr, voting_window)

            if is_approved:
                __log.info("PR %d status: will be approved", pr_num)

                gh.prs.post_accepted_status(
                    api, settings.URN, pr, voting_window, votes, vote_total,
                    threshold, meritocracy_satisfied)

                if in_window:
                    __log.info("PR %d approved for merging!", pr_num)

                    try:
                        sha = gh.prs.merge_pr(api, settings.URN, pr, votes, vote_total,
                                              threshold, meritocracy_satisfied)
                    # some error, like suddenly there's a merge conflict, or some
                    # new commits were introduced between finding this ready pr and
                    # merging it
                    except gh.exceptions.CouldntMerge:
                        __log.info("couldn't merge PR %d for some reason, skipping",
                                   pr_num)
                        gh.issues.label_issue(api, settings.URN, pr_num, ["can't merge"])
                        continue

                    gh.comments.leave_accept_comment(
                        api, settings.URN, pr_num, sha, votes, vote_total,
                        threshold, meritocracy_satisfied)
                    gh.issues.label_issue(api, settings.URN, pr_num, ["accepted"])

                    # chaosbot rewards merge owners with a follow
                    pr_owner = pr["user"]["login"]
                    gh.users.follow_user(api, pr_owner)

                    needs_update = True

            else:
                __log.info("PR %d status: will be rejected", pr_num)

                if in_window:
                    gh.prs.post_rejected_status(
                        api, settings.URN, pr, voting_window, votes, vote_total,
                        threshold, meritocracy_satisfied)
                    __log.info("PR %d rejected, closing", pr_num)
                    gh.comments.leave_reject_comment(
                        api, settings.URN, pr_num, votes, vote_total, threshold,
                        meritocracy_satisfied)
                    gh.issues.label_issue(api, settings.URN, pr_num, ["rejected"])
                    gh.prs.close_pr(api, settings.URN, pr)
                elif vote_total < 0:
                    gh.prs.post_rejected_status(
                        api, settings.URN, pr, voting_window, votes, vote_total,
                        threshold, meritocracy_satisfied)
                else:
                    gh.prs.post_pending_status(
                        api, settings.URN, pr, voting_window, votes, vote_total,
                        threshold, meritocracy_satisfied)

            for user in votes:
                if user in total_votes:
                    total_votes[user] += 1
                else:
                    total_votes[user] = 1

        if fs:
            # prepare for overwriting
            fp.seek(0)
            fp.truncate()
        json.dump(total_votes, fp)

        # flush all buffers because we might restart, which could cause a crash
        os.fsync(fp)

    # we approved a PR, restart
    if needs_update:
        __log.info("updating code and requirements and restarting self")
        startup_path = join(THIS_DIR, "..", "startup.sh")

        # before we exec, we need to flush i/o buffers so we don't lose logs or voters
        sys.stdout.flush()
        sys.stderr.flush()

        os.execl(startup_path, startup_path)

    __log.info("Waiting %d seconds until next scheduled PR polling event",
               settings.PULL_REQUEST_POLLING_INTERVAL_SECONDS)
<commit_msg>merging PR #469: Fix meritocracy.json serialization<commit_after>import logging
import json
import os
import sys
from os.path import join, abspath, dirname

import settings
import github_api as gh

THIS_DIR = dirname(abspath(__file__))

__log = logging.getLogger("pull_requests")

def poll_pull_requests(api):
    __log.info("looking for PRs")

    # get voting window
    voting_window = gh.voting.get_initial_voting_window()

    # get all ready prs (disregarding of the voting window)
    prs = gh.prs.get_ready_prs(api, settings.URN, 0)

    # This sets up a voting record, with each user having a count of votes
    # that they have cast.
    try:
        fp = open('server/voters.json', 'x')
        fp.close()
    except:
        # file already exists, which is what we want
        pass

    with open('server/voters.json', 'r+') as fp:
        total_votes = {}
        fs = fp.read()
        if fs:
            total_votes = json.loads(fs)

        top_contributors = sorted(gh.repos.get_contributors(api, settings.URN),
                                  key=lambda user: user["total"], reverse=True)
        top_contributors = [item["author"]["login"].lower() for item in top_contributors]
        contributors = set(top_contributors)  # store it while it's still a complete list
        top_contributors = top_contributors[:settings.MERITOCRACY_TOP_CONTRIBUTORS]
        top_contributors = set(top_contributors)
        top_voters = sorted(total_votes, key=total_votes.get, reverse=True)
        top_voters = set([user.lower() for user in top_voters[:settings.MERITOCRACY_TOP_VOTERS]])
        meritocracy = top_voters | top_contributors
        __log.info("generated meritocracy: " + str(meritocracy))

        with open('server/meritocracy.json', 'w') as mfp:
            json.dump(list(meritocracy), mfp)

        needs_update = False
        for pr in prs:
            pr_num = pr["number"]
            __log.info("processing PR #%d", pr_num)

            # gather all current votes
            votes, meritocracy_satisfied = gh.voting.get_votes(api, settings.URN, pr, meritocracy)

            # is our PR approved or rejected?
            vote_total, variance = gh.voting.get_vote_sum(api, votes, contributors)
            threshold = gh.voting.get_approval_threshold(api, settings.URN)
            is_approved = vote_total >= threshold and meritocracy_satisfied

            # the PR is mitigated or the threshold is not reached ?
            if variance >= threshold or not is_approved:
                voting_window = gh.voting.get_extended_voting_window(api, settings.URN)

            # is our PR in voting window?
            in_window = gh.prs.is_pr_in_voting_window(api, pr, voting_window)

            if is_approved:
                __log.info("PR %d status: will be approved", pr_num)

                gh.prs.post_accepted_status(
                    api, settings.URN, pr, voting_window, votes, vote_total,
                    threshold, meritocracy_satisfied)

                if in_window:
                    __log.info("PR %d approved for merging!", pr_num)

                    try:
                        sha = gh.prs.merge_pr(api, settings.URN, pr, votes, vote_total,
                                              threshold, meritocracy_satisfied)
                    # some error, like suddenly there's a merge conflict, or some
                    # new commits were introduced between finding this ready pr and
                    # merging it
                    except gh.exceptions.CouldntMerge:
                        __log.info("couldn't merge PR %d for some reason, skipping",
                                   pr_num)
                        gh.issues.label_issue(api, settings.URN, pr_num, ["can't merge"])
                        continue

                    gh.comments.leave_accept_comment(
                        api, settings.URN, pr_num, sha, votes, vote_total,
                        threshold, meritocracy_satisfied)
                    gh.issues.label_issue(api, settings.URN, pr_num, ["accepted"])

                    # chaosbot rewards merge owners with a follow
                    pr_owner = pr["user"]["login"]
                    gh.users.follow_user(api, pr_owner)

                    needs_update = True

            else:
                __log.info("PR %d status: will be rejected", pr_num)

                if in_window:
                    gh.prs.post_rejected_status(
                        api, settings.URN, pr, voting_window, votes, vote_total,
                        threshold, meritocracy_satisfied)
                    __log.info("PR %d rejected, closing", pr_num)
                    gh.comments.leave_reject_comment(
                        api, settings.URN, pr_num, votes, vote_total, threshold,
                        meritocracy_satisfied)
                    gh.issues.label_issue(api, settings.URN, pr_num, ["rejected"])
                    gh.prs.close_pr(api, settings.URN, pr)
                elif vote_total < 0:
                    gh.prs.post_rejected_status(
                        api, settings.URN, pr, voting_window, votes, vote_total,
                        threshold, meritocracy_satisfied)
                else:
                    gh.prs.post_pending_status(
                        api, settings.URN, pr, voting_window, votes, vote_total,
                        threshold, meritocracy_satisfied)

            for user in votes:
                if user in total_votes:
                    total_votes[user] += 1
                else:
                    total_votes[user] = 1

        if fs:
            # prepare for overwriting
            fp.seek(0)
            fp.truncate()
        json.dump(total_votes, fp)

        # flush all buffers because we might restart, which could cause a crash
        os.fsync(fp)

    # we approved a PR, restart
    if needs_update:
        __log.info("updating code and requirements and restarting self")
        startup_path = join(THIS_DIR, "..", "startup.sh")

        # before we exec, we need to flush i/o buffers so we don't lose logs or voters
        sys.stdout.flush()
        sys.stderr.flush()

        os.execl(startup_path, startup_path)

    __log.info("Waiting %d seconds until next scheduled PR polling event",
               settings.PULL_REQUEST_POLLING_INTERVAL_SECONDS)
<|endoftext|>


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

"""Global configuration handling."""

from __future__ import unicode_literals
import copy
import logging
import os
import io

import poyo

from .exceptions import ConfigDoesNotExistException
from .exceptions import InvalidConfiguration

logger = logging.getLogger(__name__)

USER_CONFIG_PATH = os.path.expanduser('~/.cookiecutterrc')

BUILTIN_ABBREVIATIONS = {
    'gh': 'https://github.com/{0}.git',
    'gl': 'https://gitlab.com/{0}.git',
    'bb': 'https://bitbucket.org/{0}',
}

DEFAULT_CONFIG = {
    'cookiecutters_dir': os.path.expanduser('~/.cookiecutters/'),
    'replay_dir': os.path.expanduser('~/.cookiecutter_replay/'),
    'default_context': {},
    'abbreviations': BUILTIN_ABBREVIATIONS,
}

def _expand_path(path):
    """Expand both environment variables and user home in the given path."""
    path = os.path.expandvars(path)
    path = os.path.expanduser(path)
    return path

def merge_config(default, overwrite):
    """Recursively update a dict with the key/value pair of another.

    Dict values that are dictionaries themselves will be updated, whilst
    preserving existing keys.
    """
    for k, v in overwrite.items():
        if isinstance(v, dict):
            default[k] = merge_config(default[k], v)
            continue
        default[k] = v

    return default

def get_config(config_path):
    """Retrieve the config from the specified path, returning a config dict."""
    if not os.path.exists(config_path):
        raise ConfigDoesNotExistException

    logger.debug('config_path is {0}'.format(config_path))
    with io.open(config_path, encoding='utf-8') as file_handle:
        try:
            yaml_dict = poyo.parse_string(file_handle.read())
        except poyo.exceptions.PoyoException as e:
            raise InvalidConfiguration(
                'Unable to parse YAML file {}. Error: {}'
                ''.format(config_path, e)
            )

    config_dict = merge_config(copy.copy(DEFAULT_CONFIG), yaml_dict)

    raw_replay_dir = config_dict['replay_dir']
    config_dict['replay_dir'] = _expand_path(raw_replay_dir)

    raw_cookies_dir = config_dict['cookiecutters_dir']
    config_dict['cookiecutters_dir'] = _expand_path(raw_cookies_dir)

    return config_dict

def get_user_config(config_file=None, default_config=False):
    """Return the user config as a dict.

    If ``default_config`` is True, ignore ``config_file`` and return default
    values for the config parameters.

    If a path to a ``config_file`` is given, that is different from the default
    location, load the user config from that.

    Otherwise look up the config file path in the ``COOKIECUTTER_CONFIG``
    environment variable. If set, load the config from this path. This will
    raise an error if the specified path is not valid.

    If the environment variable is not set, try the default config file path
    before falling back to the default config values.
    """
    # Do NOT load a config. Return defaults instead.
    if default_config:
        return copy.copy(DEFAULT_CONFIG)

    # Load the given config file
    if config_file and config_file is not USER_CONFIG_PATH:
        return get_config(config_file)

    try:
        # Does the user set up a config environment variable?
        env_config_file = os.environ['COOKIECUTTER_CONFIG']
    except KeyError:
        # Load an optional user config if it exists
        # otherwise return the defaults
        if os.path.exists(USER_CONFIG_PATH):
            return get_config(USER_CONFIG_PATH)
        else:
            return copy.copy(DEFAULT_CONFIG)
    else:
        # There is a config environment variable. Try to load it.
        # Do not check for existence, so invalid file paths raise an error.
        return get_config(env_config_file)
<commit_msg>Create a deepcopy of the DEFAULT_CONFIG<commit_after># -*- coding: utf-8 -*-

"""Global configuration handling."""

from __future__ import unicode_literals
import copy
import logging
import os
import io

import poyo

from .exceptions import ConfigDoesNotExistException
from .exceptions import InvalidConfiguration

logger = logging.getLogger(__name__)

USER_CONFIG_PATH = os.path.expanduser('~/.cookiecutterrc')

BUILTIN_ABBREVIATIONS = {
    'gh': 'https://github.com/{0}.git',
    'gl': 'https://gitlab.com/{0}.git',
    'bb': 'https://bitbucket.org/{0}',
}

DEFAULT_CONFIG = {
    'cookiecutters_dir': os.path.expanduser('~/.cookiecutters/'),
    'replay_dir': os.path.expanduser('~/.cookiecutter_replay/'),
    'default_context': {},
    'abbreviations': BUILTIN_ABBREVIATIONS,
}

def _expand_path(path):
    """Expand both environment variables and user home in the given path."""
    path = os.path.expandvars(path)
    path = os.path.expanduser(path)
    return path

def merge_config(default, overwrite):
    """Recursively update a dict with the key/value pair of another.

    Dict values that are dictionaries themselves will be updated, whilst
    preserving existing keys.
    """
    for k, v in overwrite.items():
        if isinstance(v, dict):
            default[k] = merge_config(default[k], v)
            continue
        default[k] = v

    return default

def get_config(config_path):
    """Retrieve the config from the specified path, returning a config dict."""
    if not os.path.exists(config_path):
        raise ConfigDoesNotExistException

    logger.debug('config_path is {0}'.format(config_path))
    with io.open(config_path, encoding='utf-8') as file_handle:
        try:
            yaml_dict = poyo.parse_string(file_handle.read())
        except poyo.exceptions.PoyoException as e:
            raise InvalidConfiguration(
                'Unable to parse YAML file {}. Error: {}'
                ''.format(config_path, e)
            )

    config_dict = merge_config(copy.deepcopy(DEFAULT_CONFIG), yaml_dict)

    raw_replay_dir = config_dict['replay_dir']
    config_dict['replay_dir'] = _expand_path(raw_replay_dir)

    raw_cookies_dir = config_dict['cookiecutters_dir']
    config_dict['cookiecutters_dir'] = _expand_path(raw_cookies_dir)

    return config_dict

def get_user_config(config_file=None, default_config=False):
    """Return the user config as a dict.

    If ``default_config`` is True, ignore ``config_file`` and return default
    values for the config parameters.

    If a path to a ``config_file`` is given, that is different from the default
    location, load the user config from that.

    Otherwise look up the config file path in the ``COOKIECUTTER_CONFIG``
    environment variable. If set, load the config from this path. This will
    raise an error if the specified path is not valid.

    If the environment variable is not set, try the default config file path
    before falling back to the default config values.
    """
    # Do NOT load a config. Return defaults instead.
    if default_config:
        return copy.copy(DEFAULT_CONFIG)

    # Load the given config file
    if config_file and config_file is not USER_CONFIG_PATH:
        return get_config(config_file)

    try:
        # Does the user set up a config environment variable?
        env_config_file = os.environ['COOKIECUTTER_CONFIG']
    except KeyError:
        # Load an optional user config if it exists
        # otherwise return the defaults
        if os.path.exists(USER_CONFIG_PATH):
            return get_config(USER_CONFIG_PATH)
        else:
            return copy.copy(DEFAULT_CONFIG)
    else:
        # There is a config environment variable. Try to load it.
        # Do not check for existence, so invalid file paths raise an error.
        return get_config(env_config_file)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# (c) 2015 Mikel Arregi - AvanzOSC
# (c) 2015 Oihane Crucelaegui - AvanzOSC
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

from openerp import api, exceptions, fields, models, _
from openerp.addons import decimal_precision as dp

class MrpProduction(models.Model):
    _inherit = 'mrp.production'

    pack = fields.One2many(
        comodel_name='packaging.operation', inverse_name='operation')
    expected_production = fields.One2many(
        comodel_name='mrp.production', inverse_name='production',
        string='Expected Production')
    production = fields.Many2one(
        comodel_name='mrp.production', string='Production')
    final_product_qty = fields.Float(
        string='Produced product qty', compute='_final_product_qty',
        digits=dp.get_precision('Product Unit of Measure'),
        help='This amount is the real amount produced in the MO.')
    left_product_qty = fields.Float(
        string='Qty left for packaging', compute='_left_product_qty',
        digits=dp.get_precision('Product Unit of Measure'),
        help='This amount is indicative, it is calculated with packaging'
        ' orders that are not in canceled state.')

    @api.multi
    @api.depends('move_created_ids2')
    def _final_product_qty(self):
        for record in self:
            moves = record.mapped('move_created_ids2').filtered(
                lambda x: x.state == 'done' and
                not x.location_dest_id.scrap_location and
                x.product_id == record.product_id)
            record.final_product_qty = sum(moves.mapped('product_uom_qty'))

    @api.multi
    @api.depends('final_product_qty', 'expected_production')
    def _left_product_qty(self):
        for record in self:
            moves = record.mapped('move_created_ids2').filtered(
                lambda x: x.state == 'done' and
                x.location_dest_id.scrap_location and
                x.product_id == record.product_id)
            remaining_qty = (record.final_product_qty -
                             sum(moves.mapped('product_uom_qty')))
            for production in record.expected_production.filtered(
                    lambda x: x.state != 'cancel'):
                product = production.production.product_id
                if production.move_lines2:
                    remaining_qty -= sum(production.move_lines2.filtered(
                        lambda m: m.product_id == product
                        ).mapped('product_uom_qty'))
                elif production.move_lines:
                    remaining_qty -= sum(production.move_lines.filtered(
                        lambda m: m.product_id == product
                        ).mapped('product_uom_qty'))
                else:
                    remaining_qty -= sum(production.product_lines.filtered(
                        lambda p: p.product_id == product
                        ).mapped('product_qty'))
            record.left_product_qty = remaining_qty

    @api.multi
    def get_dump_packages(self):
        self.ensure_one()
        pack_lines = []
        lines = self.env['mrp.bom.line'].search(
            ['|', ('product_template', '=', self.product_template.id),
             ('product_id', '=', self.product_id.id)])
        exist_prod = [x.product.id for x in self.pack]
        for line in lines:
            if line not in exist_prod:
                packs = filter(
                    lambda x: x not in exist_prod,
                    line.bom_id.product_tmpl_id.product_variant_ids.ids)
                pack_line = map(
                    lambda x: (0, 0, {'product': x}), packs)
                pack_lines.extend(pack_line)
        self.write({'pack': pack_lines})

    @api.one
    def recalculate_product_qty(self, qty, product):
        line = self.product_lines.filtered(
            lambda x: x.product_id == product)
        line.write({'product_qty': qty})

    @api.one
    def assign_parent_lot(self, production):
        line = self.product_lines.filtered(
            lambda x: x.product_id == production.product_id)
        line.write({'lot': (
                    production.move_created_ids2 and
                    production.move_created_ids2[0].restrict_lot_id.id or
                    False)})

    @api.one
    def create_mo_from_packaging_operation(self):
        for op in self.pack.filtered(lambda x: x.qty != 0 and not x.processed):
            linked_raw_products = []
            add_product = []
            equal_uom = op.product.uom_id.id == self.product_id.uom_id.id
            final_product_qty = equal_uom and op.fill or op.qty
            data = self.product_id_change(op.product.id, final_product_qty)
            if 'product_attributes' in data['value']:
                product_attributes = map(
                    lambda x: (0, 0, x),
                    data['value']['product_attributes'])
                data['value'].update({
                    'product_attributes': product_attributes})
            name = self.env['ir.sequence'].get('mrp.production.packaging')
            data['value'].update({
                'product_id': op.product.id,
                'product_qty': final_product_qty,
                'name': name})
            new_op = self.create(data['value'])
            new_op.action_compute()
            new_op.recalculate_product_qty(op.fill, self.product_id)
            new_op.assign_parent_lot(self)
            workorder =\
                new_op.workcenter_lines and new_op.workcenter_lines[0].id
            for attr_value in op.product.attribute_value_ids:
                raw_product = attr_value.raw_product
                if raw_product:
                    value = self.get_new_components_info(
                        raw_product.id,
                        raw_product.property_stock_production.id,
                        raw_product.property_stock_inventory.id,
                        raw_product.uom_id.id,
                        raw_product.uos_id.id,
                        op.qty, workorder)
                    linked_raw_products.append(value)
            for line in new_op.product_lines:
                if self.product_id.product_tmpl_id == line.product_template:
                    if new_op.product_id.track_all or\
                            new_op.product_id.track_production:
                        for move in self.move_created_ids2:
                            if move.product_id == self.product_id:
                                line.lot = move.restrict_lot_id
                    line.product_id = self.product_id
                    new_op.manual_production_lot = line.lot.name
                    continue
            for link_product in linked_raw_products:
                recs = new_op.product_lines.filtered(
                    lambda x: x.product_id.id == link_product['product_id'])
                if recs:
                    recs.write(link_product)
                else:
                    add_product.append(link_product)
            new_op.write({
                'product_lines': map(lambda x: (0, 0, x), add_product),
                'production': self.id,
                'origin': self.name})
            op.packaging_production = new_op

    @api.multi
    def action_compute(self, properties=None):
        if not self.production:
            return super(MrpProduction, self).action_compute(properties)
        else:
            raise exceptions.Warning(_('You can not compute again the list.'))

class PackagingOperation(models.Model):
    _name = 'packaging.operation'
    _rec_name = 'product'

    @api.multi
    @api.onchange('product', 'qty')
    def _calculate_weight(self):
        for record in self:
            value = record.mapped('product.attribute_value_ids').filtered(
                'raw_product')
            record.fill = (value[:1].numeric_value or 1) * record.qty

    @api.multi
    @api.onchange('fill')
    def _exceded_fill_quantity_warning(self):
        self.ensure_one()
        if self.fill > self.operation.left_product_qty:
            return {'warning':
                    {'title': _('Warning'),
                     'message': _("You won't be able to pack %f, there is only"
                                  " %f left" %
                                  (self.fill,
                                   self.operation.left_product_qty))}}
        return {}

    @api.multi
    @api.depends('packaging_production')
    def _is_processed(self):
        for record in self:
            record.processed = (record.packaging_production and
                                record.packaging_production.state != 'cancel')

    @api.multi
    @api.depends('product')
    def _compute_package_product(self):
        for record in self:
            record.package_product = record.product.attribute_value_ids.mapped(
                'raw_product')[:1]

    product = fields.Many2one(
        comodel_name='product.product', string='Product', required=True,
        help='Product that is going to be manufactured')
    operation = fields.Many2one(comodel_name='mrp.production')
    qty = fields.Integer(
        string='Qty', digits=dp.get_precision('Product Unit of Measure'),
        help='Product Quantity. It will be the new manufacturing order'
        ' quantity if dump uom is equal to product uom')
    fill = fields.Float(
        string='Fill', digits=dp.get_precision('Product Unit of Measure'),
        help='Product linked Raw Material value * Product Quantity. It will be'
        ' the new manufacturing order quantity if dump UoM is not equal to'
        ' product UoM')
    packaging_production = fields.Many2one(
        comodel_name='mrp.production', string='Packing manufacturing order')
    processed = fields.Boolean(
        string='Processed', compute='_is_processed')
    packing_state = fields.Selection(
        string='Packing MO State', related='packaging_production.state')
    package_product = fields.Many2one(
        comodel_name='product.product', string='Package Product',
        compute='_compute_package_product')
<commit_msg>[IMP] mrp_packaging: extract production data get function<commit_after># -*- coding: utf-8 -*-
# (c) 2015 Mikel Arregi - AvanzOSC
# (c) 2015 Oihane Crucelaegui - AvanzOSC
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

from openerp import api, exceptions, fields, models, _
from openerp.addons import decimal_precision as dp

class MrpProduction(models.Model):
    _inherit = 'mrp.production'

    pack = fields.One2many(
        comodel_name='packaging.operation', inverse_name='operation')
    expected_production = fields.One2many(
        comodel_name='mrp.production', inverse_name='production',
        string='Expected Production')
    production = fields.Many2one(
        comodel_name='mrp.production', string='Production')
    final_product_qty = fields.Float(
        string='Produced product qty', compute='_final_product_qty',
        digits=dp.get_precision('Product Unit of Measure'),
        help='This amount is the real amount produced in the MO.')
    left_product_qty = fields.Float(
        string='Qty left for packaging', compute='_left_product_qty',
        digits=dp.get_precision('Product Unit of Measure'),
        help='This amount is indicative, it is calculated with packaging'
        ' orders that are not in canceled state.')

    @api.multi
    @api.depends('move_created_ids2')
    def _final_product_qty(self):
        for record in self:
            moves = record.mapped('move_created_ids2').filtered(
                lambda x: x.state == 'done' and
                not x.location_dest_id.scrap_location and
                x.product_id == record.product_id)
            record.final_product_qty = sum(moves.mapped('product_uom_qty'))

    @api.multi
    @api.depends('final_product_qty', 'expected_production')
    def _left_product_qty(self):
        for record in self:
            moves = record.mapped('move_created_ids2').filtered(
                lambda x: x.state == 'done' and
                x.location_dest_id.scrap_location and
                x.product_id == record.product_id)
            remaining_qty = (record.final_product_qty -
                             sum(moves.mapped('product_uom_qty')))
            for production in record.expected_production.filtered(
                    lambda x: x.state != 'cancel'):
                product = production.production.product_id
                if production.move_lines2:
                    remaining_qty -= sum(production.move_lines2.filtered(
                        lambda m: m.product_id == product
                        ).mapped('product_uom_qty'))
                elif production.move_lines:
                    remaining_qty -= sum(production.move_lines.filtered(
                        lambda m: m.product_id == product
                        ).mapped('product_uom_qty'))
                else:
                    remaining_qty -= sum(production.product_lines.filtered(
                        lambda p: p.product_id == product
                        ).mapped('product_qty'))
            record.left_product_qty = remaining_qty

    @api.multi
    def get_dump_packages(self):
        self.ensure_one()
        pack_lines = []
        lines = self.env['mrp.bom.line'].search(
            ['|', ('product_template', '=', self.product_template.id),
             ('product_id', '=', self.product_id.id)])
        exist_prod = [x.product.id for x in self.pack]
        for line in lines:
            if line not in exist_prod:
                packs = filter(
                    lambda x: x not in exist_prod,
                    line.bom_id.product_tmpl_id.product_variant_ids.ids)
                pack_line = map(
                    lambda x: (0, 0, {'product': x}), packs)
                pack_lines.extend(pack_line)
        self.write({'pack': pack_lines})

    @api.one
    def recalculate_product_qty(self, qty, product):
        line = self.product_lines.filtered(
            lambda x: x.product_id == product)
        line.write({'product_qty': qty})

    @api.one
    def assign_parent_lot(self, production):
        line = self.product_lines.filtered(
            lambda x: x.product_id == production.product_id)
        line.write({'lot': (
                    production.move_created_ids2 and
                    production.move_created_ids2[0].restrict_lot_id.id or
                    False)})

    def _get_packaging_production_data(self, op_line):
        equal_uom = op_line.product.uom_id.id == self.product_id.uom_id.id
        final_product_qty = equal_uom and op_line.fill or op_line.qty
        data = self.product_id_change(op_line.product.id, final_product_qty)
        if 'product_attributes' in data['value']:
            product_attributes = map(lambda x: (0, 0, x),
                                     data['value']['product_attributes'])
            data['value'].update({'product_attributes': product_attributes})
        name = self.env['ir.sequence'].get('mrp.production.packaging')
        data['value'].update({'product_id': op_line.product.id,
                              'product_qty': final_product_qty,
                              'name': name})
        return data['value']

    @api.one
    def create_mo_from_packaging_operation(self):
        for op in self.pack.filtered(lambda x: x.qty != 0 and not x.processed):
            linked_raw_products = []
            add_product = []
            production_vals = self._get_packaging_production_data(op)
            new_op = self.create(production_vals)
            new_op.action_compute()
            new_op.recalculate_product_qty(op.fill, self.product_id)
            new_op.assign_parent_lot(self)
            workorder =\
                new_op.workcenter_lines and new_op.workcenter_lines[0].id
            for attr_value in op.product.attribute_value_ids:
                raw_product = attr_value.raw_product
                if raw_product:
                    value = self.get_new_components_info(
                        raw_product.id,
                        raw_product.property_stock_production.id,
                        raw_product.property_stock_inventory.id,
                        raw_product.uom_id.id,
                        raw_product.uos_id.id,
                        op.qty, workorder)
                    linked_raw_products.append(value)
            for line in new_op.product_lines:
                if self.product_id.product_tmpl_id == line.product_template:
                    if new_op.product_id.track_all or\
                            new_op.product_id.track_production:
                        for move in self.move_created_ids2:
                            if move.product_id == self.product_id:
                                line.lot = move.restrict_lot_id
                    line.product_id = self.product_id
                    new_op.manual_production_lot = line.lot.name
                    continue
            for link_product in linked_raw_products:
                recs = new_op.product_lines.filtered(
                    lambda x: x.product_id.id == link_product['product_id'])
                if recs:
                    recs.write(link_product)
                else:
                    add_product.append(link_product)
            new_op.write({
                'product_lines': map(lambda x: (0, 0, x), add_product),
                'production': self.id,
                'origin': self.name})
            op.packaging_production = new_op

    @api.multi
    def action_compute(self, properties=None):
        if not self.production:
            return super(MrpProduction, self).action_compute(properties)
        else:
            raise exceptions.Warning(_('You can not compute again the list.'))

class PackagingOperation(models.Model):
    _name = 'packaging.operation'
    _rec_name = 'product'

    @api.multi
    @api.onchange('product', 'qty')
    def _calculate_weight(self):
        for record in self:
            value = record.mapped('product.attribute_value_ids').filtered(
                'raw_product')
            record.fill = (value[:1].numeric_value or 1) * record.qty

    @api.multi
    @api.onchange('fill')
    def _exceded_fill_quantity_warning(self):
        self.ensure_one()
        if self.fill > self.operation.left_product_qty:
            return {'warning':
                    {'title': _('Warning'),
                     'message': _("You won't be able to pack %f, there is only"
                                  " %f left" %
                                  (self.fill,
                                   self.operation.left_product_qty))}}
        return {}

    @api.multi
    @api.depends('packaging_production')
    def _is_processed(self):
        for record in self:
            record.processed = (record.packaging_production and
                                record.packaging_production.state != 'cancel')

    @api.multi
    @api.depends('product')
    def _compute_package_product(self):
        for record in self:
            record.package_product = record.product.attribute_value_ids.mapped(
                'raw_product')[:1]

    product = fields.Many2one(
        comodel_name='product.product', string='Product', required=True,
        help='Product that is going to be manufactured')
    operation = fields.Many2one(comodel_name='mrp.production')
    qty = fields.Integer(
        string='Qty', digits=dp.get_precision('Product Unit of Measure'),
        help='Product Quantity. It will be the new manufacturing order'
        ' quantity if dump uom is equal to product uom')
    fill = fields.Float(
        string='Fill', digits=dp.get_precision('Product Unit of Measure'),
        help='Product linked Raw Material value * Product Quantity. It will be'
        ' the new manufacturing order quantity if dump UoM is not equal to'
        ' product UoM')
    packaging_production = fields.Many2one(
        comodel_name='mrp.production', string='Packing manufacturing order')
    processed = fields.Boolean(
        string='Processed', compute='_is_processed')
    packing_state = fields.Selection(
        string='Packing MO State', related='packaging_production.state')
    package_product = fields.Many2one(
        comodel_name='product.product', string='Package Product',
        compute='_compute_package_product')
<|endoftext|>