<commit_before>""" Defines default methods for unary and binary operations.
"""

from basic import Basic, cache_it

def _no_unary_operation(op, obj):
    return 'unary operation `%s` not defined for %s' % (op, obj.__class__.__name__)
def _no_binary_operation(op, obj1, obj2):
    return 'binary operation `%s` not defined between %s and %s' \
           % (op, obj1.__class__.__name__, obj2.__class__.__name__)

class ArithMeths(object):

    def __pos__(self):
        return self
    def __neg__(self):
        return Basic.Integer(-1) * self
    def __abs__(self):
        return Basic.Abs()(self)
    def __add__(self, other):
        return Basic.Add(self, other)
    def __radd__(self, other):
        return Basic.sympify(other) + self
    def __sub__(self, other):
        return self + (-Basic.sympify(other))
    def __rsub__(self, other):
        return Basic.sympify(other) - self
    def __mul__(self, other):
        return Basic.Mul(self, other)
    def __rmul__(self, other):
        return Basic.sympify(other) * self
    def __pow__(self, other):
        return Basic.Pow(self, other)
    def __rpow__(self, other):
        return Basic.sympify(other) ** self
    def __div__(self, other):
        return self * (Basic.sympify(other) ** Basic.Integer(-1))
    def __rdiv__(self, other):
        return Basic.sympify(other) / self
    def _eval_power(self, other):
        """ Evaluate Pow(self, other), return new object or None if
        no evaluation can be carried out. This method can be called
        only from Pow.__new__.
        """
        return None

class NoArithMeths(object):

    def __pos__(self):
        raise TypeError, _no_unary_operation('+', self)
    def __neg__(self):
        raise TypeError, _no_unary_operation('-', self)
    def __add__(self, other):
        raise TypeError, _no_binary_operation('+', self, other)
    def __radd__(self, other):
        raise TypeError, _no_binary_operation('+', other, self)
    def __sub__(self, other):
        raise TypeError, _no_binary_operation('-', self, other)
    def __rsub__(self, other):
        raise TypeError, _no_binary_operation('-', other, self)
    def __mul__(self, other):
        raise TypeError, _no_binary_operation('*', self, other)
    def __rmul__(self, other):
        raise TypeError, _no_binary_operation('*', other, self)
    def __div__(self, other):
        raise TypeError, _no_binary_operation('/', self, other)
    def __rdiv__(self, other):
        raise TypeError, _no_binary_operation('/', other, self)
    def __pow__(self, other):
        raise TypeError, _no_binary_operation('**', self, other)
    def __rpow__(self, other):
        raise TypeError, _no_binary_operation('**', other, self)
    def _eval_power(self, other):
        return None

class RelMeths(object):

    def __eq__(self, other):
        return Basic.Equality(self, other)
    def __ne__(self, other):
        return Basic.Unequality(self, other)
    def __lt__(self, other):
        return Basic.StrictInequality(self, other)
    def __gt__(self, other):
        return Basic.sympify(other) < self
    def __le__(self, other):
        return Basic.Inequality(self, other)
    def __ge__(self, other):
        return Basic.sympify(other) <= self

class NoRelMeths(object):

    def __eq__(self, other):
        return Basic.Equality(self, other)
    def __ne__(self, other):
        return Basic.Unequality(self, other)
    def __lt__(self, other):
        raise TypeError, _no_binary_operation('<', self, other)
    def __gt__(self, other):
        raise TypeError, _no_binary_operation('>', self, other)
    def __le__(self, other):
        raise TypeError, _no_binary_operation('<=', self, other)
    def __ge__(self, other):
        raise TypeError, _no_binary_operation('>=', self, other)
<commit_msg>workaround comparing objects when creating Equality fails<commit_after>""" Defines default methods for unary and binary operations.
"""

from basic import Basic, cache_it

def _no_unary_operation(op, obj):
    return 'unary operation `%s` not defined for %s' % (op, obj.__class__.__name__)
def _no_binary_operation(op, obj1, obj2):
    return 'binary operation `%s` not defined between %s and %s' \
           % (op, obj1.__class__.__name__, obj2.__class__.__name__)

class ArithMeths(object):

    def __pos__(self):
        return self
    def __neg__(self):
        return Basic.Integer(-1) * self
    def __abs__(self):
        return Basic.Abs()(self)
    def __add__(self, other):
        return Basic.Add(self, other)
    def __radd__(self, other):
        return Basic.sympify(other) + self
    def __sub__(self, other):
        return self + (-Basic.sympify(other))
    def __rsub__(self, other):
        return Basic.sympify(other) - self
    def __mul__(self, other):
        return Basic.Mul(self, other)
    def __rmul__(self, other):
        return Basic.sympify(other) * self
    def __pow__(self, other):
        return Basic.Pow(self, other)
    def __rpow__(self, other):
        return Basic.sympify(other) ** self
    def __div__(self, other):
        return self * (Basic.sympify(other) ** Basic.Integer(-1))
    def __rdiv__(self, other):
        return Basic.sympify(other) / self
    def _eval_power(self, other):
        """ Evaluate Pow(self, other), return new object or None if
        no evaluation can be carried out. This method can be called
        only from Pow.__new__.
        """
        return None

class NoArithMeths(object):

    def __pos__(self):
        raise TypeError, _no_unary_operation('+', self)
    def __neg__(self):
        raise TypeError, _no_unary_operation('-', self)
    def __add__(self, other):
        raise TypeError, _no_binary_operation('+', self, other)
    def __radd__(self, other):
        raise TypeError, _no_binary_operation('+', other, self)
    def __sub__(self, other):
        raise TypeError, _no_binary_operation('-', self, other)
    def __rsub__(self, other):
        raise TypeError, _no_binary_operation('-', other, self)
    def __mul__(self, other):
        raise TypeError, _no_binary_operation('*', self, other)
    def __rmul__(self, other):
        raise TypeError, _no_binary_operation('*', other, self)
    def __div__(self, other):
        raise TypeError, _no_binary_operation('/', self, other)
    def __rdiv__(self, other):
        raise TypeError, _no_binary_operation('/', other, self)
    def __pow__(self, other):
        raise TypeError, _no_binary_operation('**', self, other)
    def __rpow__(self, other):
        raise TypeError, _no_binary_operation('**', other, self)
    def _eval_power(self, other):
        return None

class RelMeths(object):

    def __eq__(self, other):
        try:
            r = Basic.Equality(self, other)
        except ValueError, msg:
            # temporary workaround:
            print 'Failed to create Equality instance: %s, using repr equality test instead' % msg
            r = repr(self)==repr(other)
        return r
    def __ne__(self, other):
        return Basic.Unequality(self, other)
    def __lt__(self, other):
        return Basic.StrictInequality(self, other)
    def __gt__(self, other):
        return Basic.sympify(other) < self
    def __le__(self, other):
        return Basic.Inequality(self, other)
    def __ge__(self, other):
        return Basic.sympify(other) <= self

class NoRelMeths(object):

    def __eq__(self, other):
        return Basic.Equality(self, other)
    def __ne__(self, other):
        return Basic.Unequality(self, other)
    def __lt__(self, other):
        raise TypeError, _no_binary_operation('<', self, other)
    def __gt__(self, other):
        raise TypeError, _no_binary_operation('>', self, other)
    def __le__(self, other):
        raise TypeError, _no_binary_operation('<=', self, other)
    def __ge__(self, other):
        raise TypeError, _no_binary_operation('>=', self, other)
<|endoftext|>


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

import codecs
import re
import difflib
import sys
import os

import duralex.alinea_parser as parser
import diff

from duralex.AbstractVisitor import AbstractVisitor

import duralex.tree as tree

