<commit_before>from django.db import models
from django.conf import settings
from polymorphic.models import PolymorphicModel
from django.utils import timezone
from django.utils.html import strip_tags
import nacl.secret
import nacl.utils
import hashlib
from django.utils.crypto import pbkdf2, get_random_string
from django.template import Template, Context
from django.contrib.sites.models import Site
from django.core.mail.message import EmailMultiAlternatives

class Report(models.Model):
    encrypted = models.BinaryField(blank=False)
    owner = models.ForeignKey(settings.AUTH_USER_MODEL)
    added = models.DateTimeField(auto_now_add=True)
    last_edited = models.DateTimeField(blank=True, null=True)
    salt = models.CharField(blank=False, max_length=256)

    submitted_to_school = models.DateTimeField(blank=True, null=True)
    contact_phone = models.CharField(blank=True, null=True, max_length=256)
    contact_voicemail = models.TextField(blank=True, null=True)
    contact_email = models.EmailField(blank=True, null=True, max_length=256)
    contact_notes = models.TextField(blank=True, null=True)
    contact_name = models.TextField(blank=True, null=True)

    @property
    def entered_into_matching(self):
        first_match_report = self.matchreport_set.first()
        if first_match_report:
            return first_match_report.added
        else:
            return None

    match_found = models.BooleanField(default=False)

    class Meta:
        ordering = ('-added',)

    def encrypt_report(self, report_text, key):
        if not self.salt:
            self.salt = get_random_string()
        else:
            self.last_edited = timezone.now()
        stretched_key = pbkdf2(key, self.salt, settings.KEY_ITERATIONS, digest=hashlib.sha256)
        box = nacl.secret.SecretBox(stretched_key)
        message = report_text.encode('utf-8')
        nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE)
        encrypted = box.encrypt(message, nonce)
        self.encrypted = encrypted

    def decrypted_report(self, key):
        stretched_key = pbkdf2(key, self.salt, settings.KEY_ITERATIONS, digest=hashlib.sha256)
        box = nacl.secret.SecretBox(stretched_key)
        decrypted = box.decrypt(bytes(self.encrypted))
        return decrypted.decode('utf-8')

    def withdraw_from_matching(self):
        self.matchreport_set.all().delete()
        self.match_found = False

    @property
    def get_submitted_report_id(self):
        if self.submitted_to_school:
            sent_report = self.sentfullreport_set.first()
            report_id = sent_report.get_report_id() if sent_report else None
            return report_id
        else:
            return None