class AddDiffVisitor(AbstractVisitor):
    letters = re.compile(r'^[a-zA-Z0-9]+$')
    REGEXP = {
        tree.TYPE_HEADER1_REFERENCE     : re.compile(r'([IVXCLDM]+\. - (?:(?:.|\n)(?![IVXCLDM]+\. - ))*)', re.UNICODE),
        tree.TYPE_HEADER2_REFERENCE     : re.compile(r'(\d+\. (?:(?:.|\n)(?!\d+\. ))*)', re.UNICODE),
        tree.TYPE_HEADER3_REFERENCE     : re.compile(r'([a-z]+\) (?:(?:.|\n)(?![a-z]+\) ))*)', re.UNICODE),
        tree.TYPE_ALINEA_REFERENCE      : re.compile(r'^(.+)$', re.UNICODE | re.MULTILINE),
        tree.TYPE_SENTENCE_REFERENCE    : re.compile(r'([A-ZÀÀÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ].*?\.)', re.UNICODE),
        tree.TYPE_WORD_REFERENCE        : re.compile(r'(\b\w.*?\b)', re.UNICODE)
    }

    def __init__(self):
        self.filename = ''
        self.content = {}
        self.begin = 0
        self.end = -1
        super(AddDiffVisitor, self).__init__()

    def visit_alinea_reference_node(self, node, post):
        if post:
            return

        match = re.finditer(AddDiffVisitor.REGEXP[tree.TYPE_ALINEA_REFERENCE], self.content[self.filename][self.begin:self.end])
        match = list(match)[node['order'] - 1 if node['order'] > 0 else node['order']]
        self.begin += match.start()
        self.end = self.begin + len(match.group(1))

    def visit_sentence_reference_node(self, node, post):
        if post:
            return

        match = re.finditer(AddDiffVisitor.REGEXP[tree.TYPE_SENTENCE_REFERENCE], self.content[self.filename][self.begin:self.end])
        match = list(match)[node['order'] - 1 if node['order'] > 0 else node['order']]
        self.begin += match.start()
        self.end = self.begin + len(match.group(1))

    def visit_header1_reference_node(self, node, post):
        if post:
            return

        match = re.finditer(AddDiffVisitor.REGEXP[tree.TYPE_HEADER1_REFERENCE], self.content[self.filename][self.begin:self.end])
        match = list(match)[node['order'] - 1 if node['order'] > 0 else node['order']]
        self.begin += match.start()
        self.end = self.begin + len(match.group(1))

    def visit_header2_reference_node(self, node, post):
        if post:
            return

        match = re.finditer(AddDiffVisitor.REGEXP[tree.TYPE_HEADER2_REFERENCE], self.content[self.filename][self.begin:self.end])
        match = list(match)[node['order'] - 1 if node['order'] > 0 else node['order']]
        self.begin += match.start()
        self.end = self.begin + len(match.group(1))

    def visit_header3_reference_node(self, node, post):
        if post:
            return

        match = re.finditer(AddDiffVisitor.REGEXP[tree.TYPE_HEADER3_REFERENCE], self.content[self.filename][self.begin:self.end])
        match = list(match)[node['order'] - 1 if node['order'] > 0 else node['order']]
        self.begin += match.start()
        self.end = self.begin + len(match.group(1))

    def visit_words_reference_node(self, node, post):
        if post:
            return

        if 'children' in node and node['children'][0]['type'] == 'quote':
            if 'position' in node and node['position'] == 'after':
                self.begin += (self.content[self.filename][self.begin:self.end].find(node['children'][0]['words'])
                    + len(node['children'][0]['words']))
            else:
                self.begin += self.content[self.filename][self.begin:self.end].find(node['children'][0]['words'])
                self.end = self.begin + len(node['children'][0]['words'])

    def visit_article_reference_node(self, node, post):
        if post:
            return
        self.set_content_from_file(node['filename'])

    def visit_bill_article_reference_node(self, node, post):
        bill_article = tree.filter_nodes(
            tree.get_root(node),
            lambda n: n['type'] == tree.TYPE_BILL_ARTICLE and n['order'] == node['order']
        )
        if len(bill_article) == 1:
            self.set_content(bill_article[0]['order'], bill_article[0]['content'])

    def visit_article_definition_node(self, node, post):
        if post:
            return
        self.set_content_from_file(node['filename'])

    def set_content_from_file(self, filename):
        self.filename = filename
        if self.filename not in self.content:
            if os.path.isfile(self.filename):
                input_file = codecs.open(self.filename, mode="r", encoding="utf-8")
                self.set_content(self.filename, input_file.read())
            else:
                self.set_content(self.filename, '')

    def set_content(self, key, content):
        self.content[key] = content
        self.begin = 0
        self.end = len(content)

    def visit_edit_node(self, node, post):
        if not post:
            self.begin = 0
            self.end = -1
            return

        old_content = self.content[self.filename]
        new_content = old_content

        try:
            if node['editType'] == 'replace':
                # replace words
                def_node = parser.filter_nodes(node, lambda x: tree.is_definition(x))[-1]
                if def_node['type'] == tree.TYPE_WORD_DEFINITION:
                    new_words = def_node['children'][0]['words']
                    if self.begin > 0 and old_content[self.begin-1] == ' ' and not re.match(self.letters, new_words[0]):
                        self.begin -= 1
                    new_content = old_content[0:self.begin] + \
                                  new_words + \
                                  (' ' if re.match(self.letters, new_words[-1]+old_content[self.end]) else '') + \
                                  old_content[self.end:]
            elif node['editType'] == 'delete':
                if self.begin > 1 and old_content[self.begin-2:self.begin] == '\n\n':
                    self.begin -= 2
                elif self.end+2 < len(old_content) and old_content[self.end:self.end+2] == '\n\n':
                    self.end += 2
                new_content = old_content[0:self.begin] + old_content[self.end:]
            elif node['editType'] == 'edit':
                def_node = parser.filter_nodes(node, lambda x: tree.is_definition(x))[-1]
                # edit words
                if def_node['type'] == tree.TYPE_WORD_DEFINITION:
                    new_content = old_content[0:self.begin] + def_node['children'][0]['words'] + old_content[self.end:]
            elif node['editType'] == 'add':
                # add a word
                if node['children'][1]['type'] == tree.TYPE_WORD_DEFINITION:
                    def_node = parser.filter_nodes(node, lambda x: x['type'] == tree.TYPE_QUOTE)[-1]
                    new_words = def_node['words']
                    new_content = old_content[0:self.begin] + \
                                  ('' if new_words[0] == ',' else ' ') + \
                                  new_words + \
                                  ('' if old_content[self.begin] == ' ' else ' ') + \
                                  old_content[self.begin:]
                # add an alinea
                if node['children'][1]['type'] == tree.TYPE_ALINEA_DEFINITION:
                    def_node = parser.filter_nodes(node, lambda x: x['type'] == tree.TYPE_QUOTE)[-1]
                    new_content += '\n' + '\n'.join([
                        n['words'] for n in parser.filter_nodes(node, lambda x: x['type'] == tree.TYPE_QUOTE)
                    ])
                # add an article
                elif node['children'][1]['type'] == tree.TYPE_ARTICLE_DEFINITION:
                    def_node = parser.filter_nodes(node, lambda x: x['type'] == tree.TYPE_QUOTE)[-1]
                    new_content = '\n'.join([
                        n['words'] for n in parser.filter_nodes(node, lambda x: x['type'] == tree.TYPE_QUOTE)
                    ])

            unified_diff = difflib.unified_diff(
                old_content.splitlines() if old_content != '' else [],
                new_content.splitlines() if new_content != '' else [],
                tofile='\"' + self.filename + '\"',
                fromfile='\"' + self.filename + '\"'
            )
            unified_diff = list(unified_diff)
            if len(unified_diff) > 0:
                node['diff'] = ('\n'.join(unified_diff)).replace('\n\n', '\n') # investigate why double newlines
                #node['htmlDiff'] = diff.make_html_rich_diff(old_content, new_content, self.filename)

            if node['parent']['type'] != tree.TYPE_AMENDMENT or node['parent']['status'] == 'approved':
                self.set_content(self.filename, new_content)
        except Exception as e:
            # FIXME: proper error message
            raise e
<commit_msg>Fix d3b9196: do not remove too much lines<commit_after># -*- coding: utf-8 -*-

import codecs
import re
import difflib
import sys
import os

import duralex.alinea_parser as parser
import diff

from duralex.AbstractVisitor import AbstractVisitor

import duralex.tree as tree

class AddDiffVisitor(AbstractVisitor):
    letters = re.compile(r'^[a-zA-Z0-9]+$')
    REGEXP = {
        tree.TYPE_HEADER1_REFERENCE     : re.compile(r'([IVXCLDM]+\. - (?:(?:.|\n)(?![IVXCLDM]+\. - ))*)', re.UNICODE),
        tree.TYPE_HEADER2_REFERENCE     : re.compile(r'(\d+\. (?:(?:.|\n)(?!\d+\. ))*)', re.UNICODE),
        tree.TYPE_HEADER3_REFERENCE     : re.compile(r'([a-z]+\) (?:(?:.|\n)(?![a-z]+\) ))*)', re.UNICODE),
        tree.TYPE_ALINEA_REFERENCE      : re.compile(r'^(.+)$', re.UNICODE | re.MULTILINE),
        tree.TYPE_SENTENCE_REFERENCE    : re.compile(r'([A-ZÀÀÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ].*?\.)', re.UNICODE),
        tree.TYPE_WORD_REFERENCE        : re.compile(r'(\b\w.*?\b)', re.UNICODE)
    }

    def __init__(self):
        self.filename = ''
        self.content = {}
        self.begin = 0
        self.end = -1
        super(AddDiffVisitor, self).__init__()

    def visit_alinea_reference_node(self, node, post):
        if post:
            return

        match = re.finditer(AddDiffVisitor.REGEXP[tree.TYPE_ALINEA_REFERENCE], self.content[self.filename][self.begin:self.end])
        match = list(match)[node['order'] - 1 if node['order'] > 0 else node['order']]
        self.begin += match.start()
        self.end = self.begin + len(match.group(1))

    def visit_sentence_reference_node(self, node, post):
        if post:
            return

        match = re.finditer(AddDiffVisitor.REGEXP[tree.TYPE_SENTENCE_REFERENCE], self.content[self.filename][self.begin:self.end])
        match = list(match)[node['order'] - 1 if node['order'] > 0 else node['order']]
        self.begin += match.start()
        self.end = self.begin + len(match.group(1))

    def visit_header1_reference_node(self, node, post):
        if post:
            return

        match = re.finditer(AddDiffVisitor.REGEXP[tree.TYPE_HEADER1_REFERENCE], self.content[self.filename][self.begin:self.end])
        match = list(match)[node['order'] - 1 if node['order'] > 0 else node['order']]
        self.begin += match.start()
        self.end = self.begin + len(match.group(1))

    def visit_header2_reference_node(self, node, post):
        if post:
            return

        match = re.finditer(AddDiffVisitor.REGEXP[tree.TYPE_HEADER2_REFERENCE], self.content[self.filename][self.begin:self.end])
        match = list(match)[node['order'] - 1 if node['order'] > 0 else node['order']]
        self.begin += match.start()
        self.end = self.begin + len(match.group(1))

    def visit_header3_reference_node(self, node, post):
        if post:
            return

        match = re.finditer(AddDiffVisitor.REGEXP[tree.TYPE_HEADER3_REFERENCE], self.content[self.filename][self.begin:self.end])
        match = list(match)[node['order'] - 1 if node['order'] > 0 else node['order']]
        self.begin += match.start()
        self.end = self.begin + len(match.group(1))

    def visit_words_reference_node(self, node, post):
        if post:
            return

        if 'children' in node and node['children'][0]['type'] == 'quote':
            if 'position' in node and node['position'] == 'after':
                self.begin += (self.content[self.filename][self.begin:self.end].find(node['children'][0]['words'])
                    + len(node['children'][0]['words']))
            else:
                self.begin += self.content[self.filename][self.begin:self.end].find(node['children'][0]['words'])
                self.end = self.begin + len(node['children'][0]['words'])

    def visit_article_reference_node(self, node, post):
        if post:
            return
        self.set_content_from_file(node['filename'])

    def visit_bill_article_reference_node(self, node, post):
        bill_article = tree.filter_nodes(
            tree.get_root(node),
            lambda n: n['type'] == tree.TYPE_BILL_ARTICLE and n['order'] == node['order']
        )
        if len(bill_article) == 1:
            self.set_content(bill_article[0]['order'], bill_article[0]['content'])

    def visit_article_definition_node(self, node, post):
        if post:
            return
        self.set_content_from_file(node['filename'])

    def set_content_from_file(self, filename):
        self.filename = filename
        if self.filename not in self.content:
            if os.path.isfile(self.filename):
                input_file = codecs.open(self.filename, mode="r", encoding="utf-8")
                self.set_content(self.filename, input_file.read())
            else:
                self.set_content(self.filename, '')

    def set_content(self, key, content):
        self.content[key] = content
        self.begin = 0
        self.end = len(content)

    def visit_edit_node(self, node, post):
        if not post:
            self.begin = 0
            self.end = -1
            return

        old_content = self.content[self.filename]
        new_content = old_content

        try:
            if node['editType'] == 'replace':
                # replace words
                def_node = parser.filter_nodes(node, lambda x: tree.is_definition(x))[-1]
                if def_node['type'] == tree.TYPE_WORD_DEFINITION:
                    new_words = def_node['children'][0]['words']
                    if self.begin > 0 and old_content[self.begin-1] == ' ' and not re.match(self.letters, new_words[0]):
                        self.begin -= 1
                    new_content = old_content[0:self.begin] + \
                                  new_words + \
                                  (' ' if re.match(self.letters, new_words[-1]+old_content[self.end]) else '') + \
                                  old_content[self.end:]
            elif node['editType'] == 'delete':
                if old_content[self.begin-2:self.begin] == '\n\n' and (old_content[self.end:self.end+2] == '\n\n' or self.end == len(old_content)-1):
                    self.begin -= 2
                elif self.begin == 0 and old_content[self.end:self.end+2] == '\n\n':
                    self.end += 2
                new_content = old_content[0:self.begin] + old_content[self.end:]
            elif node['editType'] == 'edit':
                def_node = parser.filter_nodes(node, lambda x: tree.is_definition(x))[-1]
                # edit words
                if def_node['type'] == tree.TYPE_WORD_DEFINITION:
                    new_content = old_content[0:self.begin] + def_node['children'][0]['words'] + old_content[self.end:]
            elif node['editType'] == 'add':
                # add a word
                if node['children'][1]['type'] == tree.TYPE_WORD_DEFINITION:
                    def_node = parser.filter_nodes(node, lambda x: x['type'] == tree.TYPE_QUOTE)[-1]
                    new_words = def_node['words']
                    new_content = old_content[0:self.begin] + \
                                  ('' if new_words[0] == ',' else ' ') + \
                                  new_words + \
                                  ('' if old_content[self.begin] == ' ' else ' ') + \
                                  old_content[self.begin:]
                # add an alinea
                if node['children'][1]['type'] == tree.TYPE_ALINEA_DEFINITION:
                    def_node = parser.filter_nodes(node, lambda x: x['type'] == tree.TYPE_QUOTE)[-1]
                    new_content += '\n' + '\n'.join([
                        n['words'] for n in parser.filter_nodes(node, lambda x: x['type'] == tree.TYPE_QUOTE)
                    ])
                # add an article
                elif node['children'][1]['type'] == tree.TYPE_ARTICLE_DEFINITION:
                    def_node = parser.filter_nodes(node, lambda x: x['type'] == tree.TYPE_QUOTE)[-1]
                    new_content = '\n'.join([
                        n['words'] for n in parser.filter_nodes(node, lambda x: x['type'] == tree.TYPE_QUOTE)
                    ])

            unified_diff = difflib.unified_diff(
                old_content.splitlines() if old_content != '' else [],
                new_content.splitlines() if new_content != '' else [],
                tofile='\"' + self.filename + '\"',
                fromfile='\"' + self.filename + '\"'
            )
            unified_diff = list(unified_diff)
            if len(unified_diff) > 0:
                node['diff'] = ('\n'.join(unified_diff)).replace('\n\n', '\n') # investigate why double newlines
                #node['htmlDiff'] = diff.make_html_rich_diff(old_content, new_content, self.filename)

            if node['parent']['type'] != tree.TYPE_AMENDMENT or node['parent']['status'] == 'approved':
                self.set_content(self.filename, new_content)
        except Exception as e:
            # FIXME: proper error message
            raise e
<|endoftext|>


<commit_before>#!/usr/bin/env python

from flask import Flask, request, redirect, json

from flask_cors import CORS
from motor import Motor

app = Flask(__name__)
CORS(app)

motorCtl = Motor()

@app.route("/", methods=['GET'])
def index():
    return redirect("/static/index.html", code=302)

@app.route("/api/v1/steering/<cmd>", methods=['POST'])
def steering(cmd):
    data = json.loads(request.data)
    if cmd == "left":
        motorCtl.left(data)
    elif cmd == "right":
        motorCtl.right(data)
    elif cmd == "straight":
        motorCtl.straight()
    response = cmd
    response.headers.add('Access-Control-Allow-Origin', '*')
    return response

@app.route("/api/v1/motor/<cmd>", methods=['POST'])
def motor(cmd):
    if cmd == "forward":
        motorCtl.forward()
    elif cmd == "reverse":
        motorCtl.reverse()
    response = cmd
    response.headers.add('Access-Control-Allow-Origin', '*')
    return response

@app.route("/api/v1/throttle", methods=['POST'])
def throttle():
    data = json.loads(request.data)
    motorCtl.throttle(data)
    response = str(data)
    response.headers.add('Access-Control-Allow-Origin', '*')
    return response

if __name__ == "__main__":
    app.run(host="0.0.0.0")
<commit_msg>I should just make all these changes on the robot.<commit_after>#!/usr/bin/env python

from flask import Flask, request, redirect, json

from flask_cors import CORS
from motor import Motor

app = Flask(__name__)
CORS(app)

motorCtl = Motor()

@app.route("/", methods=['GET'])
def index():
    return redirect("/static/index.html", code=302)

@app.route("/api/v1/steering/<cmd>", methods=['POST'])
def steering(cmd):
    data = json.loads(request.data)
    if cmd == "left":
        motorCtl.left(data)
    elif cmd == "right":
        motorCtl.right(data)
    elif cmd == "straight":
        motorCtl.straight()
    return cmd

@app.route("/api/v1/motor/<cmd>", methods=['POST'])
def motor(cmd):
    if cmd == "forward":
        motorCtl.forward()
    elif cmd == "reverse":
        motorCtl.reverse()
    return cmd

@app.route("/api/v1/throttle", methods=['POST'])
def throttle():
    data = json.loads(request.data)
    motorCtl.throttle(data)
    return str(data)

if __name__ == "__main__":
    app.run(host="0.0.0.0")
<|endoftext|>


<commit_before># This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 2 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
# copyright 2003-2010 Sylvain Thenault, all rights reserved.
# contact mailto:thenault@gmail.com
#
# This file is part of logilab-astng.
#
# logilab-astng is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 2.1 of the License, or (at your
# option) any later version.
#
# logilab-astng 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 Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
"""astng manager: avoid multiple astng build of a same module when
possible by providing a class responsible to get astng representation
from various source and using a cache of built modules)

"""

__docformat__ = "restructuredtext en"

import sys
import os
from os.path import dirname, basename, abspath, join, isdir, exists

from logilab.common.modutils import NoSourceFile, is_python_source, \
     file_from_modpath, load_module_from_name, modpath_from_file, \
     get_module_files, get_source_file, zipimport
from logilab.common.configuration import OptionsProviderMixIn

from logilab.astng._exceptions import ASTNGBuildingException

def astng_wrapper(func, modname):
    """wrapper to give to ASTNGManager.project_from_files"""
    print 'parsing %s...' % modname
    try:
        return func(modname)
    except ASTNGBuildingException, exc:
        print exc
    except KeyboardInterrupt:
        raise
    except Exception, exc:
        import traceback
        traceback.print_exc()

def safe_repr(obj):
    try:
        return repr(obj)
    except:
        return '???'

def zip_import_data(filepath):
    if zipimport is None:
        return None, None
    for ext in ('.zip', '.egg'):
        try:
            eggpath, resource = filepath.split(ext + '/', 1)
        except ValueError:
            continue
        try:
            importer = zipimport.zipimporter(eggpath + ext)
            return importer.get_source(resource), resource.replace('/', '.')
        except:
            continue
    return None, None