class EmailNotification(models.Model):
    name = models.CharField(blank=False, max_length=50, primary_key=True)
    subject = models.CharField(blank=False, max_length=77)
    body = models.TextField(blank=False)

    def __str__(self):
        return self.name

    def render_body(self, context={}):
        current_site = Site.objects.get_current()
        context['domain'] = current_site.domain
        return Template(self.body).render(Context(context))

    def render_body_plain(self, context={}):
        html = self.render_body(context)
        cleaned = html.replace('
','\n')
        cleaned = cleaned.replace('
','\n')
        cleaned = cleaned.replace('
','\n')
        cleaned = cleaned.replace('
', '\n')
        return strip_tags(cleaned)

    def send(self, to, from_email, context={}):
        email = EmailMultiAlternatives(self.subject, self.render_body_plain(context), from_email, to)
        email.attach_alternative(self.render_body(context), "text/html")
        email.send()

class MatchReport(models.Model):
    report = models.ForeignKey('Report')
    contact_phone = models.CharField(blank=False, max_length=256)
    contact_voicemail = models.TextField(blank=True, null=True)
    contact_name = models.TextField(blank=True, null=True)
    contact_email = models.EmailField(blank=False, max_length=256)
    contact_notes = models.TextField(blank=True, null=True)

    identifier = models.CharField(blank=False, max_length=500)
    name = models.CharField(blank=True, null=True, max_length=500)

    added = models.DateTimeField(auto_now_add=True)
    seen = models.BooleanField(blank=False, default=False)

    def __str__(self):
        return "Match report for report {0}".format(self.report.pk)

class SentReport(PolymorphicModel):
    #TODO: store link to s3 backup
    sent = models.DateTimeField(auto_now_add=True)
    to_address = models.EmailField(blank=False, null=False, max_length=256)

    def _get_id_for_schools(self, is_match):
        return "{0}-{1}-{2}".format(settings.SCHOOL_REPORT_PREFIX, '%05d' % self.id, 0 if is_match else 1)

class SentFullReport(SentReport):
    report = models.ForeignKey(Report, blank=True, null=True, on_delete=models.SET_NULL)

    def get_report_id(self):
        return self._get_id_for_schools(is_match=False)

class SentMatchReport(SentReport):
    reports = models.ManyToManyField(MatchReport)

    def get_report_id(self):
        return self._get_id_for_schools(is_match=True)
<commit_msg>Fill in __unicode__() automatically<commit_after>from django.db import models
from django.conf import settings
from polymorphic.models import PolymorphicModel
from django.utils import timezone
from django.utils.html import strip_tags
import nacl.secret
import nacl.utils
import hashlib
import six
from django.utils.crypto import pbkdf2, get_random_string
from django.template import Template, Context
from django.contrib.sites.models import Site
from django.core.mail.message import EmailMultiAlternatives

class Report(models.Model):
    encrypted = models.BinaryField(blank=False)
    owner = models.ForeignKey(settings.AUTH_USER_MODEL)
    added = models.DateTimeField(auto_now_add=True)
    last_edited = models.DateTimeField(blank=True, null=True)
    salt = models.CharField(blank=False, max_length=256)

    submitted_to_school = models.DateTimeField(blank=True, null=True)
    contact_phone = models.CharField(blank=True, null=True, max_length=256)
    contact_voicemail = models.TextField(blank=True, null=True)
    contact_email = models.EmailField(blank=True, null=True, max_length=256)
    contact_notes = models.TextField(blank=True, null=True)
    contact_name = models.TextField(blank=True, null=True)

    @property
    def entered_into_matching(self):
        first_match_report = self.matchreport_set.first()
        if first_match_report:
            return first_match_report.added
        else:
            return None

    match_found = models.BooleanField(default=False)

    class Meta:
        ordering = ('-added',)

    def encrypt_report(self, report_text, key):
        if not self.salt:
            self.salt = get_random_string()
        else:
            self.last_edited = timezone.now()
        stretched_key = pbkdf2(key, self.salt, settings.KEY_ITERATIONS, digest=hashlib.sha256)
        box = nacl.secret.SecretBox(stretched_key)
        message = report_text.encode('utf-8')
        nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE)
        encrypted = box.encrypt(message, nonce)
        self.encrypted = encrypted

    def decrypted_report(self, key):
        stretched_key = pbkdf2(key, self.salt, settings.KEY_ITERATIONS, digest=hashlib.sha256)
        box = nacl.secret.SecretBox(stretched_key)
        decrypted = box.decrypt(bytes(self.encrypted))
        return decrypted.decode('utf-8')

    def withdraw_from_matching(self):
        self.matchreport_set.all().delete()
        self.match_found = False

    @property
    def get_submitted_report_id(self):
        if self.submitted_to_school:
            sent_report = self.sentfullreport_set.first()
            report_id = sent_report.get_report_id() if sent_report else None
            return report_id
        else:
            return None

@six.python_2_unicode_compatible
class EmailNotification(models.Model):
    name = models.CharField(blank=False, max_length=50, primary_key=True)
    subject = models.CharField(blank=False, max_length=77)
    body = models.TextField(blank=False)

    def __str__(self):
        return self.name

    def render_body(self, context={}):
        current_site = Site.objects.get_current()
        context['domain'] = current_site.domain
        return Template(self.body).render(Context(context))

    def render_body_plain(self, context={}):
        html = self.render_body(context)
        cleaned = html.replace('
','\n')
        cleaned = cleaned.replace('
','\n')
        cleaned = cleaned.replace('
','\n')
        cleaned = cleaned.replace('
', '\n')
        return strip_tags(cleaned)

    def send(self, to, from_email, context={}):
        email = EmailMultiAlternatives(self.subject, self.render_body_plain(context), from_email, to)
        email.attach_alternative(self.render_body(context), "text/html")
        email.send()

@six.python_2_unicode_compatible
class MatchReport(models.Model):
    report = models.ForeignKey('Report')
    contact_phone = models.CharField(blank=False, max_length=256)
    contact_voicemail = models.TextField(blank=True, null=True)
    contact_name = models.TextField(blank=True, null=True)
    contact_email = models.EmailField(blank=False, max_length=256)
    contact_notes = models.TextField(blank=True, null=True)

    identifier = models.CharField(blank=False, max_length=500)
    name = models.CharField(blank=True, null=True, max_length=500)

    added = models.DateTimeField(auto_now_add=True)
    seen = models.BooleanField(blank=False, default=False)

    def __str__(self):
        return "Match report for report {0}".format(self.report.pk)

class SentReport(PolymorphicModel):
    #TODO: store link to s3 backup
    sent = models.DateTimeField(auto_now_add=True)
    to_address = models.EmailField(blank=False, null=False, max_length=256)

    def _get_id_for_schools(self, is_match):
        return "{0}-{1}-{2}".format(settings.SCHOOL_REPORT_PREFIX, '%05d' % self.id, 0 if is_match else 1)

class SentFullReport(SentReport):
    report = models.ForeignKey(Report, blank=True, null=True, on_delete=models.SET_NULL)

    def get_report_id(self):
        return self._get_id_for_schools(is_match=False)

class SentMatchReport(SentReport):
    reports = models.ManyToManyField(MatchReport)

    def get_report_id(self):
        return self._get_id_for_schools(is_match=True)
<|endoftext|>


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

# Copyright (c) 2015 Ericsson AB
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os

from calvin.actorstore.store import ActorStore, GlobalStore
from calvin.utilities.calvinlogger import get_logger

_log = get_logger(__name__)

def full_port_name(namespace, actor_name, port_name):
    if actor_name != ".":
        return namespace + ':' + actor_name + '.' + port_name
    return namespace + '.' + port_name

class Analyzer(object):

    """
    Process an cs_info dictionary (output from calvin parser) to
    produce a running calvin application.
    """

    # FIXME: Provide additional checks making use of
    #        - actor_def.inport_names and actor_def.outport_names
    #        - make use of arg_type (STRING, NUMBER, etc.)
    #        - analyze the actions wrt port use and token consumption:
    #          for f in actor_def.action_priority:
    #              print f.__name__, [x.cell_contents for x in f.__closure__]
    #
    def __init__(self, cs_info, verify=True):
        super(Analyzer, self).__init__()
        self.cs_info = cs_info
        self.local_components = cs_info['components'] if 'components' in cs_info else {}
        self.constants = {}
        self.app_info = {}
        self.connections = {}
        self.actors = {}
        self.verify = verify
        self.actorstore = ActorStore()
        self.analyze()

    def analyze(self):
        """
        Analyze a CalvinScript in canonical format (i.e. as given by the CS parser)
        and produce an app_info structure, sutitable for deploying an application.
        The app_info contains a dict of actors and their type, arguments, etc., and
        a dict of connections between ports where output ports are keys and the
        corresponding value is a list of input ports to connect to.
        The value for the 'valid' key is True of the script is syntactically correct.

        A CalvinScript consists of component definitions, and a _structure_ defining
        the actual script. Each component definition consists of statements declaring
        ports and arguments, and a _structure_ part, defining what the component does.
        """
        self.script_name = os.path.basename(self.cs_info['sourcefile'])
        s = self.cs_info['structure']
        root_namespace, _ = os.path.splitext(self.script_name)
        self.constants = self.cs_info['constants']
        argd = {}
        valid = True

        try:
            self.analyze_structure(s, root_namespace, argd)
        except Exception as e:
            _log.exception(e)
            valid = False
        self.app_info = {'valid': valid, 'actors': self.actors, 'connections': self.connections}
        if self.script_name:
            self.app_info['name'] = self.script_name

    def debug_info(self, d):
        file = 'File "%s"' % self.script_name
        line = ', line %d' % d['dbg_line'] if 'dbg_line' in d else ''
        return file + line

    def lookup_constant(self, identifier):
        """
        Return value for constant 'identifier'
        Raise an exception if not found
        """
        kind, value = self.constants[identifier]
        if kind != "IDENTIFIER":
            return (kind, value)
        return self.lookup_constant(value)

    def lookup(self, actor_type):
        """
        Search for the definition of 'actor_type'.
        Returns a tuple (found, is_primitive, info) where info is either a
        class (primitive) or a dictionary with component definition
        Search order:
          1 - components defined in the current script: self.local_components
          2 - primitive actors in the order defined by actor store
          3 - components in the order defined by actor store
        Steps 2 and 3 are handled by generic lookup in actor store
        """
        if actor_type in self.local_components:
            compdef = self.local_components[actor_type]
            return compdef, False
        found, is_actor, info, signer = self.actorstore.lookup(actor_type)
        if self.verify and not found:
            msg = 'Actor "{}" not found.'.format(actor_type)
            raise Exception(msg)
        return info, is_actor or not found

    def add_connection(self, src_actor_port, dst_actor_port):
        if type(dst_actor_port) is list:
            self.connections.setdefault(src_actor_port, []).extend(dst_actor_port)
        else:
            self.connections.setdefault(src_actor_port, []).append(dst_actor_port)

    def expand_literals(self, structure, argd):
        # Check for literals on inports...
        const_count = 1
        implicit = [c for c in structure['connections'] if not c['src']]
        for c in implicit:
            kind, value = c['src_port']
            if kind == "IDENTIFIER":
                if value in argd:
                    kind, value = ('VALUE', argd[value])
                else:
                    kind, value = self.lookup_constant(value)
            # Replace constant with std.Constant(data=value, n=-1) its outport
            name = '_literal_const_' + str(const_count)
            const_count += 1
            # Replace implicit actor with actual actor ...
            structure['actors'][name] = {
                'actor_type': 'std.Constant',
                'args': {
                    'data': (kind, value),
                    'n': ('NUMBER', -1)
                },
                'dbg_line': c['dbg_line']}
            # ... and create a connection from it
            c['src'] = name
            c['src_port'] = 'token'

    def resolve_arguments(self, arguments, argd):
        args = {}
        for arg_name, (arg_type, arg_value) in arguments.iteritems():
            if arg_type == 'IDENTIFIER':
                # We are looking for the value of a variable whose name is in value
                variable_name = arg_value
                if variable_name in argd:
                    arg_value = argd[variable_name]
                else:
                    _, arg_value = self.lookup_constant(variable_name)
            args[arg_name] = arg_value
        return args

    def create_connection(self, c, namespace, in_mappings, out_mappings):
        # export_mapping = {'in':{}, 'out':{}}
        # Get the full port name.
        # If src/dst is ".", the full port name is component port name at caller level
        src_actor_port = full_port_name(namespace, c['src'], c['src_port'])
        dst_actor_port = full_port_name(namespace, c['dst'], c['dst_port'])

        # resolve any references to components first
        # N.B. if there is a match for src_actor_port the result is a list:
        dst_actor_port = in_mappings.get(dst_actor_port, dst_actor_port)
        src_actor_port = out_mappings.get(src_actor_port, src_actor_port)

        # Add connections if possible, or export a port mapping for calling level
        if c['src'] != '.' and c['dst'] != '.':
            self.add_connection(src_actor_port, dst_actor_port)
            export_mapping = {}, {}
        elif c['dst'] != '.':
            # Add mapping from component inport to internal actors/components
            if type(dst_actor_port) is not list:
                dst_actor_port = [dst_actor_port]
            export_mapping = {src_actor_port: dst_actor_port}, {}
        else:
            # Add mapping from internal actor/component to component outport
            export_mapping = {}, {dst_actor_port: src_actor_port}

        return export_mapping

    def analyze_structure(self, structure, namespace, argd):
        """
        Analyze a (sub) structure and resolve actor names, arguments, and connections.
        Parameter argd is a dict with arguments for the structure
        Returns a dict with port mappings corresponding to the externally visible ports
        of the structure, i.e. the ports of a component.
        """
        # Check for literals on inports...
        self.expand_literals(structure, argd)

        in_mappings = {}
        out_mappings = {}
        for actor_name, actor_def in structure['actors'].iteritems():
            # Look up actor
            info, is_actor = self.lookup(actor_def['actor_type'])
            # Resolve arguments
            args = self.resolve_arguments(actor_def['args'], argd)

            qualified_name = namespace + ':' + actor_name

            if is_actor:
                # Create the actor signature to be able to look it up in the GlobalStore if neccessary
                signature_desc = {'is_primitive': True,
                                  'actor_type': actor_def['actor_type'],
                                  'inports': [],
                                  'outports': []}
                for c in structure['connections']:
                    if actor_name == c['src'] and c['src_port'] not in signature_desc['outports']:
                        signature_desc['outports'].append(c['src_port'])
                    elif actor_name == c['dst'] and c['dst_port'] not in signature_desc['inports']:
                        signature_desc['inports'].append(c['dst_port'])
                signature = GlobalStore.actor_signature(signature_desc)
                # Add actor and its arguments to the list of actor instances
                self.actors[qualified_name] = {'actor_type': actor_def['actor_type'], 'args': args,
                                               'signature': signature, 'signature_desc': signature_desc}
            else:
                # Recurse into components
                # qualified_name constitutes a namespace here
                comp_in_mapping, comp_out_mapping = self.analyze_structure(info['structure'], qualified_name, args)
                in_mappings.update(comp_in_mapping)
                out_mappings.update(comp_out_mapping)

        export_in_mappings = {}
        export_out_mappings = {}
        for c in structure['connections']:
            in_mapping, out_mapping = self.create_connection(c, namespace, in_mappings, out_mappings)
            for p in in_mapping:
                export_in_mappings.setdefault(p, []).extend(in_mapping[p])
            export_out_mappings.update(out_mapping)

        return export_in_mappings, export_out_mappings

def generate_app_info(cs_info, verify=True):
    a = Analyzer(cs_info, verify=verify)
    return a.app_info

if __name__ == '__main__':
    import cscompiler
    import json

    filename = 'scripts/test2.calvin'
    with open(filename, 'r') as f:
        script = f.read()
        print script
        print "---------------"
        data, errors, warnings = cscompiler.compile(script, filename)
        if errors:
            print "{reason} {script} [{line}:{col}]".format(script=filename, **errors[0])

        a = Analyzer(data)
        print "======= DONE ========"
        print json.dumps(a.app_info, indent=4, sort_keys=True)
<commit_msg>Factor out signature creation<commit_after># -*- coding: utf-8 -*-

# Copyright (c) 2015 Ericsson AB
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os

from calvin.actorstore.store import ActorStore, GlobalStore
from calvin.utilities.calvinlogger import get_logger

_log = get_logger(__name__)

def full_port_name(namespace, actor_name, port_name):
    if actor_name != ".":
        return namespace + ':' + actor_name + '.' + port_name
    return namespace + '.' + port_name

def _create_signature(actor_name, actor_type, connections):
    # Create the actor signature to be able to look it up in the GlobalStore if neccessary
    signature_desc = {'is_primitive': True,
                      'actor_type': actor_type,
                      'inports': [],
                      'outports': []}
    for c in connections:
        if actor_name == c['src'] and c['src_port'] not in signature_desc['outports']:
            signature_desc['outports'].append(c['src_port'])
        elif actor_name == c['dst'] and c['dst_port'] not in signature_desc['inports']:
            signature_desc['inports'].append(c['dst_port'])
    return GlobalStore.actor_signature(signature_desc)

class Analyzer(object):

    """
    Process an cs_info dictionary (output from calvin parser) to
    produce a running calvin application.
    """

    # FIXME: Provide additional checks making use of
    #        - actor_def.inport_names and actor_def.outport_names
    #        - make use of arg_type (STRING, NUMBER, etc.)
    #        - analyze the actions wrt port use and token consumption:
    #          for f in actor_def.action_priority:
    #              print f.__name__, [x.cell_contents for x in f.__closure__]
    #
    def __init__(self, cs_info, verify=True):
        super(Analyzer, self).__init__()
        self.cs_info = cs_info
        self.local_components = cs_info['components'] if 'components' in cs_info else {}
        self.constants = {}
        self.app_info = {}
        self.connections = {}
        self.actors = {}
        self.verify = verify
        self.actorstore = ActorStore()
        self.analyze()

    def analyze(self):
        """
        Analyze a CalvinScript in canonical format (i.e. as given by the CS parser)
        and produce an app_info structure, sutitable for deploying an application.
        The app_info contains a dict of actors and their type, arguments, etc., and
        a dict of connections between ports where output ports are keys and the
        corresponding value is a list of input ports to connect to.
        The value for the 'valid' key is True of the script is syntactically correct.

        A CalvinScript consists of component definitions, and a _structure_ defining
        the actual script. Each component definition consists of statements declaring
        ports and arguments, and a _structure_ part, defining what the component does.
        """
        self.script_name = os.path.basename(self.cs_info['sourcefile'])
        s = self.cs_info['structure']
        root_namespace, _ = os.path.splitext(self.script_name)
        self.constants = self.cs_info['constants']
        argd = {}
        valid = True

        try:
            self.analyze_structure(s, root_namespace, argd)
        except Exception as e:
            _log.exception(e)
            valid = False
        self.app_info = {'valid': valid, 'actors': self.actors, 'connections': self.connections}
        if self.script_name:
            self.app_info['name'] = self.script_name

    def debug_info(self, d):
        file = 'File "%s"' % self.script_name
        line = ', line %d' % d['dbg_line'] if 'dbg_line' in d else ''
        return file + line

    def lookup_constant(self, identifier):
        """
        Return value for constant 'identifier'
        Raise an exception if not found
        """
        kind, value = self.constants[identifier]
        if kind != "IDENTIFIER":
            return (kind, value)
        return self.lookup_constant(value)

    def lookup(self, actor_type):
        """
        Search for the definition of 'actor_type'.
        Returns a tuple (found, is_primitive, info) where info is either a
        class (primitive) or a dictionary with component definition
        Search order:
          1 - components defined in the current script: self.local_components
          2 - primitive actors in the order defined by actor store
          3 - components in the order defined by actor store
        Steps 2 and 3 are handled by generic lookup in actor store
        """
        if actor_type in self.local_components:
            compdef = self.local_components[actor_type]
            return compdef, False
        found, is_actor, info, signer = self.actorstore.lookup(actor_type)
        if self.verify and not found:
            msg = 'Actor "{}" not found.'.format(actor_type)
            raise Exception(msg)
        return info, is_actor or not found

    def add_connection(self, src_actor_port, dst_actor_port):
        if type(dst_actor_port) is list:
            self.connections.setdefault(src_actor_port, []).extend(dst_actor_port)
        else:
            self.connections.setdefault(src_actor_port, []).append(dst_actor_port)

    def expand_literals(self, structure, argd):
        # Check for literals on inports...
        const_count = 1
        implicit = [c for c in structure['connections'] if not c['src']]
        for c in implicit:
            kind, value = c['src_port']
            if kind == "IDENTIFIER":
                if value in argd:
                    kind, value = ('VALUE', argd[value])
                else:
                    kind, value = self.lookup_constant(value)
            # Replace constant with std.Constant(data=value, n=-1) its outport
            name = '_literal_const_' + str(const_count)
            const_count += 1
            # Replace implicit actor with actual actor ...
            structure['actors'][name] = {
                'actor_type': 'std.Constant',
                'args': {
                    'data': (kind, value),
                    'n': ('NUMBER', -1)
                },
                'dbg_line': c['dbg_line']}
            # ... and create a connection from it
            c['src'] = name
            c['src_port'] = 'token'

    def resolve_arguments(self, arguments, argd):
        args = {}
        for arg_name, (arg_type, arg_value) in arguments.iteritems():
            if arg_type == 'IDENTIFIER':
                # We are looking for the value of a variable whose name is in value
                variable_name = arg_value
                if variable_name in argd:
                    arg_value = argd[variable_name]
                else:
                    _, arg_value = self.lookup_constant(variable_name)
            args[arg_name] = arg_value
        return args

    def create_connection(self, c, namespace, in_mappings, out_mappings):
        # export_mapping = {'in':{}, 'out':{}}
        # Get the full port name.
        # If src/dst is ".", the full port name is component port name at caller level
        src_actor_port = full_port_name(namespace, c['src'], c['src_port'])
        dst_actor_port = full_port_name(namespace, c['dst'], c['dst_port'])

        # resolve any references to components first
        # N.B. if there is a match for src_actor_port the result is a list:
        dst_actor_port = in_mappings.get(dst_actor_port, dst_actor_port)
        src_actor_port = out_mappings.get(src_actor_port, src_actor_port)

        # Add connections if possible, or export a port mapping for calling level
        if c['src'] != '.' and c['dst'] != '.':
            self.add_connection(src_actor_port, dst_actor_port)
            export_mapping = {}, {}
        elif c['dst'] != '.':
            # Add mapping from component inport to internal actors/components
            if type(dst_actor_port) is not list:
                dst_actor_port = [dst_actor_port]
            export_mapping = {src_actor_port: dst_actor_port}, {}
        else:
            # Add mapping from internal actor/component to component outport
            export_mapping = {}, {dst_actor_port: src_actor_port}

        return export_mapping

    def analyze_structure(self, structure, namespace, argd):
        """
        Analyze a (sub) structure and resolve actor names, arguments, and connections.
        Parameter argd is a dict with arguments for the structure
        Returns a dict with port mappings corresponding to the externally visible ports
        of the structure, i.e. the ports of a component.
        """
        # Check for literals on inports...
        self.expand_literals(structure, argd)

        in_mappings = {}
        out_mappings = {}
        for actor_name, actor_def in structure['actors'].iteritems():
            # Look up actor
            info, is_actor = self.lookup(actor_def['actor_type'])
            # Resolve arguments
            args = self.resolve_arguments(actor_def['args'], argd)

            qualified_name = namespace + ':' + actor_name

            if is_actor:
                # Add actor and its arguments to the list of actor instances
                self.actors[qualified_name] = {
                    'actor_type': actor_def['actor_type'],
                    'args': args,
                    'signature': _create_signature(actor_name, actor_def['actor_type'], structure['connections'])
                }
            else:
                # Recurse into components
                # qualified_name constitutes a namespace here
                comp_in_mapping, comp_out_mapping = self.analyze_structure(info['structure'], qualified_name, args)
                in_mappings.update(comp_in_mapping)
                out_mappings.update(comp_out_mapping)

        export_in_mappings = {}
        export_out_mappings = {}
        for c in structure['connections']:
            in_mapping, out_mapping = self.create_connection(c, namespace, in_mappings, out_mappings)
            for p in in_mapping:
                export_in_mappings.setdefault(p, []).extend(in_mapping[p])
            export_out_mappings.update(out_mapping)

        return export_in_mappings, export_out_mappings

def generate_app_info(cs_info, verify=True):
    a = Analyzer(cs_info, verify=verify)
    return a.app_info

if __name__ == '__main__':
    import cscompiler
    import json

    filename = 'scripts/test2.calvin'
    with open(filename, 'r') as f:
        script = f.read()
        print script
        print "---------------"
        data, errors, warnings = cscompiler.compile(script, filename)
        if errors:
            print "{reason} {script} [{line}:{col}]".format(script=filename, **errors[0])

        a = Analyzer(data)
        print "======= DONE ========"
        print json.dumps(a.app_info, indent=4, sort_keys=True)
<|endoftext|>


<commit_before># Copyright (C) 2016 OpenMotics BV
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""
Tests for MasterCommunicator module.
"""

from __future__ import absolute_import

import threading
import time
import unittest

import xmlrunner
from pytest import mark

from gateway.maintenance_communicator import InMaintenanceModeException
from ioc import SetTestMode, SetUpTestInjections
from master.classic import master_api
from master.classic.master_communicator import BackgroundConsumer, \
    CrcCheckFailedException, MasterCommunicator
from serial_test import DummyPty
from serial_utils import CommunicationTimedOutException

class MasterCommunicatorTest(unittest.TestCase):
    """ Tests for MasterCommunicator class """

    @classmethod
    def setUpClass(cls):
        SetTestMode()

    def test_do_command(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        pty = DummyPty([action.create_input(1, fields)])
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.start()

        pty.master_reply(action.create_output(1, {'resp': 'OK'}))
        output = comm.do_command(action, fields)
        self.assertEqual('OK', output['resp'])

    @mark.slow
    def test_timeout(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        pty = DummyPty([action.create_input(1, fields)])
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.start()

        self.assertRaises(CommunicationTimedOutException, comm.do_command, action, fields)

    def test_timeout_ongoing(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        pty = DummyPty([action.create_input(1, fields),
                        action.create_input(2, fields)])
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.start()

        self.assertRaises(CommunicationTimedOutException, comm.do_command, action, fields,
                          timeout=0.1)

        pty.master_reply(action.create_output(2, {'resp': 'OK'}))
        output = comm.do_command(action, fields)
        self.assertEqual('OK', output['resp'])

    @mark.slow
    def test_split_data(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        sequence = []
        for i in range(1, 18):
            sequence.append(action.create_input(i, fields))

        pty = DummyPty(sequence)
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.start()

        for i in range(1, 18):
            data = action.create_output(i, {'resp': 'OK'})

            ready = threading.Event()

            def write():
                pty.master_reply(data[:i])
                ready.set()
                pty.master_wait()
                pty.fd.write(data[i:])

            thread = threading.Thread(target=write)
            thread.start()

            ready.wait(2)
            output = comm.do_command(action, fields)
            self.assertEqual('OK', output['resp'])
            thread.join(2)
            assert not thread.is_alive()

    def test_passthrough(self):
        pty = DummyPty(['data from passthrough'])
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.enable_passthrough()
        comm.start()

        pty.master_reply(bytearray(b'got it!'))
        comm.send_passthrough_data(bytearray(b'data from passthrough'))
        self.assertEqual(bytearray(b'got it!'), comm.get_passthrough_data())

    def test_passthrough_with_commands(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        pty = DummyPty([action.create_input(1, fields),
                        action.create_input(2, fields),
                        action.create_input(3, fields)])
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.enable_passthrough()
        comm.start()

        pty.master_reply(bytearray(b'hello') + action.create_output(1, {'resp': 'OK'}))
        self.assertEqual('OK', comm.do_command(action, fields)['resp'])
        self.assertEqual(bytearray(b'hello'), comm.get_passthrough_data())

        pty.master_reply(action.create_output(2, {'resp': 'OK'}) + bytearray(b'world'))
        self.assertEqual('OK', comm.do_command(action, fields)['resp'])
        self.assertEqual(bytearray(b'world'), comm.get_passthrough_data())

        pty.master_reply(bytearray(b'hello') + action.create_output(3, {'resp': 'OK'}) + bytearray(b' world'))
        self.assertEqual('OK', comm.do_command(action, fields)['resp'])
        self.assertEqual(bytearray(b'hello world'), comm.get_passthrough_data())

    def test_maintenance_mode(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        pty = DummyPty([master_api.to_cli_mode().create_input(0),
                        bytearray(b'error list\r\n'), bytearray(b'exit\r\n')])
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.start()

        comm.start_maintenance_mode()
        pty.fd.write(bytearray(b'OK'))
        self.assertRaises(InMaintenanceModeException, comm.do_command, action, fields)
        self.assertEqual(bytearray(b'OK'), comm.get_maintenance_data())

        comm.send_maintenance_data(bytearray(b'error list\r\n'))
        pty.fd.write(bytearray(b'the list\n'))
        self.assertEqual(bytearray(b'the list\n'), comm.get_maintenance_data())

        comm.stop_maintenance_mode()

    def test_maintenance_passthrough(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        pty = DummyPty([master_api.to_cli_mode().create_input(0),
                        bytearray(b'error list\r\n'), bytearray(b'exit\r\n')])
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.enable_passthrough()
        comm.start()

        ready = threading.Event()

        def get_passthrough():
            """ Background thread that reads the passthrough data. """
            self.assertEqual('Before maintenance', comm.get_passthrough_data())
            ready.set()
            self.assertEqual('After maintenance', comm.get_passthrough_data())

        thread = threading.Thread(target=get_passthrough)
        thread.start()

        pty.fd.write(bytearray(b'Before maintenance'))
        ready.wait(2)
        comm.start_maintenance_mode()

        pty.fd.write(bytearray(b'OK'))
        time.sleep(0.2)
        self.assertRaises(InMaintenanceModeException, comm.do_command, action, fields)
        self.assertEqual(bytearray(b'OK'), comm.get_maintenance_data())

        comm.send_maintenance_data(bytearray(b'error list\r\n'))
        pty.fd.write(bytearray(b'the list\n'))
        time.sleep(0.2)
        self.assertEqual(bytearray(b'the list\n'), comm.get_maintenance_data())

        comm.stop_maintenance_mode()
        pty.fd.write(bytearray(b'After maintenance'))

        thread.join(2)
        assert not thread.is_alive()

    def test_background_consumer(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        pty = DummyPty([action.create_input(1, fields)])
        SetUpTestInjections(controller_serial=pty)

        got_output = {'phase': 1}

        def callback(output):
            """ Callback that check if the correct result was returned for OL. """
            if got_output['phase'] == 1:
                self.assertEqual([(3, int(12 * 10.0 / 6.0))], output['outputs'])
                got_output['phase'] = 2
            elif got_output['phase'] == 2:
                self.assertEqual([(3, int(12 * 10.0 / 6.0)), (5, int(6 * 10.0 / 6.0))],
                                 output['outputs'])
                got_output['phase'] = 3

        comm = MasterCommunicator(init_master=False)
        comm.enable_passthrough()
        comm.register_consumer(BackgroundConsumer(master_api.output_list(), 0, callback))
        comm.start()

        pty.fd.write(bytearray(b'OL\x00\x01\x03\x0c\r\n'))
        pty.fd.write(bytearray(b'junkOL\x00\x02\x03\x0c\x05\x06\r\n here'))

        pty.master_reply(action.create_output(1, {'resp': 'OK'}))
        output = comm.do_command(action, fields)
        self.assertEqual('OK', output['resp'])

        self.assertEqual(3, got_output['phase'])
        self.assertEqual(bytearray(b'junk here'), comm.get_passthrough_data())

    def test_background_consumer_passthrough(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        pty = DummyPty([action.create_input(1, fields)])
        SetUpTestInjections(controller_serial=pty)

        got_output = {'passed': False}

        def callback(output_):
            """ Callback that check if the correct result was returned for OL. """
            self.assertEqual([(3, int(12 * 10.0 / 6.0))], output_['outputs'])
            got_output['passed'] = True

        comm = MasterCommunicator(init_master=False)
        comm.enable_passthrough()
        comm.register_consumer(BackgroundConsumer(master_api.output_list(), 0, callback, True))
        comm.start()

        pty.fd.write(bytearray(b'OL\x00\x01'))
        pty.fd.write(bytearray(b'\x03\x0c\r\n'))

        pty.master_reply(action.create_output(1, {'resp': 'OK'}))
        output = comm.do_command(action, fields)
        self.assertEqual('OK', output['resp'])

        self.assertEqual(True, got_output['passed'])
        self.assertEqual(bytearray(b'OL\x00\x01\x03\x0c\r\n'), comm.get_passthrough_data())

    def test_bytes_counter(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        pty = DummyPty([action.create_input(1, fields)])
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.enable_passthrough()
        comm.start()

        pty.fd.write(bytearray(b'hello'))
        pty.master_reply(action.create_output(1, {'resp': 'OK'}))
        comm.do_command(action, fields)
        self.assertEqual(bytearray(b'hello'), comm.get_passthrough_data())

        self.assertEqual(21, comm.get_communication_statistics()['bytes_written'])
        self.assertEqual(5 + 18, comm.get_communication_statistics()['bytes_read'])

    def test_crc_checking(self):
        action = master_api.sensor_humidity_list()

        fields1 = {}
        for i in range(0, 32):
            fields1['hum%d' % i] = master_api.Svt(master_api.Svt.RAW, i)
        fields1['crc'] = bytearray([ord('C'), 1, 240])

        fields2 = {}
        for i in range(0, 32):
            fields2['hum%d' % i] = master_api.Svt(master_api.Svt.RAW, 2 * i)
        fields2['crc'] = bytearray([ord('C'), 0, 0])

        pty = DummyPty([action.create_input(1),
                        action.create_input(2)])
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.start()

        pty.master_reply(action.create_output(1, fields1))
        output = comm.do_command(action)
        self.assertEqual(bytearray(b'\x00'), output['hum0'].get_byte())
        self.assertEqual(bytearray(b'\x01'), output['hum1'].get_byte())

        pty.master_reply(action.create_output(2, fields2))
        with self.assertRaises(CrcCheckFailedException):
            comm.do_command(action)

if __name__ == '__main__':
    unittest.main(testRunner=xmlrunner.XMLTestRunner(output='../gw-unit-reports'))
<commit_msg>add misalignment test to master communicator<commit_after># Copyright (C) 2016 OpenMotics BV
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""
Tests for MasterCommunicator module.
"""

from __future__ import absolute_import

import threading
import time
import unittest

import xmlrunner
from pytest import mark

from gateway.maintenance_communicator import InMaintenanceModeException
from ioc import SetTestMode, SetUpTestInjections
from master.classic import master_api
from master.classic.master_communicator import BackgroundConsumer, \
    CrcCheckFailedException, MasterCommunicator
from serial_test import DummyPty
from serial_utils import CommunicationTimedOutException

class MasterCommunicatorTest(unittest.TestCase):
    """ Tests for MasterCommunicator class """

    @classmethod
    def setUpClass(cls):
        SetTestMode()

    def test_do_command(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        pty = DummyPty([action.create_input(1, fields)])
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.start()

        pty.master_reply(action.create_output(1, {'resp': 'OK'}))
        output = comm.do_command(action, fields)
        self.assertEqual('OK', output['resp'])

    @mark.slow
    def test_timeout(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        pty = DummyPty([action.create_input(1, fields)])
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.start()

        self.assertRaises(CommunicationTimedOutException, comm.do_command, action, fields)

    def test_timeout_ongoing(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        pty = DummyPty([action.create_input(1, fields),
                        action.create_input(2, fields)])
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.start()

        self.assertRaises(CommunicationTimedOutException, comm.do_command, action, fields,
                          timeout=0.1)

        pty.master_reply(action.create_output(2, {'resp': 'OK'}))
        output = comm.do_command(action, fields)
        self.assertEqual('OK', output['resp'])

    @mark.slow
    def test_split_data(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        sequence = []
        for i in range(1, 18):
            sequence.append(action.create_input(i, fields))

        pty = DummyPty(sequence)
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.start()

        for i in range(1, 18):
            data = action.create_output(i, {'resp': 'OK'})

            ready = threading.Event()

            def write():
                pty.master_reply(data[:i])
                ready.set()
                pty.master_wait()
                pty.fd.write(data[i:])

            thread = threading.Thread(target=write)
            thread.start()

            ready.wait(2)
            output = comm.do_command(action, fields)
            self.assertEqual('OK', output['resp'])
            thread.join(2)
            assert not thread.is_alive()

    @mark.skip
    def test_misalignment(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        pty = DummyPty([action.create_input(1, fields),
                        action.create_input(2, fields)])
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.start()

        data = action.create_output(1, {'resp': 'OK'})
        # Only send partial data.
        pty.master_reply(data[:-4])
        pty.master_reply(b'\r\n')
        with self.assertRaises(CommunicationTimedOutException):
            comm.do_command(action, fields)

        # Next message processed correctly.
        pty.master_reply(action.create_output(2, {'resp': 'OK'}))
        output = comm.do_command(action, fields)
        self.assertEqual('OK', output['resp'])

    def test_passthrough(self):
        pty = DummyPty([b'data from passthrough'])
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.enable_passthrough()
        comm.start()

        pty.master_reply(bytearray(b'got it!'))
        comm.send_passthrough_data(bytearray(b'data from passthrough'))
        self.assertEqual(bytearray(b'got it!'), comm.get_passthrough_data())

    def test_passthrough_with_commands(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        pty = DummyPty([action.create_input(1, fields),
                        action.create_input(2, fields),
                        action.create_input(3, fields)])
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.enable_passthrough()
        comm.start()

        pty.master_reply(bytearray(b'hello') + action.create_output(1, {'resp': 'OK'}))
        self.assertEqual('OK', comm.do_command(action, fields)['resp'])
        self.assertEqual(bytearray(b'hello'), comm.get_passthrough_data())

        pty.master_reply(action.create_output(2, {'resp': 'OK'}) + bytearray(b'world'))
        self.assertEqual('OK', comm.do_command(action, fields)['resp'])
        self.assertEqual(bytearray(b'world'), comm.get_passthrough_data())

        pty.master_reply(bytearray(b'hello') + action.create_output(3, {'resp': 'OK'}) + bytearray(b' world'))
        self.assertEqual('OK', comm.do_command(action, fields)['resp'])
        self.assertEqual(bytearray(b'hello world'), comm.get_passthrough_data())

    def test_maintenance_mode(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        pty = DummyPty([master_api.to_cli_mode().create_input(0),
                        bytearray(b'error list\r\n'), bytearray(b'exit\r\n')])
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.start()

        comm.start_maintenance_mode()
        pty.fd.write(bytearray(b'OK'))
        self.assertRaises(InMaintenanceModeException, comm.do_command, action, fields)
        self.assertEqual(bytearray(b'OK'), comm.get_maintenance_data())

        comm.send_maintenance_data(bytearray(b'error list\r\n'))
        pty.fd.write(bytearray(b'the list\n'))
        self.assertEqual(bytearray(b'the list\n'), comm.get_maintenance_data())

        comm.stop_maintenance_mode()

    def test_maintenance_passthrough(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        pty = DummyPty([master_api.to_cli_mode().create_input(0),
                        bytearray(b'error list\r\n'), bytearray(b'exit\r\n')])
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.enable_passthrough()
        comm.start()

        ready = threading.Event()

        def get_passthrough():
            """ Background thread that reads the passthrough data. """
            self.assertEqual('Before maintenance', comm.get_passthrough_data())
            ready.set()
            self.assertEqual('After maintenance', comm.get_passthrough_data())

        thread = threading.Thread(target=get_passthrough)
        thread.start()

        pty.fd.write(bytearray(b'Before maintenance'))
        ready.wait(2)
        comm.start_maintenance_mode()

        pty.fd.write(bytearray(b'OK'))
        time.sleep(0.2)
        self.assertRaises(InMaintenanceModeException, comm.do_command, action, fields)
        self.assertEqual(bytearray(b'OK'), comm.get_maintenance_data())

        comm.send_maintenance_data(bytearray(b'error list\r\n'))
        pty.fd.write(bytearray(b'the list\n'))
        time.sleep(0.2)
        self.assertEqual(bytearray(b'the list\n'), comm.get_maintenance_data())

        comm.stop_maintenance_mode()
        pty.fd.write(bytearray(b'After maintenance'))

        thread.join(2)
        assert not thread.is_alive()

    def test_background_consumer(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        pty = DummyPty([action.create_input(1, fields)])
        SetUpTestInjections(controller_serial=pty)

        got_output = {'phase': 1}

        def callback(output):
            """ Callback that check if the correct result was returned for OL. """
            if got_output['phase'] == 1:
                self.assertEqual([(3, int(12 * 10.0 / 6.0))], output['outputs'])
                got_output['phase'] = 2
            elif got_output['phase'] == 2:
                self.assertEqual([(3, int(12 * 10.0 / 6.0)), (5, int(6 * 10.0 / 6.0))],
                                 output['outputs'])
                got_output['phase'] = 3

        comm = MasterCommunicator(init_master=False)
        comm.enable_passthrough()
        comm.register_consumer(BackgroundConsumer(master_api.output_list(), 0, callback))
        comm.start()

        pty.fd.write(bytearray(b'OL\x00\x01\x03\x0c\r\n'))
        pty.fd.write(bytearray(b'junkOL\x00\x02\x03\x0c\x05\x06\r\n here'))

        pty.master_reply(action.create_output(1, {'resp': 'OK'}))
        output = comm.do_command(action, fields)
        self.assertEqual('OK', output['resp'])

        self.assertEqual(3, got_output['phase'])
        self.assertEqual(bytearray(b'junk here'), comm.get_passthrough_data())

    def test_background_consumer_passthrough(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        pty = DummyPty([action.create_input(1, fields)])
        SetUpTestInjections(controller_serial=pty)

        got_output = {'passed': False}

        def callback(output_):
            """ Callback that check if the correct result was returned for OL. """
            self.assertEqual([(3, int(12 * 10.0 / 6.0))], output_['outputs'])
            got_output['passed'] = True

        comm = MasterCommunicator(init_master=False)
        comm.enable_passthrough()
        comm.register_consumer(BackgroundConsumer(master_api.output_list(), 0, callback, True))
        comm.start()

        pty.fd.write(bytearray(b'OL\x00\x01'))
        pty.fd.write(bytearray(b'\x03\x0c\r\n'))

        pty.master_reply(action.create_output(1, {'resp': 'OK'}))
        output = comm.do_command(action, fields)
        self.assertEqual('OK', output['resp'])

        self.assertEqual(True, got_output['passed'])
        self.assertEqual(bytearray(b'OL\x00\x01\x03\x0c\r\n'), comm.get_passthrough_data())

    def test_bytes_counter(self):
        action = master_api.basic_action()
        fields = {'action_type': 1, 'action_number': 2}

        pty = DummyPty([action.create_input(1, fields)])
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.enable_passthrough()
        comm.start()

        pty.fd.write(bytearray(b'hello'))
        pty.master_reply(action.create_output(1, {'resp': 'OK'}))
        comm.do_command(action, fields)
        self.assertEqual(bytearray(b'hello'), comm.get_passthrough_data())

        self.assertEqual(21, comm.get_communication_statistics()['bytes_written'])
        self.assertEqual(5 + 18, comm.get_communication_statistics()['bytes_read'])

    def test_crc_checking(self):
        action = master_api.sensor_humidity_list()

        fields1 = {}
        for i in range(0, 32):
            fields1['hum%d' % i] = master_api.Svt(master_api.Svt.RAW, i)
        fields1['crc'] = bytearray([ord('C'), 1, 240])

        fields2 = {}
        for i in range(0, 32):
            fields2['hum%d' % i] = master_api.Svt(master_api.Svt.RAW, 2 * i)
        fields2['crc'] = bytearray([ord('C'), 0, 0])

        pty = DummyPty([action.create_input(1),
                        action.create_input(2)])
        SetUpTestInjections(controller_serial=pty)

        comm = MasterCommunicator(init_master=False)
        comm.start()

        pty.master_reply(action.create_output(1, fields1))
        output = comm.do_command(action)
        self.assertEqual(bytearray(b'\x00'), output['hum0'].get_byte())
        self.assertEqual(bytearray(b'\x01'), output['hum1'].get_byte())

        pty.master_reply(action.create_output(2, fields2))
        with self.assertRaises(CrcCheckFailedException):
            comm.do_command(action)

if __name__ == '__main__':
    unittest.main(testRunner=xmlrunner.XMLTestRunner(output='../gw-unit-reports'))
<|endoftext|>


<commit_before>from __future__ import division, print_function

import math

DYNAMIC_RANGE = 0xFF
WAVE_LENGTH = 0xFF

# The useful circle constant!
TAU = math.pi * 2

class WaveGenerator(object):
    def __init__(self, function):
        """
        Initialise function generator

        :param function: Callable function to generate a waveform.

        """
        self.function = function
        self.dynamic_range = DYNAMIC_RANGE
        self.wave_length = WAVE_LENGTH

    def __iter__(self):
        args = (self.dynamic_range, self.wave_length)
        for x in range(0, self.wave_length + 1):
            yield self.function(x, *args)

def sine_wave_function(x, dynamic, _):
    origin = dynamic >> 1
    return origin + int(math.sin((x / float(dynamic)) * TAU) * origin + 0.5)

def square_wave_function(x, dynamic, length):
    half_wave = length >> 1
    return dynamic if x <= half_wave else 0

def saw_tooth_function(x, dynamic, _):
    origin = dynamic >> 1
    return (origin + x) % dynamic

def reverse_saw_tooth_function(x, dynamic, _):
    origin = dynamic >> 1
    return (origin - x) % dynamic

def triangle_wave_function(x, dynamic, length):
    origin = dynamic >> 1
    half_wave = length >> 1
    quarter_wave = length >> 1
    three_quarter_wave = half_wave + quarter_wave
    if 0 <= x < quarter_wave:
        return origin + x * 2
    elif quarter_wave <= x < three_quarter_wave:
        return dynamic - (x - quarter_wave) * 2
    else:
        return ((x - three_quarter_wave) * 2) - 1

def invert_wave(wave):
    """
    Invert the wave or mirror about the origin.
    """
    return [DYNAMIC_RANGE - x for x in wave]

def mirror_wave(wave):
    """
    Invert the wave about half a wave length
    """
    return list(reversed(wave))

if __name__ == '__main__':
    wave = list(WaveGenerator(saw_tooth_function))
    print(wave)
    from collections import Counter

    wave_counter = Counter(wave)
    print("Summary:", wave_counter)
    print("Most Common:", wave_counter.most_common())
    print("Length:", sum(wave_counter.values()))
<commit_msg>Updated wave functions to be generators and modifiers<commit_after>from __future__ import division, print_function

import math

DYNAMIC_RANGE = 0xFF
WAVE_LENGTH = 256

TAU = math.pi * 2  # The useful circle constant!

def zero_wave():
    """
    A flat line about the origin.
    """
    origin = DYNAMIC_RANGE >> 1
    return [origin for _ in range(WAVE_LENGTH)]

def sine_wave():
    """
    Generate a sine wave.
    """
    origin = DYNAMIC_RANGE >> 1
    f_dynamic = float(DYNAMIC_RANGE)
    return [origin + int(math.sin((x / f_dynamic) * TAU) * origin + 0.5) for x in range(WAVE_LENGTH)]

def square_wave():
    """
    Generate a square wave.
    """
    half_wave = WAVE_LENGTH >> 1
    high = DYNAMIC_RANGE,
    low = 0
    return [high if x < half_wave else low for x in range(WAVE_LENGTH)]

def triangle_wave():
    """
    Generate a triangle wave.
    """
    origin = DYNAMIC_RANGE >> 1
    half_wave = WAVE_LENGTH >> 1
    quarter_wave = half_wave >> 1
    three_quarter_wave = half_wave + quarter_wave

    def wave_func(x):
        if 0 <= x < quarter_wave:
            return origin + x * 2
        elif quarter_wave <= x < three_quarter_wave:
            return DYNAMIC_RANGE - (x - quarter_wave) * 2
        else:
            return ((x - three_quarter_wave) * 2) - 1

    return [wave_func(x) for x in range(WAVE_LENGTH)]

def sawtooth_wave():
    """
    Generate a sawtooth wave.
    """
    origin = DYNAMIC_RANGE >> 1
    return [(origin + x) % DYNAMIC_RANGE for x in range(WAVE_LENGTH)]

def reverse_sawtooth_wave():
    """
    Generate a reverse sawtooth wave.
    """
    origin = DYNAMIC_RANGE >> 1
    return [(origin - x) % DYNAMIC_RANGE for x in range(WAVE_LENGTH)]

def invert_wave(wave):
    """
    Invert the wave or mirror about the origin.
    """
    return [DYNAMIC_RANGE - x for x in wave]

def mirror_wave(wave):
    """
    Invert the wave about half a wave length
    """
    return list(reversed(wave))
<|endoftext|>


<commit_before>import functools
from . import data, importer, whitelist

def load_location(url, base_path=None, module=False):
    """
    Read a single Python file in as code and extract members from it.

    Args:
        url -- a URL either absolute (contains ':') or relative
        base_path -- if url is relative, base_path is prepended to it.

    The resulting URL needs to look something like this:
        https://github.com/foo/bar/blob/master/bibliopixel/myfile.MyClass
    """
    if base_path and ':' not in url:
        slashes = base_path.endswith('/') + url.startswith('/')
        if slashes == 0:
            url = base_path + '/' + url
        elif slashes == 1:
            url = base_path + url
        else:
            url = base_path[:-1] + url

    slash = url.rfind('/')
    url_root, filepath = url[:slash + 1], url[slash + 1:]
    filename, *python_path = filepath.split('.')

    whitelist.check_url(url_root)

    file_url = url_root + filename + '.py'
    source = data.load(file_url, False)
    compiled = compile(source, file_url, mode='exec')
    local = {}
    exec(compiled, local)

    try:
        names = local['__all__']
    except KeyError:
        names = local

    if python_path and python_path[0] == 'py':
        python_path.pop(0)

    if not python_path:
        if module:
            return local
        python_path = [importer.guess_name(names, filename, url)]

    first, *rest = python_path

    try:
        result = local[first]
    except:
        raise AttributeError(first)

    for r in rest:
        result = getattr(result, r)

    return result

@functools.lru_cache()
def load_code(name, base_path=None):
    """Load executable code from a URL or a path"""
    if '/' in name:
        return load_location(name, base_path, module=False)

    return importer.import_code(name, base_path)

@functools.lru_cache()
def load(name, base_path=None):
    """Load a module from a URL or a path"""
    if '/' in name:
        return load_location(name, base_path, module=True)

    return importer.import_symbol(name, base_path)

def cache_clear():
    load.cache_clear()
    data.cache_clear()
<commit_msg>Clarify loady.code methods<commit_after>import functools
from . import data, importer, whitelist

def load_location(url, base_path=None, module=False):
    """
    Read a single Python file in as code and extract members from it.

    Args:
        url -- a URL either absolute (contains ':') or relative
        base_path -- if url is relative, base_path is prepended to it.

    The resulting URL needs to look something like this:
        https://github.com/foo/bar/blob/master/bibliopixel/myfile.MyClass
    """
    if base_path and ':' not in url:
        slashes = base_path.endswith('/') + url.startswith('/')
        if slashes == 0:
            url = base_path + '/' + url
        elif slashes == 1:
            url = base_path + url
        else:
            url = base_path[:-1] + url

    slash = url.rfind('/')
    url_root, filepath = url[:slash + 1], url[slash + 1:]
    filename, *python_path = filepath.split('.')

    whitelist.check_url(url_root)

    file_url = url_root + filename + '.py'
    source = data.load(file_url, False)
    compiled = compile(source, file_url, mode='exec')
    local = {}
    exec(compiled, local)

    try:
        names = local['__all__']
    except KeyError:
        names = local

    if python_path and python_path[0] == 'py':
        python_path.pop(0)

    if not python_path:
        if module:
            return local
        python_path = [importer.guess_name(names, filename, url)]

    first, *rest = python_path

    try:
        result = local[first]
    except:
        raise AttributeError(first)

    for r in rest:
        result = getattr(result, r)

    return result

@functools.lru_cache()
def load_code(name, base_path=None):
    """Load executable code from a URL or a path"""
    if '/' in name:
        return load_location(name, base_path, module=False)

    return importer.import_code(name, base_path)

@functools.lru_cache()
def load(name, base_path=None):
    """Load a module from a URL or a path"""
    if '/' in name:
        return load_location(name, base_path, module=True)

    return importer.import_symbol(name, base_path)

load_module = load

def cache_clear():
    load.cache_clear()
    data.cache_clear()
<|endoftext|>


<commit_before>#!/usr/bin/env python
import numpy as np
from copy import deepcopy
from path import Path

def harmonic(x):
    lam   = 0.5
    omega = 5.0
    return omega*omega*x*x/(4.*lam)

if __name__ == '__main__':

    tau = 0.5
    sig = 0.02
    nslice = 10
    nptcl  = 1
    ndim   = 1
    path = Path( tau,lam=0.5,nslice=nslice,nptcl=nptcl,ndim=ndim)
            #,confs=np.array([ [[-0.2]] , [[0.2]] ]) )
    path.set_ext_potential(harmonic)
    path.set_int_potential()
    old_action = path.action(from_scratch=True)

    cur = 0 # current configuration (~cur points to the proposed configuration)
    mc_pair = [path,deepcopy(path)]

    nsample = 1000 # number of samples to gather
    block_size = 10 # no blocking
    x2 = np.zeros(nsample)
    path_trace = np.zeros([nsample,nslice,nptcl,ndim])
    nmove = 0
    naccept = 0
    for isample in range(nsample):
        # collect statistics
        path_trace[isample] = mc_pair[cur].confs
        x2[isample] = np.linalg.norm(mc_pair[cur].confs,axis=1).mean()
        for istep in range(block_size):
            # single bead moves
            for iconf in range(nslice):
                mc_pair[~cur].move_conf(iconf,sig*np.random.randn(nptcl,ndim))
                nmove += 1
                new_action = mc_pair[~cur].action(from_scratch=False)
                prob = np.exp(-(new_action-old_action))
                if np.random.rand()<prob:
                    naccept += 1
                    cur = ~cur
                    old_action = new_action
                # end if
            # end for iconf
        # end for istep
    # end for isample
    np.savetxt('x2.dat',x2)
    np.savetxt('paths.dat',path_trace)
    print float(naccept)/nmove

# end __main__
<commit_msg>fixed bug<commit_after>#!/usr/bin/env python
import numpy as np
from copy import deepcopy
from path import Path

def harmonic(x,lam,omega):
    return omega*omega*x*x/(4.*lam)

if __name__ == '__main__':

    lam = 0.5
    omega = 20.

    tau = 0.1
    sig = 0.2
    nslice = 10
    nptcl  = 1
    ndim   = 1
    path = Path( tau,lam=lam,nslice=nslice,nptcl=nptcl,ndim=ndim)
    path.set_ext_potential(lambda x:harmonic(x,lam,omega))
    path.set_int_potential()
    old_action = path.action(from_scratch=True)

    nsample = 1000 # number of samples to gather
    block_size = 10 # number of steps in between collecting statistics

    x2 = np.zeros(nsample)
    path_trace = np.zeros([nsample,nslice,nptcl,ndim])
    nmove = 0
    naccept = 0
    for isample in range(nsample):
        # collect statistics
        path_trace[isample] = path.confs
        x2[isample] = (np.linalg.norm(path.confs,axis=1)**2.).mean()
        for istep in range(block_size):
            # single bead moves
            for iconf in range(nslice):
                move = sig*np.random.randn(nptcl,ndim)
                path.move_conf(iconf,move)
                nmove += 1
                new_action = path.action(from_scratch=False)
                prob = np.exp(-(new_action-old_action))
                if np.random.rand()<prob:
                    naccept += 1
                    old_action = new_action
                else:
                    path.move_conf(iconf,-move)
                # end if
            # end for iconf
        # end for istep
    # end for isample
    np.savetxt('x2.dat',x2)
    np.savetxt('pos.dat',path_trace)
    print float(naccept)/nmove

# end __main__
<|endoftext|>


<commit_before>import time
from twisted.internet.task import LoopingCall
from carbon.conf import settings
from carbon import log

class BufferManager:
  def __init__(self):
    self.buffers = {}

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

  def get_buffer(self, metric_path):
    if metric_path not in self.buffers:
      log.aggregator("Allocating new metric buffer for %s" % metric_path)
      self.buffers[metric_path] = MetricBuffer(metric_path)

    return self.buffers[metric_path]

  def clear(self):
    for buffer in self.buffers.values():
      buffer.close()

    self.buffers.clear()

class MetricBuffer:
  __slots__ = ('metric_path', 'interval_buffers', 'compute_task', 'configured',
               'aggregation_frequency', 'aggregation_func')

  def __init__(self, metric_path):
    self.metric_path = metric_path
    self.interval_buffers = {}
    self.compute_task = None
    self.configured = False
    self.aggregation_frequency = None
    self.aggregation_func = None

  def input(self, datapoint):
    (timestamp, value) = datapoint
    interval = timestamp - (timestamp % self.aggregation_frequency)
    if interval in self.interval_buffers:
      buffer = self.interval_buffers[interval]
    else:
      buffer = self.interval_buffers[interval] = IntervalBuffer(interval)

    buffer.input(datapoint)

  def configure_aggregation(self, frequency, func):
    self.aggregation_frequency = int(frequency)
    self.aggregation_func = func
    self.compute_task = LoopingCall(self.compute_value)
    self.compute_task.start(frequency, now=False)
    self.configured = True

  def compute_value(self):
    now = int( time.time() )
    current_interval = now - (now % self.aggregation_frequency)
    age_threshold = current_interval - (settings['MAX_AGGREGATION_INTERVALS'] * self.aggregation_frequency)

    for buffer in self.interval_buffers.values():
      if buffer.active:
        value = self.aggregation_func(buffer.values)
        datapoint = (buffer.interval, value)
        state.events.metricGenerated(self.metric_path, datapoint)
        state.instrumnetation.increment('aggregateDatapointsSent')
        buffer.mark_inactive()

      if buffer.interval < age_threshold:
        del self.interval_buffers[buffer.interval]

  def close(self):
    if self.compute_task and self.compute_task.running:
      self.compute_task.stop()

  @property
  def size(self):
    return sum([len(buf.values) for buf in self.interval_buffers.values()])

class IntervalBuffer:
  __slots__ = ('interval', 'values', 'active')

  def __init__(self, interval):
    self.interval = interval
    self.values = []
    self.active = True

  def input(self, datapoint):
    self.values.append( datapoint[1] )
    self.active = True

  def mark_inactive(self):
    self.active = False

# Shared importable singleton
BufferManager = BufferManager()

# Avoid import circularity
from carbon import state
<commit_msg>fixed typo<commit_after>import time
from twisted.internet.task import LoopingCall
from carbon.conf import settings
from carbon import log

class BufferManager:
  def __init__(self):
    self.buffers = {}

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

  def get_buffer(self, metric_path):
    if metric_path not in self.buffers:
      log.aggregator("Allocating new metric buffer for %s" % metric_path)
      self.buffers[metric_path] = MetricBuffer(metric_path)

    return self.buffers[metric_path]

  def clear(self):
    for buffer in self.buffers.values():
      buffer.close()

    self.buffers.clear()

class MetricBuffer:
  __slots__ = ('metric_path', 'interval_buffers', 'compute_task', 'configured',
               'aggregation_frequency', 'aggregation_func')

  def __init__(self, metric_path):
    self.metric_path = metric_path
    self.interval_buffers = {}
    self.compute_task = None
    self.configured = False
    self.aggregation_frequency = None
    self.aggregation_func = None

  def input(self, datapoint):
    (timestamp, value) = datapoint
    interval = timestamp - (timestamp % self.aggregation_frequency)
    if interval in self.interval_buffers:
      buffer = self.interval_buffers[interval]
    else:
      buffer = self.interval_buffers[interval] = IntervalBuffer(interval)

    buffer.input(datapoint)

  def configure_aggregation(self, frequency, func):
    self.aggregation_frequency = int(frequency)
    self.aggregation_func = func
    self.compute_task = LoopingCall(self.compute_value)
    self.compute_task.start(frequency, now=False)
    self.configured = True

  def compute_value(self):
    now = int( time.time() )
    current_interval = now - (now % self.aggregation_frequency)
    age_threshold = current_interval - (settings['MAX_AGGREGATION_INTERVALS'] * self.aggregation_frequency)

    for buffer in self.interval_buffers.values():
      if buffer.active:
        value = self.aggregation_func(buffer.values)
        datapoint = (buffer.interval, value)
        state.events.metricGenerated(self.metric_path, datapoint)
        state.instrumentation.increment('aggregateDatapointsSent')
        buffer.mark_inactive()

      if buffer.interval < age_threshold:
        del self.interval_buffers[buffer.interval]

  def close(self):
    if self.compute_task and self.compute_task.running:
      self.compute_task.stop()

  @property
  def size(self):
    return sum([len(buf.values) for buf in self.interval_buffers.values()])

class IntervalBuffer:
  __slots__ = ('interval', 'values', 'active')

  def __init__(self, interval):
    self.interval = interval
    self.values = []
    self.active = True

  def input(self, datapoint):
    self.values.append( datapoint[1] )
    self.active = True

  def mark_inactive(self):
    self.active = False

# Shared importable singleton
BufferManager = BufferManager()

# Avoid import circularity
from carbon import state
<|endoftext|>


<commit_before># Copyright 2013-2019 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

import os
from spack import *

class Npm(AutotoolsPackage):
    """npm: A package manager for javascript."""

    homepage = "https://github.com/npm/npm"
    # base http://www.npmjs.com/
    url      = "https://registry.npmjs.org/npm/-/npm-3.10.5.tgz"

    version('3.10.9', sha256='fb0871b1aebf4b74717a72289fade356aedca83ee54e7386e38cb51874501dd6')
    version('3.10.5', sha256='ff019769e186152098841c1fa6325e5a79f7903a45f13bd0046a4dc8e63f845f')

    depends_on('node-js', type=('build', 'run'))

    def setup_dependent_build_environment(self, env, dependent_spec):
        npm_config_cache_dir = "%s/npm-cache" % dependent_spec.prefix
        if not os.path.isdir(npm_config_cache_dir):
            mkdir(npm_config_cache_dir)
        env.set('npm_config_cache', npm_config_cache_dir)

    def setup_dependent_run_environment(self, env, dependent_spec):
        npm_config_cache_dir = "%s/npm-cache" % dependent_spec.prefix
        if not os.path.isdir(npm_config_cache_dir):
            mkdir(npm_config_cache_dir)
        env.set('npm_config_cache', npm_config_cache_dir)
<commit_msg>npm: add Python 3 support (#14255)<commit_after># Copyright 2013-2019 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

import os
import shutil
from spack import *

# NOTE: not actually an Autotools package
class Npm(Package):
    """npm: A package manager for javascript."""

    homepage = "https://github.com/npm/npm"
    # base http://www.npmjs.com/
    url      = "https://registry.npmjs.org/npm/-/npm-6.13.4.tgz"

    version('6.13.4', sha256='a063290bd5fa06a8753de14169b7b243750432f42d01213fbd699e6b85916de7')
    version('3.10.9', sha256='fb0871b1aebf4b74717a72289fade356aedca83ee54e7386e38cb51874501dd6')
    version('3.10.5', sha256='ff019769e186152098841c1fa6325e5a79f7903a45f13bd0046a4dc8e63f845f')

    depends_on('node-js', type=('build', 'run'))

    # npm 6.13.4 ships with node-gyp 5.0.5, which contains several Python 3
    # compatibility issues on macOS. Manually update to node-gyp 6.0.1 for
    # full Python 3 support.
    resource(name='node-gyp', destination='node-gyp',
             url='https://registry.npmjs.org/node-gyp/-/node-gyp-6.0.1.tgz',
             sha256='bbc0e137e17a63676efc97a0e3b1fcf101498a1c2c01c3341cd9491f248711b8')
    resource(name='env-paths', destination='env-paths',
             url='https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz',
             sha256='168b394fbca60ea81dc84b1824466df96246b9eb4d671c2541f55f408a264b4c')

    phases = ['configure', 'build', 'install']

    def patch(self):
        shutil.rmtree('node_modules/node-gyp')
        install_tree('node-gyp/package', 'node_modules/node-gyp')
        filter_file('"node-gyp": "^5.0.5"', '"node-gyp": "^6.0.1"',
                    'package.json', string=True)
        install_tree('env-paths/package', 'node_modules/env-paths')

    def configure(self, spec, prefix):
        configure('--prefix={0}'.format(prefix))

    def build(self, spec, prefix):
        make()

    def install(self, spec, prefix):
        make('install')

    def setup_dependent_build_environment(self, env, dependent_spec):
        npm_config_cache_dir = "%s/npm-cache" % dependent_spec.prefix
        if not os.path.isdir(npm_config_cache_dir):
            mkdir(npm_config_cache_dir)
        env.set('npm_config_cache', npm_config_cache_dir)

    def setup_dependent_run_environment(self, env, dependent_spec):
        npm_config_cache_dir = "%s/npm-cache" % dependent_spec.prefix
        if not os.path.isdir(npm_config_cache_dir):
            mkdir(npm_config_cache_dir)
        env.set('npm_config_cache', npm_config_cache_dir)
<|endoftext|>


<commit_before>from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.core.urlresolvers import reverse
from django.shortcuts import get_object_or_404
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.conf import settings

from working_waterfronts.working_waterfronts_api.models import Image
from working_waterfronts.working_waterfronts_api.forms import ImageForm
from working_waterfronts.working_waterfronts_api.functions import group_required

@login_required
@group_required('Administration Users', 'Data Entry Users')
def image_list(request):
    """
    */entry/images*

    The entry interface's images list. This view lists all images,
    their description, and allows you to click on them to view/edit the
    image.
    """

    message = ""
    if request.GET.get('success') == 'true':
        message = "Image deleted successfully!"
    elif request.GET.get('saved') == 'true':
        message = "Image saved successfully!"

    paginator = Paginator(Image.objects.order_by('name'), settings.PAGE_LENGTH)
    page = request.GET.get('page')

    try:
        images = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        images = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        images = paginator.page(paginator.num_pages)

    return render(request, 'list.html', {
        'message': message,
        'parent_url': reverse('home'),
        'parent_text': 'Home',
        'new_url': reverse('new-image'),
        'new_text': "New image",
        'title': "All images",
        'item_classification': "image",
        'item_list': images,
        'edit_url': 'edit-image'
    })

@login_required
@group_required('Administration Users', 'Data Entry Users')
def image(request, id=None):
    """
    */entry/images/<id>*, */entry/images/new*

    The entry interface's edit/add/delete image view. This view creates
    the edit page for a given image, or the "new image" page if it
    is not passed an ID. It also accepts POST requests to create or edit
    images.

    If called with DELETE, it will return a 200 upon success or a 404 upon
    failure. This is to be used as part of an AJAX call, or some other API
    call.
    """
    if request.method == 'DELETE':
        image = get_object_or_404(Image, pk=id)
        image.delete()
        return HttpResponse()

    if request.method == 'POST':
        message = ''

        if id:
            instance = get_object_or_404(Image, pk=id)
        else:
            instance = None
        image_form = ImageForm(
            request.POST,
            request.FILES,
            instance=instance)
        if image_form.is_valid():
            image_form.save()
            return HttpResponseRedirect(
                "%s?saved=true" % reverse('entry-list-images'))
        else:
            pass
    else:
        message = ''

    if id:
        image = Image.objects.get(id=id)
        title = "Edit {0}".format(image.name)
        post_url = reverse('edit-image', kwargs={'id': id})
        image_form = ImageForm(instance=image)

        if request.GET.get('success') == 'true':
            message = "Image saved successfully!"

    elif request.method != 'POST':
        image_form = ImageForm()
        post_url = reverse('new-image')
        title = "New Image"

    else:
        post_url = reverse('new-image')
        title = "New Image"

    return render(request, 'image.html', {
        'parent_url': [
            {'url': reverse('home'), 'name': 'Home'},
            {'url': reverse('entry-list-images'), 'name': 'Images'}
        ],
        'title': title,
        'message': message,
        'post_url': post_url,
        'errors': [],
        'image_form': image_form,
    })
<commit_msg>Remove login-required decorators<commit_after>from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.core.urlresolvers import reverse
from django.shortcuts import get_object_or_404
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.conf import settings

from working_waterfronts.working_waterfronts_api.models import Image
from working_waterfronts.working_waterfronts_api.forms import ImageForm
from working_waterfronts.working_waterfronts_api.functions import group_required

def image_list(request):
    """
    */entry/images*

    The entry interface's images list. This view lists all images,
    their description, and allows you to click on them to view/edit the
    image.
    """

    message = ""
    if request.GET.get('success') == 'true':
        message = "Image deleted successfully!"
    elif request.GET.get('saved') == 'true':
        message = "Image saved successfully!"

    paginator = Paginator(Image.objects.order_by('name'), settings.PAGE_LENGTH)
    page = request.GET.get('page')

    try:
        images = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        images = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        images = paginator.page(paginator.num_pages)

    return render(request, 'list.html', {
        'message': message,
        'parent_url': reverse('home'),
        'parent_text': 'Home',
        'new_url': reverse('new-image'),
        'new_text': "New image",
        'title': "All images",
        'item_classification': "image",
        'item_list': images,
        'edit_url': 'edit-image'
    })

def image(request, id=None):
    """
    */entry/images/<id>*, */entry/images/new*

    The entry interface's edit/add/delete image view. This view creates
    the edit page for a given image, or the "new image" page if it
    is not passed an ID. It also accepts POST requests to create or edit
    images.

    If called with DELETE, it will return a 200 upon success or a 404 upon
    failure. This is to be used as part of an AJAX call, or some other API
    call.
    """
    if request.method == 'DELETE':
        image = get_object_or_404(Image, pk=id)
        image.delete()
        return HttpResponse()

    if request.method == 'POST':
        message = ''

        if id:
            instance = get_object_or_404(Image, pk=id)
        else:
            instance = None
        image_form = ImageForm(
            request.POST,
            request.FILES,
            instance=instance)
        if image_form.is_valid():
            image_form.save()
            return HttpResponseRedirect(
                "%s?saved=true" % reverse('entry-list-images'))
        else:
            pass
    else:
        message = ''

    if id:
        image = Image.objects.get(id=id)
        title = "Edit {0}".format(image.name)
        post_url = reverse('edit-image', kwargs={'id': id})
        image_form = ImageForm(instance=image)

        if request.GET.get('success') == 'true':
            message = "Image saved successfully!"

    elif request.method != 'POST':
        image_form = ImageForm()
        post_url = reverse('new-image')
        title = "New Image"

    else:
        post_url = reverse('new-image')
        title = "New Image"

    return render(request, 'image.html', {
        'parent_url': [
            {'url': reverse('home'), 'name': 'Home'},
            {'url': reverse('entry-list-images'), 'name': 'Images'}
        ],
        'title': title,
        'message': message,
        'post_url': post_url,
        'errors': [],
        'image_form': image_form,
    })
<|endoftext|>