class ASTNGManager(OptionsProviderMixIn):
    """the astng manager, responsible to build astng from files
     or modules.

    Use the Borg pattern.
    """

    name = 'astng loader'
    options = (("ignore",
                {'type' : "csv", 'metavar' : "<file>",
                 'dest' : "black_list", "default" : ('CVS',),
                 'help' : "add <file> (may be a directory) to the black list\
. It should be a base name, not a path. You may set this option multiple times\
."}),
               ("project",
                {'default': "No Name", 'type' : 'string', 'short': 'p',
                 'metavar' : '<project name>',
                 'help' : 'set the project name.'}),
               )
    brain = {}
    def __init__(self, borg=True):
        if borg:
            self.__dict__ = ASTNGManager.brain
        if not self.__dict__:
            OptionsProviderMixIn.__init__(self)
            self.load_defaults()
            # NOTE: cache entries are added by the [re]builder
            self._cache = {} #Cache(cache_size)
            self._mod_file_cache = {}

    def reset_cache(self):
        self._cache = {} #Cache(cache_size)
        self._mod_file_cache = {}

    def from_directory(self, directory, modname=None):
        """given a module name, return the astng object"""
        # FIXME : seems to be dead or unused code
        modname = modname or basename(directory)
        directory = abspath(directory)
        return Package(directory, modname, self)

    def astng_from_file(self, filepath, modname=None, fallback=True):
        """given a module name, return the astng object"""
        try:
            filepath = get_source_file(filepath, include_no_ext=True)
            source = True
        except NoSourceFile:
            source = False
        if modname is None:
            modname = '.'.join(modpath_from_file(filepath))
        if modname in self._cache:
            return self._cache[modname]
        if source:
            try:
                from logilab.astng.builder import ASTNGBuilder
                return ASTNGBuilder(self).file_build(filepath, modname)
            except (SyntaxError, KeyboardInterrupt, SystemExit):
                raise
            except Exception, ex:
                raise
                if __debug__:
                    print 'error while building astng for', filepath
                    import traceback
                    traceback.print_exc()
                msg = 'Unable to load module %s (%s)' % (modname, ex)
                raise ASTNGBuildingException(msg), None, sys.exc_info()[-1]
        elif fallback and modname:
            return self.astng_from_module_name(modname)
        raise ASTNGBuildingException('unable to get astng for file %s' %
                                     filepath)

    def astng_from_module_name(self, modname, context_file=None):
        """given a module name, return the astng object"""
        if modname in self._cache:
            return self._cache[modname]
        old_cwd = os.getcwd()
        if context_file:
            os.chdir(dirname(context_file))
        try:
            filepath = self.file_from_module_name(modname, context_file)
            if filepath is not None and not is_python_source(filepath):
                data, zmodname = zip_import_data(filepath)
                if data is not None:
                    from logilab.astng.builder import ASTNGBuilder
                    try:
                        return ASTNGBuilder(self).string_build(data, zmodname,
                                                               filepath)
                    except (SyntaxError, KeyboardInterrupt, SystemExit):
                        raise
            if filepath is None or not is_python_source(filepath):
                try:
                    module = load_module_from_name(modname)
                # catch SystemError as well, we may get that on badly
                # initialized C-module
                except (SystemError, ImportError), ex:
                    msg = 'Unable to load module %s (%s)' % (modname, ex)
                    raise ASTNGBuildingException(msg)
                return self.astng_from_module(module, modname)
            return self.astng_from_file(filepath, modname, fallback=False)
        finally:
            os.chdir(old_cwd)

    def file_from_module_name(self, modname, contextfile):
        try:
            value = self._mod_file_cache[(modname, contextfile)]
        except KeyError:
            try:
                value = file_from_modpath(modname.split('.'),
                                          context_file=contextfile)
            except ImportError, ex:
                msg = 'Unable to load module %s (%s)' % (modname, ex)
                value = ASTNGBuildingException(msg)
            self._mod_file_cache[(modname, contextfile)] = value
        if isinstance(value, ASTNGBuildingException):
            raise value
        return value

    def astng_from_module(self, module, modname=None):
        """given an imported module, return the astng object"""
        modname = modname or module.__name__
        if modname in self._cache:
            return self._cache[modname]
        try:
            # some builtin modules don't have __file__ attribute
            filepath = module.__file__
            if is_python_source(filepath):
                return self.astng_from_file(filepath, modname)
        except AttributeError:
            pass
        from logilab.astng.builder import ASTNGBuilder
        return ASTNGBuilder(self).module_build(module, modname)

    def astng_from_class(self, klass, modname=None):
        """get astng for the given class"""
        if modname is None:
            try:
                modname = klass.__module__
            except AttributeError:
                raise ASTNGBuildingException(
                    'Unable to get module for class %s' % safe_repr(klass))
        modastng = self.astng_from_module_name(modname)
        return modastng.getattr(klass.__name__)[0] # XXX

    def infer_astng_from_something(self, obj, modname=None, context=None):
        """infer astng for the given class"""
        if hasattr(obj, '__class__') and not isinstance(obj, type):
            klass = obj.__class__
        else:
            klass = obj
        if modname is None:
            try:
                modname = klass.__module__
            except AttributeError:
                raise ASTNGBuildingException(
                    'Unable to get module for %s' % safe_repr(klass))
            except Exception, ex:
                raise ASTNGBuildingException(
                    'Unexpected error while retrieving module for %s: %s'
                    % (safe_repr(klass), ex))
        try:
            name = klass.__name__
        except AttributeError:
            raise ASTNGBuildingException(
                'Unable to get name for %s' % safe_repr(klass))
        except Exception, ex:
            raise ASTNGBuildingException(
                'Unexpected error while retrieving name for %s: %s'
                % (safe_repr(klass), ex))
        # take care, on living object __module__ is regularly wrong :(
        modastng = self.astng_from_module_name(modname)
        if klass is obj:
            for  infered in modastng.igetattr(name, context):
                yield infered
        else:
            for infered in modastng.igetattr(name, context):
                yield infered.instanciate_class()

    def project_from_files(self, files, func_wrapper=astng_wrapper,
                           project_name=None, black_list=None):
        """return a Project from a list of files or modules"""
        # build the project representation
        project_name = project_name or self.config.project
        black_list = black_list or self.config.black_list
        project = Project(project_name)
        for something in files:
            if not exists(something):
                fpath = file_from_modpath(something.split('.'))
            elif isdir(something):
                fpath = join(something, '__init__.py')
            else:
                fpath = something
            astng = func_wrapper(self.astng_from_file, fpath)
            if astng is None:
                continue
            project.path = project.path or astng.file
            project.add_module(astng)
            base_name = astng.name
            # recurse in package except if __init__ was explicitly given
            if astng.package and something.find('__init__') == -1:
                # recurse on others packages / modules if this is a package
                for fpath in get_module_files(dirname(astng.file),
                                              black_list):
                    astng = func_wrapper(self.astng_from_file, fpath)
                    if astng is None or astng.name == base_name:
                        continue
                    project.add_module(astng)
        return project

# FIXME : seems to be dead or unused code
class Package:
    """a package using a dictionary like interface

    load submodules lazily, as they are needed
    """

    def __init__(self, path, name, manager):
        self.name = name
        self.path = abspath(path)
        self.manager = manager
        self.parent = None
        self.lineno = 0
        self.__keys = None
        self.__subobjects = None

    def fullname(self):
        """return the full name of the package (i.e. prefix by the full name
        of the parent package if any
        """
        if self.parent is None:
            return self.name
        return '%s.%s' % (self.parent.fullname(), self.name)

    def get_subobject(self, name):
        """method used to get sub-objects lazily : sub package or module are
        only build once they are requested
        """
        if self.__subobjects is None:
            try:
                self.__subobjects = dict.fromkeys(self.keys())
            except AttributeError:
                # python <= 2.3
                self.__subobjects = dict([(k, None) for k in self.keys()])
        obj = self.__subobjects[name]
        if obj is None:
            objpath = join(self.path, name)
            if isdir(objpath):
                obj = Package(objpath, name, self.manager)
                obj.parent = self
            else:
                modname = '%s.%s' % (self.fullname(), name)
                obj = self.manager.astng_from_file(objpath + '.py', modname)
            self.__subobjects[name] = obj
        return obj

    def get_module(self, modname):
        """return the Module or Package object with the given name if any
        """
        path = modname.split('.')
        if path[0] != self.name:
            raise KeyError(modname)
        obj = self
        for part in path[1:]:
            obj = obj.get_subobject(part)
        return obj

    def keys(self):
        if self.__keys is None:
            self.__keys = []
            for fname in os.listdir(self.path):
                if fname.endswith('.py'):
                    self.__keys.append(fname[:-3])
                    continue
                fpath = join(self.path, fname)
                if isdir(fpath) and exists(join(fpath, '__init__.py')):
                    self.__keys.append(fname)
            self.__keys.sort()
        return self.__keys[:]

    def values(self):
        return [self.get_subobject(name) for name in self.keys()]

    def items(self):
        return zip(self.keys(), self.values())

    def get(self, name, default=None):
        try:
            return self.get_subobject(name)
        except KeyError:
            return default

    def __getitem__(self, name):
        return self.get_subobject(name)

    def __contains__(self, name):
        return bool(self.get(name))

    def __iter__(self):
        return iter(self.keys())

class Project:
    """a project handle a set of modules / packages"""
    def __init__(self, name=''):
        self.name = name
        self.path = None
        self.modules = []
        self.locals = {}
        self.__getitem__ = self.locals.__getitem__
        self.__iter__ = self.locals.__iter__
        self.values = self.locals.values
        self.keys = self.locals.keys
        self.items = self.locals.items

    def add_module(self, node):
        self.locals[node.name] = node
        self.modules.append(node)

    def get_module(self, name):
        return self.locals[name]

    def get_children(self):
        return self.modules

    def __repr__(self):
        return '<Project %r at %s (%s modules)>' % (self.name, id(self),
                                                    len(self.modules))

<commit_msg>backport stable<commit_after># This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 2 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
# copyright 2003-2010 Sylvain Thenault, all rights reserved.
# contact mailto:thenault@gmail.com
#
# This file is part of logilab-astng.
#
# logilab-astng is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 2.1 of the License, or (at your
# option) any later version.
#
# logilab-astng 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 Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
"""astng manager: avoid multiple astng build of a same module when
possible by providing a class responsible to get astng representation
from various source and using a cache of built modules)

"""

__docformat__ = "restructuredtext en"

import sys
import os
from os.path import dirname, basename, abspath, join, isdir, exists

from logilab.common.modutils import NoSourceFile, is_python_source, \
     file_from_modpath, load_module_from_name, modpath_from_file, \
     get_module_files, get_source_file, zipimport
from logilab.common.configuration import OptionsProviderMixIn

from logilab.astng._exceptions import ASTNGBuildingException

def astng_wrapper(func, modname):
    """wrapper to give to ASTNGManager.project_from_files"""
    print 'parsing %s...' % modname
    try:
        return func(modname)
    except ASTNGBuildingException, exc:
        print exc
    except KeyboardInterrupt:
        raise
    except Exception, exc:
        import traceback
        traceback.print_exc()

def safe_repr(obj):
    try:
        return repr(obj)
    except:
        return '???'

def zip_import_data(filepath):
    if zipimport is None:
        return None, None
    for ext in ('.zip', '.egg'):
        try:
            eggpath, resource = filepath.split(ext + '/', 1)
        except ValueError:
            continue
        try:
            importer = zipimport.zipimporter(eggpath + ext)
            return importer.get_source(resource), resource.replace('/', '.')
        except:
            continue
    return None, None

class ASTNGManager(OptionsProviderMixIn):
    """the astng manager, responsible to build astng from files
     or modules.

    Use the Borg pattern.
    """

    name = 'astng loader'
    options = (("ignore",
                {'type' : "csv", 'metavar' : "<file>",
                 'dest' : "black_list", "default" : ('CVS',),
                 'help' : "add <file> (may be a directory) to the black list\
. It should be a base name, not a path. You may set this option multiple times\
."}),
               ("project",
                {'default': "No Name", 'type' : 'string', 'short': 'p',
                 'metavar' : '<project name>',
                 'help' : 'set the project name.'}),
               )
    brain = {}
    def __init__(self, borg=True):
        if borg:
            self.__dict__ = ASTNGManager.brain
        if not self.__dict__:
            OptionsProviderMixIn.__init__(self)
            self.load_defaults()
            # NOTE: cache entries are added by the [re]builder
            self._cache = {} #Cache(cache_size)
            self._mod_file_cache = {}

    def reset_cache(self):
        self._cache = {} #Cache(cache_size)
        self._mod_file_cache = {}

    def from_directory(self, directory, modname=None):
        """given a module name, return the astng object"""
        # FIXME : seems to be dead or unused code
        modname = modname or basename(directory)
        directory = abspath(directory)
        return Package(directory, modname, self)

    def astng_from_file(self, filepath, modname=None, fallback=True, source=False):
        """given a module name, return the astng object"""
        try:
            filepath = get_source_file(filepath, include_no_ext=True)
            source = True
        except NoSourceFile:
            pass
        if modname is None:
            try:
                modname = '.'.join(modpath_from_file(filepath))
            except ImportError:
                modname = filepath
        if modname in self._cache:
            return self._cache[modname]
        if source:
            try:
                from logilab.astng.builder import ASTNGBuilder
                return ASTNGBuilder(self).file_build(filepath, modname)
            except (SyntaxError, KeyboardInterrupt, SystemExit):
                raise
            except Exception, ex:
                if __debug__:
                    print 'error while building astng for', filepath
                    import traceback
                    traceback.print_exc()
                msg = 'Unable to load module %s (%s)' % (modname, ex)
                raise ASTNGBuildingException(msg), None, sys.exc_info()[-1]
        elif fallback and modname:
            return self.astng_from_module_name(modname)
        raise ASTNGBuildingException('unable to get astng for file %s' %
                                     filepath)

    def astng_from_module_name(self, modname, context_file=None):
        """given a module name, return the astng object"""
        if modname in self._cache:
            return self._cache[modname]
        old_cwd = os.getcwd()
        if context_file:
            os.chdir(dirname(context_file))
        try:
            filepath = self.file_from_module_name(modname, context_file)
            if filepath is not None and not is_python_source(filepath):
                data, zmodname = zip_import_data(filepath)
                if data is not None:
                    from logilab.astng.builder import ASTNGBuilder
                    try:
                        return ASTNGBuilder(self).string_build(data, zmodname,
                                                               filepath)
                    except (SyntaxError, KeyboardInterrupt, SystemExit):
                        raise
            if filepath is None or not is_python_source(filepath):
                try:
                    module = load_module_from_name(modname)
                # catch SystemError as well, we may get that on badly
                # initialized C-module
                except (SystemError, ImportError), ex:
                    msg = 'Unable to load module %s (%s)' % (modname, ex)
                    raise ASTNGBuildingException(msg)
                return self.astng_from_module(module, modname)
            return self.astng_from_file(filepath, modname, fallback=False)
        finally:
            os.chdir(old_cwd)

    def file_from_module_name(self, modname, contextfile):
        try:
            value = self._mod_file_cache[(modname, contextfile)]
        except KeyError:
            try:
                value = file_from_modpath(modname.split('.'),
                                          context_file=contextfile)
            except ImportError, ex:
                msg = 'Unable to load module %s (%s)' % (modname, ex)
                value = ASTNGBuildingException(msg)
            self._mod_file_cache[(modname, contextfile)] = value
        if isinstance(value, ASTNGBuildingException):
            raise value
        return value

    def astng_from_module(self, module, modname=None):
        """given an imported module, return the astng object"""
        modname = modname or module.__name__
        if modname in self._cache:
            return self._cache[modname]
        try:
            # some builtin modules don't have __file__ attribute
            filepath = module.__file__
            if is_python_source(filepath):
                return self.astng_from_file(filepath, modname)
        except AttributeError:
            pass
        from logilab.astng.builder import ASTNGBuilder
        return ASTNGBuilder(self).module_build(module, modname)

    def astng_from_class(self, klass, modname=None):
        """get astng for the given class"""
        if modname is None:
            try:
                modname = klass.__module__
            except AttributeError:
                raise ASTNGBuildingException(
                    'Unable to get module for class %s' % safe_repr(klass))
        modastng = self.astng_from_module_name(modname)
        return modastng.getattr(klass.__name__)[0] # XXX

    def infer_astng_from_something(self, obj, modname=None, context=None):
        """infer astng for the given class"""
        if hasattr(obj, '__class__') and not isinstance(obj, type):
            klass = obj.__class__
        else:
            klass = obj
        if modname is None:
            try:
                modname = klass.__module__
            except AttributeError:
                raise ASTNGBuildingException(
                    'Unable to get module for %s' % safe_repr(klass))
            except Exception, ex:
                raise ASTNGBuildingException(
                    'Unexpected error while retrieving module for %s: %s'
                    % (safe_repr(klass), ex))
        try:
            name = klass.__name__
        except AttributeError:
            raise ASTNGBuildingException(
                'Unable to get name for %s' % safe_repr(klass))
        except Exception, ex:
            raise ASTNGBuildingException(
                'Unexpected error while retrieving name for %s: %s'
                % (safe_repr(klass), ex))
        # take care, on living object __module__ is regularly wrong :(
        modastng = self.astng_from_module_name(modname)
        if klass is obj:
            for  infered in modastng.igetattr(name, context):
                yield infered
        else:
            for infered in modastng.igetattr(name, context):
                yield infered.instanciate_class()

    def project_from_files(self, files, func_wrapper=astng_wrapper,
                           project_name=None, black_list=None):
        """return a Project from a list of files or modules"""
        # build the project representation
        project_name = project_name or self.config.project
        black_list = black_list or self.config.black_list
        project = Project(project_name)
        for something in files:
            if not exists(something):
                fpath = file_from_modpath(something.split('.'))
            elif isdir(something):
                fpath = join(something, '__init__.py')
            else:
                fpath = something
            astng = func_wrapper(self.astng_from_file, fpath)
            if astng is None:
                continue
            project.path = project.path or astng.file
            project.add_module(astng)
            base_name = astng.name
            # recurse in package except if __init__ was explicitly given
            if astng.package and something.find('__init__') == -1:
                # recurse on others packages / modules if this is a package
                for fpath in get_module_files(dirname(astng.file),
                                              black_list):
                    astng = func_wrapper(self.astng_from_file, fpath)
                    if astng is None or astng.name == base_name:
                        continue
                    project.add_module(astng)
        return project

# FIXME : seems to be dead or unused code
class Package:
    """a package using a dictionary like interface

    load submodules lazily, as they are needed
    """

    def __init__(self, path, name, manager):
        self.name = name
        self.path = abspath(path)
        self.manager = manager
        self.parent = None
        self.lineno = 0
        self.__keys = None
        self.__subobjects = None

    def fullname(self):
        """return the full name of the package (i.e. prefix by the full name
        of the parent package if any
        """
        if self.parent is None:
            return self.name
        return '%s.%s' % (self.parent.fullname(), self.name)

    def get_subobject(self, name):
        """method used to get sub-objects lazily : sub package or module are
        only build once they are requested
        """
        if self.__subobjects is None:
            try:
                self.__subobjects = dict.fromkeys(self.keys())
            except AttributeError:
                # python <= 2.3
                self.__subobjects = dict([(k, None) for k in self.keys()])
        obj = self.__subobjects[name]
        if obj is None:
            objpath = join(self.path, name)
            if isdir(objpath):
                obj = Package(objpath, name, self.manager)
                obj.parent = self
            else:
                modname = '%s.%s' % (self.fullname(), name)
                obj = self.manager.astng_from_file(objpath + '.py', modname)
            self.__subobjects[name] = obj
        return obj

    def get_module(self, modname):
        """return the Module or Package object with the given name if any
        """
        path = modname.split('.')
        if path[0] != self.name:
            raise KeyError(modname)
        obj = self
        for part in path[1:]:
            obj = obj.get_subobject(part)
        return obj

    def keys(self):
        if self.__keys is None:
            self.__keys = []
            for fname in os.listdir(self.path):
                if fname.endswith('.py'):
                    self.__keys.append(fname[:-3])
                    continue
                fpath = join(self.path, fname)
                if isdir(fpath) and exists(join(fpath, '__init__.py')):
                    self.__keys.append(fname)
            self.__keys.sort()
        return self.__keys[:]

    def values(self):
        return [self.get_subobject(name) for name in self.keys()]

    def items(self):
        return zip(self.keys(), self.values())

    def get(self, name, default=None):
        try:
            return self.get_subobject(name)
        except KeyError:
            return default

    def __getitem__(self, name):
        return self.get_subobject(name)

    def __contains__(self, name):
        return bool(self.get(name))

    def __iter__(self):
        return iter(self.keys())

class Project:
    """a project handle a set of modules / packages"""
    def __init__(self, name=''):
        self.name = name
        self.path = None
        self.modules = []
        self.locals = {}
        self.__getitem__ = self.locals.__getitem__
        self.__iter__ = self.locals.__iter__
        self.values = self.locals.values
        self.keys = self.locals.keys
        self.items = self.locals.items

    def add_module(self, node):
        self.locals[node.name] = node
        self.modules.append(node)

    def get_module(self, name):
        return self.locals[name]

    def get_children(self):
        return self.modules

    def __repr__(self):
        return '<Project %r at %s (%s modules)>' % (self.name, id(self),
                                                    len(self.modules))

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from __future__ import print_function

import time
import argparse
import traceback

from globalvalues import RPI
if RPI:
    import RPi.GPIO as GPIO

from auxiliaries import LED, Config, PublicKey, NetworkStatus
from auxiliaries import datetime_from_epoch, set_verbosity
from sensor import Sensor
from sender import ServerSender

from globalvalues import SIGNAL_PIN, NOISE_PIN
from globalvalues import POWER_LED_PIN, NETWORK_LED_PIN, COUNTS_LED_PIN
from globalvalues import DEFAULT_CONFIG, DEFAULT_PUBLICKEY, DEFAULT_LOGFILE
from globalvalues import DEFAULT_HOSTNAME, DEFAULT_PORT
from globalvalues import DEFAULT_INTERVAL_NORMAL, DEFAULT_INTERVAL_TEST
from globalvalues import ANSI_RESET, ANSI_YEL, ANSI_GR, ANSI_RED

# this is hacky, but, the {{}} get converted to {} in the first .format() call
#   and then get filled in later
CPM_DISPLAY_TEXT = (
    '{{time}}: {yellow} {{counts}} cts{reset}' +
    ' --- {green}{{cpm:.2f}} +/- {{cpm_err:.2f}} cpm{reset}' +
    ' ({{start_time}} to {{end_time}})').format(
    yellow=ANSI_YEL, reset=ANSI_RESET, green=ANSI_GR)
strf = '%H:%M:%S'

class Manager(object):
    """
    Master object for dosimeter operation.

    Initializes other classes, tracks time intervals, and converts the counts
    from Sensor into a CPM to give to the server.

    time_interval is the interval (in seconds) over for which CPM is
    calculated.
    """

    # Note: keep the __init__() keywords identical to the keywords in argparse,
    #   in order to avoid unpacking them individually.
    # The None's are handled differently, depending on whether test mode.
    def __init__(self,
                 network_LED_pin=NETWORK_LED_PIN,
                 power_LED_pin=POWER_LED_PIN,
                 counts_LED_pin=COUNTS_LED_PIN,
                 signal_pin=SIGNAL_PIN,
                 noise_pin=NOISE_PIN,
                 test=False,
                 interval=None,
                 config=None,
                 publickey=None,
                 hostname=DEFAULT_HOSTNAME,
                 port=DEFAULT_PORT,
                 verbosity=None,
                 log=False,
                 logfile=None,
                 ):

        self.handle_input(log, logfile, verbosity,
                          test, interval, config, publickey)

        # LEDs
        if RPI:
            self.power_LED = LED(power_LED_pin)
            self.network_LED = LED(network_LED_pin)
            self.counts_LED = LED(counts_LED_pin)

            self.power_LED.on()
        else:
            self.power_LED = None
            self.network_LED = None
            self.counts_LED = None

        # other objects
        self.sensor = Sensor(
            counts_LED=self.counts_LED,
            verbosity=self.v,
            logfile=self.logfile)
        self.network_up = NetworkStatus(
            network_led=self.network_LED,
            verbosity=self.v,
            logfile=self.logfile)
        self.sender = ServerSender(
            manager=self,
            verbosity=self.v,
            logfile=self.logfile)

    def handle_input(self,
                     log, logfile, verbosity,
                     test, interval, config, publickey):

        # resolve logging defaults
        if log and logfile is None:
            # use default file if logging is enabled
            logfile = DEFAULT_LOGFILE
        if logfile and not log:
            # enable logging if logfile is specified
            #   (this overrides a log=False input which wouldn't make sense)
            log = True
        if log:
            self.logfile = logfile
        else:
            self.logfile = None

        # set up verbosity
        if verbosity is None:
            if test:
                verbosity = 2
            else:
                verbosity = 1
        self.v = verbosity
        set_verbosity(self, logfile=logfile)

        if log:
            self.vprint(1, '')
            self.vprint(1, 'Writing to logfile at {}'.format(self.logfile))
        self.test = test
        self.running = False

        # resolve defaults that depend on test mode
        if self.test:
            if interval is None:
                self.vprint(
                    2, "No interval given, using default for TEST MODE")
                interval = DEFAULT_INTERVAL_TEST
        else:
            if interval is None:
                self.vprint(
                    2, "No interval given, using default for NORMAL MODE")
                interval = DEFAULT_INTERVAL_NORMAL
            if config is None:
                self.vprint(2, "No config file given, " +
                            "attempting to use default config path")
                config = DEFAULT_CONFIG
            if publickey is None:
                self.vprint(2, "No publickey file given, " +
                            "attempting to use default publickey path")
                publickey = DEFAULT_PUBLICKEY

        self.interval = interval

        if config:
            try:
                self.config = Config(config,
                                     verbosity=self.v, logfile=self.logfile)
            except IOError:
                raise IOError(
                    'Unable to open config file {}!'.format(config))
        else:
            self.vprint(
                1, 'WARNING: no config file given. Not posting to server')
            self.config = None

        if publickey:
            try:
                self.publickey = PublicKey(
                    publickey, verbosity=self.v, logfile=self.logfile)
            except IOError:
                raise IOError(
                    'Unable to load publickey file {}!'.format(publickey))
        else:
            self.vprint(
                1, 'WARNING: no public key given. Not posting to server')
            self.publickey = None

    def run(self):
        """
        Start counting time.

        This method does NOT return, so run in a subprocess if you
        want to keep control.

        However, setting self.running = False will stop, as will a
          KeyboardInterrupt.
        """

        this_start, this_end = self.get_interval(time.time())
        self.vprint(
            1, ('Manager is starting to run at {}' +
                ' with intervals of {}s').format(
                datetime_from_epoch(this_start), self.interval))
        self.running = True

        try:
            while self.running:
                try:
                    self.vprint(3, 'Sleeping at {} until {}'.format(
                        datetime_from_epoch(time.time()),
                        datetime_from_epoch(this_end)))
                    self.sleep_until(this_end)
                except SleepError:
                    self.vprint(1, 'SleepError: system clock skipped ahead!')
                    # the previous start/end times are meaningless.
                    # There are a couple ways this could be handled.
                    # 1. keep the same start time, but go until time.time()
                    #    - but if there was actually an execution delay,
                    #      the CPM will be too high.
                    # 2. set start time to be time.time() - interval,
                    #    and end time is time.time().
                    #    - but if the system clock was adjusted halfway through
                    #      the interval, the CPM will be too low.
                    # The second one is more acceptable.
                    self.vprint(3, 'this_start = {}, this_end = {}'.format(
                        datetime_from_epoch(this_start),
                        datetime_from_epoch(this_end)))
                    this_start, this_end = self.get_interval(
                        time.time() - self.interval)

                self.handle_cpm(this_start, this_end)
                this_start, this_end = self.get_interval(this_end)
        except KeyboardInterrupt:
            self.vprint(1, '\nKeyboardInterrupt: stopping Manager run')
            self.stop()
        except SystemExit:
            self.vprint(1, '\nSystemExit: taking down Manager')
            self.stop()
            self.takedown()

    def stop(self):
        """Stop counting time."""
        self.running = False

    def sleep_until(self, end_time):
        """
        Sleep until the given timestamp.

        Input:
          end_time: number of seconds since epoch, e.g. time.time()
        """

        sleeptime = end_time - time.time()
        self.vprint(3, 'Sleeping for {} seconds'.format(sleeptime))
        if sleeptime < 0:
            # this shouldn't happen now that SleepError is raised and handled
            raise RuntimeError
        time.sleep(sleeptime)
        if time.time() - end_time > 5 or time.time() < end_time:
            # raspberry pi clock reset during this interval
            # normally the first half of the condition triggers it.
            raise SleepError

    def get_interval(self, start_time):
        """
        Return start and end time for interval, based on given start_time.
        """
        end_time = start_time + self.interval
        return start_time, end_time

    def handle_cpm(self, this_start, this_end):
        """Get CPM from sensor, display text, send to server."""

        cpm, cpm_err = self.sensor.get_cpm(this_start, this_end)
        counts = int(round(cpm * self.interval / 60))

        start_text = datetime_from_epoch(this_start).strftime(strf)
        end_text = datetime_from_epoch(this_end).strftime(strf)

        self.vprint(1, CPM_DISPLAY_TEXT.format(
            time=datetime_from_epoch(time.time()),
            counts=counts,
            cpm=cpm,
            cpm_err=cpm_err,
            start_time=start_text,
            end_time=end_text,
        ))
        if self.test:
            self.vprint(
                1, ANSI_RED + " * Test mode, not sending to server * " +
                ANSI_RESET)
        elif not self.config:
            self.vprint(1, "Missing config file, not sending to server")
        elif not self.publickey:
            self.vprint(1, "Missing public key, not sending to server")
        elif not self.network_up:
            self.vprint(1, "Network down, not sending to server")
        else:
            self.sender.send_cpm(cpm, cpm_err)

    def takedown(self):
        """Delete self and child objects and clean up GPIO nicely."""

        # sensor
        self.sensor.cleanup()
        del(self.sensor)

        # network
        self.network_up.cleanup()
        del(self.network_up)

        # power LED
        self.power_LED.off()
        GPIO.cleanup()

        # self. can I even do this?
        del(self)

    @classmethod
    def from_argparse(cls):
        """
        Initialize a Manager instance using arguments from the command line.

        For usage:
        python manager.py -h
        """

        # Note: keep the keywords identical to the keywords in __init__(),
        #   to avoid individual handling of arguments.
        # The arguments with default=None depend on test state.
        #   They are handled in __init__()
        # Also, LED pin numbers could be added here if you want.

        parser = argparse.ArgumentParser(
            description="Manager for the DoseNet radiation detector")
        # test mode
        parser.add_argument(
            '--test', '-t', action='store_true', default=False,
            help='Start in test mode (no config, 30s intervals)')
        # interval: default depends on whether test mode is enabled
        parser.add_argument(
            '--interval', '-i', type=int, default=None,
            help=('Interval of CPM measurement, in seconds' +
                  ' (default 300 for normal mode)'))
        # verbosity
        parser.add_argument(
            '--verbosity', '-v', type=int, default=None,
            help='Verbosity level (0 to 3) (default 1)')
        parser.add_argument(
            '--log', '-l', action='store_true', default=False,
            help='Enable file logging of all verbose text (default off)')
        parser.add_argument(
            '--logfile', '-f', type=str, default=None,
            help='Specify file for logging (default {})'.format(
                DEFAULT_LOGFILE))
        # config file and public key
        parser.add_argument(
            '--config', '-c', default=None,
            help='Specify a config file (default {})'.format(DEFAULT_CONFIG))
        parser.add_argument(
            '--publickey', '-k', default=None,
            help='Specify a publickey file (default {})'.format(
                DEFAULT_PUBLICKEY))
        # server address and port
        parser.add_argument(
            '--hostname', '-s', default=DEFAULT_HOSTNAME,
            help='Specify a server hostname (default {})'.format(
                DEFAULT_HOSTNAME))
        parser.add_argument(
            '--port', '-p', type=int, default=DEFAULT_PORT,
            help='Specify a port for the server (default {})'.format(
                DEFAULT_PORT))

        args = parser.parse_args()
        arg_dict = vars(args)
        mgr = Manager(**arg_dict)

        return mgr

class SleepError(Exception):
    pass

if __name__ == '__main__':
    mgr = Manager.from_argparse()
    try:
        mgr.run()
    except:
        if mgr.logfile:
            # print exception info to logfile
            with open(mgr.logfile, 'a') as f:
                traceback.print_exc(15, f)
        # regardless, re-raise the error which will print to stderr
        raise
<commit_msg>tweak verbosity around sleep_until and SleepError<commit_after># -*- coding: utf-8 -*-
from __future__ import print_function

import time
import argparse
import traceback

from globalvalues import RPI
if RPI:
    import RPi.GPIO as GPIO

from auxiliaries import LED, Config, PublicKey, NetworkStatus
from auxiliaries import datetime_from_epoch, set_verbosity
from sensor import Sensor
from sender import ServerSender

from globalvalues import SIGNAL_PIN, NOISE_PIN
from globalvalues import POWER_LED_PIN, NETWORK_LED_PIN, COUNTS_LED_PIN
from globalvalues import DEFAULT_CONFIG, DEFAULT_PUBLICKEY, DEFAULT_LOGFILE
from globalvalues import DEFAULT_HOSTNAME, DEFAULT_PORT
from globalvalues import DEFAULT_INTERVAL_NORMAL, DEFAULT_INTERVAL_TEST
from globalvalues import ANSI_RESET, ANSI_YEL, ANSI_GR, ANSI_RED

# this is hacky, but, the {{}} get converted to {} in the first .format() call
#   and then get filled in later
CPM_DISPLAY_TEXT = (
    '{{time}}: {yellow} {{counts}} cts{reset}' +
    ' --- {green}{{cpm:.2f}} +/- {{cpm_err:.2f}} cpm{reset}' +
    ' ({{start_time}} to {{end_time}})').format(
    yellow=ANSI_YEL, reset=ANSI_RESET, green=ANSI_GR)
strf = '%H:%M:%S'

class Manager(object):
    """
    Master object for dosimeter operation.

    Initializes other classes, tracks time intervals, and converts the counts
    from Sensor into a CPM to give to the server.

    time_interval is the interval (in seconds) over for which CPM is
    calculated.
    """

    # Note: keep the __init__() keywords identical to the keywords in argparse,
    #   in order to avoid unpacking them individually.
    # The None's are handled differently, depending on whether test mode.
    def __init__(self,
                 network_LED_pin=NETWORK_LED_PIN,
                 power_LED_pin=POWER_LED_PIN,
                 counts_LED_pin=COUNTS_LED_PIN,
                 signal_pin=SIGNAL_PIN,
                 noise_pin=NOISE_PIN,
                 test=False,
                 interval=None,
                 config=None,
                 publickey=None,
                 hostname=DEFAULT_HOSTNAME,
                 port=DEFAULT_PORT,
                 verbosity=None,
                 log=False,
                 logfile=None,
                 ):

        self.handle_input(log, logfile, verbosity,
                          test, interval, config, publickey)

        # LEDs
        if RPI:
            self.power_LED = LED(power_LED_pin)
            self.network_LED = LED(network_LED_pin)
            self.counts_LED = LED(counts_LED_pin)

            self.power_LED.on()
        else:
            self.power_LED = None
            self.network_LED = None
            self.counts_LED = None

        # other objects
        self.sensor = Sensor(
            counts_LED=self.counts_LED,
            verbosity=self.v,
            logfile=self.logfile)
        self.network_up = NetworkStatus(
            network_led=self.network_LED,
            verbosity=self.v,
            logfile=self.logfile)
        self.sender = ServerSender(
            manager=self,
            verbosity=self.v,
            logfile=self.logfile)

    def handle_input(self,
                     log, logfile, verbosity,
                     test, interval, config, publickey):

        # resolve logging defaults
        if log and logfile is None:
            # use default file if logging is enabled
            logfile = DEFAULT_LOGFILE
        if logfile and not log:
            # enable logging if logfile is specified
            #   (this overrides a log=False input which wouldn't make sense)
            log = True
        if log:
            self.logfile = logfile
        else:
            self.logfile = None

        # set up verbosity
        if verbosity is None:
            if test:
                verbosity = 2
            else:
                verbosity = 1
        self.v = verbosity
        set_verbosity(self, logfile=logfile)

        if log:
            self.vprint(1, '')
            self.vprint(1, 'Writing to logfile at {}'.format(self.logfile))
        self.test = test
        self.running = False

        # resolve defaults that depend on test mode
        if self.test:
            if interval is None:
                self.vprint(
                    2, "No interval given, using default for TEST MODE")
                interval = DEFAULT_INTERVAL_TEST
        else:
            if interval is None:
                self.vprint(
                    2, "No interval given, using default for NORMAL MODE")
                interval = DEFAULT_INTERVAL_NORMAL
            if config is None:
                self.vprint(2, "No config file given, " +
                            "attempting to use default config path")
                config = DEFAULT_CONFIG
            if publickey is None:
                self.vprint(2, "No publickey file given, " +
                            "attempting to use default publickey path")
                publickey = DEFAULT_PUBLICKEY

        self.interval = interval

        if config:
            try:
                self.config = Config(config,
                                     verbosity=self.v, logfile=self.logfile)
            except IOError:
                raise IOError(
                    'Unable to open config file {}!'.format(config))
        else:
            self.vprint(
                1, 'WARNING: no config file given. Not posting to server')
            self.config = None

        if publickey:
            try:
                self.publickey = PublicKey(
                    publickey, verbosity=self.v, logfile=self.logfile)
            except IOError:
                raise IOError(
                    'Unable to load publickey file {}!'.format(publickey))
        else:
            self.vprint(
                1, 'WARNING: no public key given. Not posting to server')
            self.publickey = None

    def run(self):
        """
        Start counting time.

        This method does NOT return, so run in a subprocess if you
        want to keep control.

        However, setting self.running = False will stop, as will a
          KeyboardInterrupt.
        """

        this_start, this_end = self.get_interval(time.time())
        self.vprint(
            1, ('Manager is starting to run at {}' +
                ' with intervals of {}s').format(
                datetime_from_epoch(this_start), self.interval))
        self.running = True

        try:
            while self.running:
                try:
                    self.vprint(3, 'Sleeping at {} until {}'.format(
                        datetime_from_epoch(time.time()),
                        datetime_from_epoch(this_end)))
                    self.sleep_until(this_end)
                except SleepError:
                    self.vprint(1, 'SleepError: system clock skipped ahead!')
                    # the previous start/end times are meaningless.
                    # There are a couple ways this could be handled.
                    # 1. keep the same start time, but go until time.time()
                    #    - but if there was actually an execution delay,
                    #      the CPM will be too high.
                    # 2. set start time to be time.time() - interval,
                    #    and end time is time.time().
                    #    - but if the system clock was adjusted halfway through
                    #      the interval, the CPM will be too low.
                    # The second one is more acceptable.
                    self.vprint(
                        3, 'former this_start = {}, this_end = {}'.format(
                            datetime_from_epoch(this_start),
                            datetime_from_epoch(this_end)))
                    this_start, this_end = self.get_interval(
                        time.time() - self.interval)

                self.handle_cpm(this_start, this_end)
                this_start, this_end = self.get_interval(this_end)
        except KeyboardInterrupt:
            self.vprint(1, '\nKeyboardInterrupt: stopping Manager run')
            self.stop()
        except SystemExit:
            self.vprint(1, '\nSystemExit: taking down Manager')
            self.stop()
            self.takedown()

    def stop(self):
        """Stop counting time."""
        self.running = False

    def sleep_until(self, end_time):
        """
        Sleep until the given timestamp.

        Input:
          end_time: number of seconds since epoch, e.g. time.time()
        """

        sleeptime = end_time - time.time()
        self.vprint(3, 'Sleeping for {} seconds'.format(sleeptime))
        if sleeptime < 0:
            # this shouldn't happen now that SleepError is raised and handled
            raise RuntimeError
        time.sleep(sleeptime)
        now = time.time()
        self.vprint(
            3, 'sleep_until offset is {} seconds'.format(now - end_time))
        # if the clock hasn't changed, this offset should be very small
        if now - end_time > 5 or now < end_time:
            # raspberry pi clock reset during this interval
            # normally the first half of the condition triggers it.
            raise SleepError

    def get_interval(self, start_time):
        """
        Return start and end time for interval, based on given start_time.
        """
        end_time = start_time + self.interval
        return start_time, end_time

    def handle_cpm(self, this_start, this_end):
        """Get CPM from sensor, display text, send to server."""

        cpm, cpm_err = self.sensor.get_cpm(this_start, this_end)
        counts = int(round(cpm * self.interval / 60))

        start_text = datetime_from_epoch(this_start).strftime(strf)
        end_text = datetime_from_epoch(this_end).strftime(strf)

        self.vprint(1, CPM_DISPLAY_TEXT.format(
            time=datetime_from_epoch(time.time()),
            counts=counts,
            cpm=cpm,
            cpm_err=cpm_err,
            start_time=start_text,
            end_time=end_text,
        ))
        if self.test:
            self.vprint(
                1, ANSI_RED + " * Test mode, not sending to server * " +
                ANSI_RESET)
        elif not self.config:
            self.vprint(1, "Missing config file, not sending to server")
        elif not self.publickey:
            self.vprint(1, "Missing public key, not sending to server")
        elif not self.network_up:
            self.vprint(1, "Network down, not sending to server")
        else:
            self.sender.send_cpm(cpm, cpm_err)

    def takedown(self):
        """Delete self and child objects and clean up GPIO nicely."""

        # sensor
        self.sensor.cleanup()
        del(self.sensor)

        # network
        self.network_up.cleanup()
        del(self.network_up)

        # power LED
        self.power_LED.off()
        GPIO.cleanup()

        # self. can I even do this?
        del(self)

    @classmethod
    def from_argparse(cls):
        """
        Initialize a Manager instance using arguments from the command line.

        For usage:
        python manager.py -h
        """

        # Note: keep the keywords identical to the keywords in __init__(),
        #   to avoid individual handling of arguments.
        # The arguments with default=None depend on test state.
        #   They are handled in __init__()
        # Also, LED pin numbers could be added here if you want.

        parser = argparse.ArgumentParser(
            description="Manager for the DoseNet radiation detector")
        # test mode
        parser.add_argument(
            '--test', '-t', action='store_true', default=False,
            help='Start in test mode (no config, 30s intervals)')
        # interval: default depends on whether test mode is enabled
        parser.add_argument(
            '--interval', '-i', type=int, default=None,
            help=('Interval of CPM measurement, in seconds' +
                  ' (default 300 for normal mode)'))
        # verbosity
        parser.add_argument(
            '--verbosity', '-v', type=int, default=None,
            help='Verbosity level (0 to 3) (default 1)')
        parser.add_argument(
            '--log', '-l', action='store_true', default=False,
            help='Enable file logging of all verbose text (default off)')
        parser.add_argument(
            '--logfile', '-f', type=str, default=None,
            help='Specify file for logging (default {})'.format(
                DEFAULT_LOGFILE))
        # config file and public key
        parser.add_argument(
            '--config', '-c', default=None,
            help='Specify a config file (default {})'.format(DEFAULT_CONFIG))
        parser.add_argument(
            '--publickey', '-k', default=None,
            help='Specify a publickey file (default {})'.format(
                DEFAULT_PUBLICKEY))
        # server address and port
        parser.add_argument(
            '--hostname', '-s', default=DEFAULT_HOSTNAME,
            help='Specify a server hostname (default {})'.format(
                DEFAULT_HOSTNAME))
        parser.add_argument(
            '--port', '-p', type=int, default=DEFAULT_PORT,
            help='Specify a port for the server (default {})'.format(
                DEFAULT_PORT))

        args = parser.parse_args()
        arg_dict = vars(args)
        mgr = Manager(**arg_dict)

        return mgr

class SleepError(Exception):
    pass

if __name__ == '__main__':
    mgr = Manager.from_argparse()
    try:
        mgr.run()
    except:
        if mgr.logfile:
            # print exception info to logfile
            with open(mgr.logfile, 'a') as f:
                traceback.print_exc(15, f)
        # regardless, re-raise the error which will print to stderr
        raise
<|endoftext|>


<commit_before>"""
adjusts module path to account for virtual namespace

This is required primarily for testing.
"""

import sys
import os

import tiddlywebplugins.utils

VIRTUAL_NAMESPACE = 'tiddlywebplugins'

if sys.version_info[0] <= 2:
    local_package = os.path.abspath(VIRTUAL_NAMESPACE)
    sys.modules[VIRTUAL_NAMESPACE].__dict__['__path__'].insert(0, local_package)
<commit_msg>Update docs on mangler<commit_after>"""
Adjusts module path to account for virtual namespace/namespace packages.

This is required primarily for testing.

The new setuptools allows implicit namespace packages so in order for us
to manipulate the paths associated with the namespace we need to load a
namespace first. Without it, a KeyError happens.
"""

import sys
import os

# Cause namespace to exist.
import tiddlywebplugins.utils

VIRTUAL_NAMESPACE = 'tiddlywebplugins'

if sys.version_info[0] <= 2:
    local_package = os.path.abspath(VIRTUAL_NAMESPACE)
    sys.modules[VIRTUAL_NAMESPACE].__dict__['__path__'].insert(0, local_package)
<|endoftext|>


<commit_before># coding=utf-8

from utils import SensorConsumerBase
import sys
import datetime

class Door(SensorConsumerBase):

    def __init__(self):
        SensorConsumerBase.__init__(self)
        self.notification = None
        self.delete_notification("door")
        self.door_open_elapsed_since = None

    def run(self):
        self.subscribe("door-pubsub", self.pubsub_callback)

    def pubsub_callback(self, data):
        if "action" in data:
            return

        influx_data = {
            "measurement": "door",
            "time": datetime.datetime.utcnow().isoformat() + "Z",
            "tags": {
                "location": "door",
            },
            "fields": data["data"],
        }
        self.insert_into_influx([influx_data])

        if data["data"]["door_outer_open"]:
            if not self.door_open_elapsed_since:
                self.door_open_elapsed_since = datetime.datetime.now()
            notification = {
                "notification": "door",
                "message": "Ulko-ovi on auki ({elapsed_since})",
                "user_dismissable": False,
                "elapsed_since": self.door_open_elapsed_since,
            }
            if self.notification != notification:
                self.notification = notification
                self.update_notification_from_dict(**notification)
        else:
            if self.door_open_elapsed_since:
                self.delete_notification("door")
                self.door_open_elapsed_since = None
                self.notification = None

def main():
    item = Door()
    item.run()
    return 0

if __name__ == '__main__':
    sys.exit(main())
<commit_msg>Trigger lights based on door state<commit_after># coding=utf-8

from utils import SensorConsumerBase
import sys
import datetime
import json

class Door(SensorConsumerBase):

    def __init__(self):
        SensorConsumerBase.__init__(self)
        self.notification = None
        self.delete_notification("door")
        self.door_open_elapsed_since = None

        self.outer_door_state = None
        self.inner_door_state = None

    def run(self):
        self.subscribe("door-pubsub", self.pubsub_callback)

    def pubsub_callback(self, data):
        if "action" in data:
            return

        influx_data = {
            "measurement": "door",
            "time": datetime.datetime.utcnow().isoformat() + "Z",
            "tags": {
                "location": "door",
            },
            "fields": data["data"],
        }
        self.insert_into_influx([influx_data])

        if self.outer_door_state is not None:
            if self.outer_door_state != data["data"]["door_outer_open"]:
                self.redis_instance.publish("lightcontrol-triggers-pubsub", json.dumps({"key": "outer-door", "trigger": "switch", "open": data["data"]["door_outer_open"]}))
        if self.inner_door_state is not None:
            if self.inner_door_state != data["data"]["door_inner_open"]:
                self.redis_instance.publish("lightcontrol-triggers-pubsub", json.dumps({"key": "inner-door", "trigger": "switch", "open": data["data"]["door_inner_open"]}))

        self.outer_door_state = data["data"]["door_outer_open"]
        self.inner_door_state = data["data"]["door_inner_open"]

        if data["data"]["door_outer_open"]:
            if not self.door_open_elapsed_since:
                self.door_open_elapsed_since = datetime.datetime.now()
            notification = {
                "notification": "door",
                "message": "Ulko-ovi on auki ({elapsed_since})",
                "user_dismissable": False,
                "elapsed_since": self.door_open_elapsed_since,
            }
            if self.notification != notification:
                self.notification = notification
                self.update_notification_from_dict(**notification)
        else:
            if self.door_open_elapsed_since:
                self.delete_notification("door")
                self.door_open_elapsed_since = None
                self.notification = None

def main():
    item = Door()
    item.run()
    return 0

if __name__ == '__main__':
    sys.exit(main())
<|endoftext|>