<commit_before>#!/usr/bin/env python2
# -*- coding:utf-8 -*-

# Copyright (c) 2012 Simon C. <contact at saimon.org>

# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.

import logging

import locale
locale.setlocale(locale.LC_ALL, '')

from c2cstats.parser import ParserError
from c2cstats.generators import generate

from flask import Flask, request, redirect, url_for, render_template, \
    jsonify, flash
from flaskext.cache import Cache
from flask.ext.assets import Environment

# configuration
SECRET_KEY = 'development key'
CACHE_TYPE = 'filesystem'
CACHE_DIR = '_cache'
CACHE_THRESHOLD = 100

app = Flask(__name__)
app.config.from_object(__name__)
app.config.from_envvar('C2CSTATS_SETTINGS', silent=True)

assets = Environment(app)
cache = Cache(app)

# logging config
app.logger.setLevel(logging.INFO)
# app.logger.addHandler(logging.StreamHandler(sys.stdout))

@app.route('/')
@cache.cached(timeout=86400)
def index():
    return render_template('index.html')

@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404

@app.route('/user/')
def user_index():
    return redirect(url_for('index'))

@app.route('/user/<int:user_id>/json')
@cache.cached(timeout=604800)
def get_user_stats(user_id):

    try:
        data = generate(str(user_id))
    except ParserError:
        msg = u'Error while generating statistics'
        app.logger.error(msg)
        data = { 'error': msg }
    except:
        msg = u'Something went wrong ...'
        app.logger.error(msg)
        data = { 'error': msg }

    # jsonify uses indent=None for XMLHttpRequest
    return jsonify(**data)

    # resp = make_response(json.dumps(data, indent=None))
    # resp.mimetype = 'application/json'
    # return resp

@app.route('/user/<int:user_id>')
@cache.cached(timeout=86400)
def show_user_stats(user_id):
    user_id = str(user_id)

    context = {
        'json_url': url_for('get_user_stats', user_id=user_id),
        'user_id': user_id
        }

    return render_template('user.html', **context)

@app.route('/query', methods=['POST'])
def query_user():
    try:
        user_id = int(request.form['user_id'])
    except ValueError:
        flash(u"Le numéro d'utilisateur n'est pas valide", 'alert-error')
        return redirect(url_for('index'))

    return redirect(url_for('show_user_stats', user_id=user_id))
<commit_msg>no cache for the developpment config<commit_after>#!/usr/bin/env python2
# -*- coding:utf-8 -*-

# Copyright (c) 2012 Simon C. <contact at saimon.org>

# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.

import logging

import locale
locale.setlocale(locale.LC_ALL, '')

from c2cstats.parser import ParserError
from c2cstats.generators import generate

from flask import Flask, request, redirect, url_for, render_template, \
    jsonify, flash
from flaskext.cache import Cache
from flask.ext.assets import Environment

# configuration
SECRET_KEY = 'development key'
CACHE_TYPE = 'null'
CACHE_DIR = '_cache'
CACHE_THRESHOLD = 100

app = Flask(__name__)
app.config.from_object(__name__)
app.config.from_envvar('C2CSTATS_SETTINGS', silent=True)

assets = Environment(app)
cache = Cache(app)

# logging config
app.logger.setLevel(logging.INFO)
# app.logger.addHandler(logging.StreamHandler(sys.stdout))

@app.route('/')
@cache.cached(timeout=86400)
def index():
    return render_template('index.html')

@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404

@app.route('/user/')
def user_index():
    return redirect(url_for('index'))

@app.route('/user/<int:user_id>/json')
@cache.cached(timeout=604800)
def get_user_stats(user_id):

    try:
        data = generate(str(user_id))
    except ParserError:
        msg = u'Error while generating statistics'
        app.logger.error(msg)
        data = { 'error': msg }
    except:
        msg = u'Something went wrong ...'
        app.logger.error(msg)
        data = { 'error': msg }

    # jsonify uses indent=None for XMLHttpRequest
    return jsonify(**data)

    # resp = make_response(json.dumps(data, indent=None))
    # resp.mimetype = 'application/json'
    # return resp

@app.route('/user/<int:user_id>')
@cache.cached(timeout=86400)
def show_user_stats(user_id):
    user_id = str(user_id)

    context = {
        'json_url': url_for('get_user_stats', user_id=user_id),
        'user_id': user_id
        }

    return render_template('user.html', **context)

@app.route('/query', methods=['POST'])
def query_user():
    try:
        user_id = int(request.form['user_id'])
    except ValueError:
        flash(u"Le numéro d'utilisateur n'est pas valide", 'alert-error')
        return redirect(url_for('index'))

    return redirect(url_for('show_user_stats', user_id=user_id))
<|endoftext|>


<commit_before>#!/usr/bin/env python2
# -*- coding:utf-8 -*-

import os
import codecs
import urlparse
import locale
locale.setlocale(locale.LC_ALL, '')

from c2cstats.parser import Outings, ParserError
from c2cstats.generators import generate_json

from flask import Flask, request, g, redirect, url_for, \
     render_template, flash

# configuration
SECRET_KEY = 'development key'
FILES_DIR = '_output'
FILES_URL = '/files'

app = Flask(__name__)
app.config.from_object(__name__)
app.config.from_envvar('C2CSTATS_SETTINGS', silent=True)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/user/')
def user_index():
    return redirect(url_for('index'))

@app.route('/user/<int:user_id>')
def show_user_stats(user_id):
    user_id = str(user_id)

    data_dir = app.config['FILES_DIR']
    json_file = os.path.join(data_dir, user_id + '.json')

    context = {
        'json_url': app.config['FILES_URL'] + '/' + user_id + '.json',
        'user_id': user_id,
        }

    if not os.path.isfile(json_file):
        try:
            generate_json(user_id, json_file)
        except ParserError:
            flash('Error while loading page', 'error')
            return redirect(url_for('index'))

    return render_template('user.html', **context)

@app.route('/query', methods=['POST'])
def query_user():
    return redirect(url_for('show_user_stats',
                            user_id=int(request.form['user_id'])))

<commit_msg>cleanup<commit_after>#!/usr/bin/env python2
# -*- coding:utf-8 -*-

import os
import codecs
import urlparse
import locale
locale.setlocale(locale.LC_ALL, '')

from c2cstats.generators import generate_json

from flask import Flask, request, g, redirect, url_for, \
     render_template, flash

# configuration
SECRET_KEY = 'development key'
FILES_DIR = '_output'
FILES_URL = '/files'

app = Flask(__name__)
app.config.from_object(__name__)
app.config.from_envvar('C2CSTATS_SETTINGS', silent=True)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/user/')
def user_index():
    return redirect(url_for('index'))

@app.route('/user/<int:user_id>')
def show_user_stats(user_id):
    user_id = str(user_id)
    json_file = os.path.join(app.config['FILES_DIR'], user_id + '.json')

    context = {
        'json_url': app.config['FILES_URL'] + '/' + user_id + '.json',
        'user_id': user_id,
        }

    if not os.path.isfile(json_file):
        try:
            generate_json(user_id, json_file)
        except ParserError:
            flash('Error while loading page', 'error')
            return redirect(url_for('index'))

    return render_template('user.html', **context)

@app.route('/query', methods=['POST'])
def query_user():
    return redirect(url_for('show_user_stats',
                            user_id=int(request.form['user_id'])))
<|endoftext|>


<commit_before>import numpy

class Factory(object):
    @classmethod
    def torus_knot(cls, view_matrix):
        return {
            'type': 'TorusKnot',
            'modelViewMatrix': cls.__to_list(view_matrix),
            'color': 0xff00ff,
            'knotsNumber': 16,
            'radius': 7,
            'tube': 2
        }

    @classmethod
    def text(cls, view_matrix, string, color=0xFFFFFF, font_weight='bold', font_face='Courier New'):
        return {
            'type': 'Text',
            'modelViewMatrix': cls.__to_list(view_matrix),
            'text': string,
            'color': color,
            'fontOptions': {
                'face': font_face,
                'weight': font_weight
            }
        }

    @classmethod
    def points(cls, view_matrix, positions, colors, point_size=1.0):
        return {
            'type': 'Points',
            'modelViewMatrix': cls.__to_list(view_matrix),
            'pointSize': point_size,
            'pointsPositions': cls.__to_list(positions),
            'pointsColors': cls.__to_list(colors),
        }

    @classmethod
    def line(cls, view_matrix, positions, width=1, color=0xFFFFFF):
        return {
            'type': 'Line',
            'modelViewMatrix': cls.__to_list(view_matrix),
            'color': color,
            'lineWidth': width,
            'pointsPositions': cls.__to_list(positions),
        }

    @classmethod
    def surface(cls, view_matrix, heights, resolution):
        return {
            'type': 'Surface',
            'modelViewMatrix': cls.__to_list(view_matrix),
            'heights': list(heights),
            'resolution': resolution,
        }

    @classmethod
    def marching_cubes(cls, view_matrix, scalars_field, resolution, isolation, color=0xFFFFFF):
        return {
            'type': 'MarchingCubes',
            'modelViewMatrix': cls.__to_list(view_matrix),
            'resolution': resolution,
            'color': color,
            'isolation': isolation,
            'scalarsField': cls.__to_list(scalars_field),
        }

    @classmethod
    def stl(cls, view_matrix, stl, color=0xFFFFFF):
        return {
            'type': 'STL',
            'modelViewMatrix': cls.__to_list(view_matrix),
            'color': color,
            'STL': stl,
        }

    @classmethod
    def stl_load(cls, filename, view_matrix=numpy.identity(4)):
        with open(filename) as stl:
            return cls.stl(view_matrix, stl.read())

    @classmethod
    def __to_list(cls, arg):
        if not hasattr(arg, '__iter__'):
            return [arg]

        return sum([cls.__to_list(item) for item in list(arg)], [])
<commit_msg>Use numpy to create lists<commit_after>import numpy

class Factory(object):
    @classmethod
    def torus_knot(cls, view_matrix):
        return {
            'type': 'TorusKnot',
            'modelViewMatrix': cls.__to_list(view_matrix),
            'color': 0xff00ff,
            'knotsNumber': 16,
            'radius': 7,
            'tube': 2
        }

    @classmethod
    def text(cls, view_matrix, string, color=0xFFFFFF, font_weight='bold', font_face='Courier New'):
        return {
            'type': 'Text',
            'modelViewMatrix': cls.__to_list(view_matrix),
            'text': string,
            'color': color,
            'fontOptions': {
                'face': font_face,
                'weight': font_weight
            }
        }

    @classmethod
    def points(cls, view_matrix, positions, colors, point_size=1.0):
        return {
            'type': 'Points',
            'modelViewMatrix': cls.__to_list(view_matrix),
            'pointSize': point_size,
            'pointsPositions': cls.__to_list(positions),
            'pointsColors': cls.__to_list(colors),
        }

    @classmethod
    def line(cls, view_matrix, positions, width=1, color=0xFFFFFF):
        return {
            'type': 'Line',
            'modelViewMatrix': cls.__to_list(view_matrix),
            'color': color,
            'lineWidth': width,
            'pointsPositions': cls.__to_list(positions),
        }

    @classmethod
    def surface(cls, view_matrix, heights, resolution):
        return {
            'type': 'Surface',
            'modelViewMatrix': cls.__to_list(view_matrix),
            'heights': list(heights),
            'resolution': resolution,
        }

    @classmethod
    def marching_cubes(cls, view_matrix, scalars_field, resolution, isolation, color=0xFFFFFF):
        return {
            'type': 'MarchingCubes',
            'modelViewMatrix': cls.__to_list(view_matrix),
            'resolution': resolution,
            'color': color,
            'isolation': isolation,
            'scalarsField': cls.__to_list(scalars_field),
        }

    @classmethod
    def stl(cls, view_matrix, stl, color=0xFFFFFF):
        return {
            'type': 'STL',
            'modelViewMatrix': cls.__to_list(view_matrix),
            'color': color,
            'STL': stl,
        }

    @classmethod
    def stl_load(cls, filename, view_matrix=numpy.identity(4)):
        with open(filename) as stl:
            return cls.stl(view_matrix, stl.read())

    @staticmethod
    def __to_list(arg):
        return numpy.array(arg).flatten().tolist()
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
from django.test import TestCase
from django.db import models

from ..models import Date, Publisher

class DateFields(TestCase):

    def test_date_insert(self):
        field = Date._meta.get_field_by_name('date_insert')[0]
        self.assertEqual(field.__class__, models.DateTimeField)
        self.assertTrue(field.auto_now_add)

    def test_date_update(self):
        field = Date._meta.get_field_by_name('date_update')[0]
        self.assertEqual(field.__class__, models.DateTimeField)
        self.assertTrue(field.auto_now)

class PublisherFields(TestCase):

    def test_site(self):
        field = Publisher._meta.get_field_by_name('site')[0]
        self.assertEqual(field.__class__, models.ForeignKey)

    def test_site_iid(self):
        field = Publisher._meta.get_field_by_name('site_iid')[0]
        self.assertEqual(field.__class__, models.PositiveIntegerField)
        self.assertEqual(field.max_length, 4)
        self.assertTrue(field.null)
        self.assertTrue(field.blank)
        self.assertTrue(field.db_index)

    def test_site_domain(self):
        field = Publisher._meta.get_field_by_name('site_domain')[0]
        self.assertEqual(field.__class__, models.CharField)
        self.assertEqual(field.max_length, 100)
        self.assertTrue(field.null)
        self.assertTrue(field.blank)
        self.assertTrue(field.db_index)

    def test_date_available(self):
        field = Publisher._meta.get_field_by_name('date_available')[0]
        self.assertEqual(field.__class__, models.DateTimeField)
        self.assertTrue(field.null)
        self.assertTrue(field.db_index)

    def test_published(self):
        field = Publisher._meta.get_field_by_name('published')[0]
        self.assertEqual(field.__class__, models.BooleanField)
        self.assertFalse(field.default)
        self.assertTrue(field.db_index)
<commit_msg>test channeling fields<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
from django.test import TestCase
from django.db import models

from ..models import Date, Publisher, Slugged, Channeling
from ..models import Imaged

class DateFields(TestCase):

    def test_date_insert(self):
        field = Date._meta.get_field_by_name('date_insert')[0]
        self.assertEqual(field.__class__, models.DateTimeField)
        self.assertTrue(field.auto_now_add)

    def test_date_update(self):
        field = Date._meta.get_field_by_name('date_update')[0]
        self.assertEqual(field.__class__, models.DateTimeField)
        self.assertTrue(field.auto_now)

class PublisherFields(TestCase):

    def test_site(self):
        field = Publisher._meta.get_field_by_name('site')[0]
        self.assertEqual(field.__class__, models.ForeignKey)

    def test_site_iid(self):
        field = Publisher._meta.get_field_by_name('site_iid')[0]
        self.assertEqual(field.__class__, models.PositiveIntegerField)
        self.assertEqual(field.max_length, 4)
        self.assertTrue(field.null)
        self.assertTrue(field.blank)
        self.assertTrue(field.db_index)

    def test_site_domain(self):
        field = Publisher._meta.get_field_by_name('site_domain')[0]
        self.assertEqual(field.__class__, models.CharField)
        self.assertEqual(field.max_length, 100)
        self.assertTrue(field.null)
        self.assertTrue(field.blank)
        self.assertTrue(field.db_index)

    def test_date_available(self):
        field = Publisher._meta.get_field_by_name('date_available')[0]
        self.assertEqual(field.__class__, models.DateTimeField)
        self.assertTrue(field.null)
        self.assertTrue(field.db_index)

    def test_published(self):
        field = Publisher._meta.get_field_by_name('published')[0]
        self.assertEqual(field.__class__, models.BooleanField)
        self.assertFalse(field.default)
        self.assertTrue(field.db_index)

class ChannelingFields(TestCase):

    def test_channel(self):
        field = Channeling._meta.get_field_by_name('channel')[0]
        self.assertEqual(field.__class__, models.ForeignKey)
        self.assertEqual(field.verbose_name, u"Channel")

    def test_channel_name(self):
        field = Channeling._meta.get_field_by_name('channel_name')[0]
        self.assertEqual(field.__class__, models.CharField)
        self.assertEqual(field.max_length, 140)
        self.assertTrue(field.null)
        self.assertTrue(field.blank)
        self.assertTrue(field.db_index)

    def test_channel_long_slug(self):
        field = Channeling._meta.get_field_by_name('channel_long_slug')[0]
        self.assertEqual(field.__class__, models.CharField)
        self.assertEqual(field.max_length, 250)
        self.assertTrue(field.null)
        self.assertTrue(field.blank)
        self.assertTrue(field.db_index)

class SluggedTest(TestCase):

    def test_channel(self):
        field = Slugged._meta.get_field_by_name('slug')[0]
        self.assertEqual(field.__class__, models.SlugField)
        self.assertTrue(field.db_index)
        self.assertEqual(field.max_length, 150)

class ImagedTest(TestCase):

    def test_main_image(self):
        field = Imaged._meta.get_field_by_name('main_image')[0]
        self.assertEqual(field.__class__, models.ForeignKey)
        self.assertEqual(field.verbose_name, u'Main Image')

    def test_main_image_caption(self):
        field = Imaged._meta.get_field_by_name('main_image_caption')[0]
        self.assertEqual(field.__class__, models.CharField)
        self.assertEqual(field.max_length, 255)
        self.assertTrue(field.null)
        self.assertTrue(field.blank)

    def test_images(self):
        field = Imaged._meta.get_field_by_name('images')[0]
        self.assertEqual(field.__class__, models.ManyToManyField)
        self.assertTrue(field.null)
        self.assertTrue(field.blank)
<|endoftext|>


<commit_before>from time import time
from functools import wraps

class Metrics(object):

    def __init__(self, backend):
        self.backend = backend

    def gauge(self, name, value, tags=None):
        """
        Record the value of a gauge.

        >>> metrics.gauge('users.notifications', 13, tags=['', ''])
        """
        return self._report(name, 'gauge', value, tags)

    def increment(self, name, tags=None):
        """
        Increment a counter.

        >>> metrics.increment('user.profile.views')
        """
        self._report(name, 'counter', 1, tags)

    def decrement(self, name, tags=None):
        """
        Decrement a counter.

        >>> metrics.decrement('hotel.occupation')
        """
        self._report(name, 'counter', -1, tags)

    def timing(self, name, value, tags=None):
        """
        Record a timing.

        >>> metrics.timing('hotel.availability.request_time', 4)
        """
        self._report(name, 'timing', value, tags)

    def event(self, name, text, tags=None):
        """
        Record an event.

        >>> metrics.event('user.signup', 'New user registered')
        """
        self._report(name, 'event', text, tags)

    def custom(self, name, metric, value, tags=None, id_=None):
        """
        Send a custom metric report.

        >>> metrics.custom('hotel.availability.response_data', metric='xml', value={'status': 'ok', 'xml': ...}, id_='2B75D750')
        """
        self._report(name, metric, value, tags, id_)

    class _TimedContextManagerDecorator(object):
        """
        A context manager and a decorator which will report the elapsed time in
        the context OR in a function call.
        """

        def __init__(self, metrics, name=None, tags=None, use_ms=None):
            self.metrics = metrics
            self.name = name
            self.tags = tags
            self.use_ms = use_ms

        def __call__(self, func):
            """
            Decorator which returns the elapsed time of the function call.
            """
            if not self.name:
                self.name = '%s.%s' % (func.__module__, func.__name__)

            @wraps(func)
            def wrapped(*args, **kwargs):
                with self:
                    return func(*args, **kwargs)
            return wrapped

        def __enter__(self):
            self.start = time()

        def __exit__(self, type, value, traceback):
            elapsed = time() - self.start
            elapsed = int(round(1000 * elapsed)) if self.use_ms else elapsed
            self.metrics.timing(self.name, elapsed, self.tags)

    def timed(self, name=None, tags=None, use_ms=None):
        """
        A decorator or context manager that will measure the distribution of a
        function's/context's run time. If the metric is not defined as a decorator, the module
        name and function name will be used.
        ::

            @metrics.timed('user.query.time')
            def get_user(user_id):
                # Do what you need to ...
                pass

            # Is equivalent to ...
            with metrics.timed('user.query.time'):
                # Do what you need to ...
                pass

            # Is equivalent to ...
            start = time.time()
            try:
                get_user(user_id)
            finally:
                metrics.timing('user.query.time', time.time() - start)
        """
        return self._TimedContextManagerDecorator(self, name, tags, use_ms)

    def _report(self, name, metric, value, tags, id_=None):
        return self.backend.report(name, metric, value, tags, id_)
<commit_msg>Improve base metric class documentation<commit_after>from time import time
from functools import wraps

class Metrics(object):

    def __init__(self, backend):
        self.backend = backend

    def gauge(self, name, value, tags=None):
        """
        Record the value of a gauge.

        >>> metrics.gauge('users.notifications', 13, tags=['new_message', 'follow_request'])
        """
        return self._report(name, 'gauge', value, tags)

    def increment(self, name, tags=None):
        """
        Increment a counter.

        >>> metrics.increment('user.profile.views')
        """
        self._report(name, 'counter', 1, tags)

    def decrement(self, name, tags=None):
        """
        Decrement a counter.

        >>> metrics.decrement('hotel.occupation')
        """
        self._report(name, 'counter', -1, tags)

    def timing(self, name, value, tags=None):
        """
        Record a timing.

        >>> metrics.timing('hotel.availability.request_time', 4)
        """
        self._report(name, 'timing', value, tags)

    def event(self, name, text, tags=None):
        """
        Record an event.

        >>> metrics.event('user.signup', 'New user registered')
        """
        self._report(name, 'event', text, tags)

    def custom(self, name, metric, value, tags=None, id_=None):
        """
        Send a custom metric report.

        >>> metrics.custom('hotel.availability.response_data', metric='xml', value={'status': 'ok', 'xml': ...}, id_='2B75D750')
        """
        self._report(name, metric, value, tags, id_)

    class _TimedContextManagerDecorator(object):
        """
        Class that implements the context manager and the decorator for "timed" method.
        """

        def __init__(self, metrics, name=None, tags=None, use_ms=None):
            self.metrics = metrics
            self.name = name
            self.tags = tags
            self.use_ms = use_ms

        def __call__(self, func):
            """
            Decorator which returns the elapsed time of the function call.
            """
            if not self.name:
                self.name = u'{0:s}.{1:s}'.format(func.__module__, func.__name__)

            @wraps(func)
            def wrapped(*args, **kwargs):
                with self:
                    return func(*args, **kwargs)
            return wrapped

        def __enter__(self):
            self.start = time()

        def __exit__(self, type, value, traceback):
            elapsed = time() - self.start
            elapsed = int(round(1000 * elapsed)) if self.use_ms else elapsed
            self.metrics.timing(self.name, elapsed, self.tags)

    def timed(self, name=None, tags=None, use_ms=None):
        """
        Measure the amount of time of a function (using a decorator) or a piece of
        code (using a context manager). If _name_ is not provided while using the decorator it
        will be used the name of the module and the function.
        ::

            # With decorator
            @metrics.timed('request.response_time')
            def perform_request(params):
                pass

            # With context manager
            with metrics.timed('request.response_time'):
                pass
        """
        return self._TimedContextManagerDecorator(self, name, tags, use_ms)

    def _report(self, name, metric, value, tags, id_=None):
        return self.backend.report(name, metric, value, tags, id_)
<|endoftext|>


<commit_before>"OrderPortal web application server."

import logging
import os
import sys

import tornado.web
import tornado.ioloop

from orderportal import designs
from orderportal import settings
from orderportal import utils
from orderportal import uimodules
from orderportal.requesthandler import RequestHandler

from orderportal.home import *
from orderportal.admin import *
from orderportal.account import *
from orderportal.group import *
from orderportal.form import *
from orderportal.order import *
from orderportal.news import *
from orderportal.info import *
from orderportal.file import *
from orderportal.event import *
from orderportal.search import *

def main():
    if len(sys.argv) == 2:
        filepath = sys.argv[1]
    else:
        filepath = None
    utils.load_settings(filepath=filepath)
    designs.load_design_documents(utils.get_db())

    url = tornado.web.url
    handlers = [
        url(r'/', Home, name='home'),
        url(r'/status', Status, name="status"),
        url(r'/order/([^/.]+)', Order, name='order'),
        url(r'/api/v1/order/([^/.]+)', OrderApiV1, name='order_api'),
        url(r'/order/([^/]+).csv', OrderCsv, name='order_csv'),
        url(r'/order/([^/]+).xlsx', OrderXlsx, name='order_xlsx'),
        url(r'/order/([^/]+).zip', OrderZip, name='order_zip'),
        url(r'/order/([0-9a-f]{32})/logs', OrderLogs, name='order_logs'),
        url(r'/order', OrderCreate, name='order_create'),
        url(r'/api/v1/order', OrderCreateApiV1, name='order_create_api'),
        url(r'/order/([0-9a-f]{32})/edit', OrderEdit, name='order_edit'),
        url(r'/order/([0-9a-f]{32})/transition/(\w+)',
            OrderTransition, name='order_transition'),
        url(r'/api/v1/order/([0-9a-f]{32})/transition/(\w+)',
            OrderTransitionApiV1, name='order_transition_api'),
        url(r'/order/([0-9a-f]{32})/owner', OrderOwner, name='order_owner'),
        url(r'/order/([0-9a-f]{32})/clone', OrderClone, name='order_clone'),
        url(r'/order/([0-9a-f]{32})/file', OrderFile, name='order_file_add'),
        url(r'/order/([0-9a-f]{32})/file/([^/]+)',OrderFile,name='order_file'),
        url(r'/order/([0-9a-f]{32})/report', OrderReport, name='order_report'),
        url(r'/api/v1/order/([0-9a-f]{32})/report',
            OrderReportApiV1, name='order_report_api'),
        url(r'/order/([0-9a-f]{32})/report/edit',
            OrderReportEdit, name='order_report_edit'),
        url(r'/orders', Orders, name='orders'),
        url(r'/api/v1/orders', OrdersApiV1, name='orders_api'),
        url(r'/orders.csv', OrdersCsv, name='orders_csv'),
        url(r'/orders.xlsx', OrdersXlsx, name='orders_xlsx'),
        url(r'/accounts', Accounts, name='accounts'),
        url(r'/api/v1/accounts', AccountsApiV1, name='accounts_api'),
        url(r'/accounts.csv', AccountsCsv, name='accounts_csv'),
        url(r'/accounts.xlsx', AccountsXlsx, name='accounts_xlsx'),
        url(r'/account/([^/]+)', Account, name='account'),
        url(r'/api/v1/account/([^/]+)', AccountApiV1, name='account_api'),
        url(r'/account/([^/]+)/orders', AccountOrders, name='account_orders'),
        url(r'/api/v1/account/([^/]+)/orders',
            AccountOrdersApiV1, name='account_orders_api'),
        url(r'/account/([^/]+)/groups/orders',
            AccountGroupsOrders, name='account_groups_orders'),
        url(r'/api/v1/account/([^/]+)/groups/orders',
            AccountGroupsOrdersApiV1, name='account_groups_orders_api'),
        url(r'/account/([^/]+)/logs', AccountLogs, name='account_logs'),
        url(r'/account/([^/]+)/messages',
            AccountMessages, name='account_messages'),
        url(r'/account/([^/]+)/edit', AccountEdit, name='account_edit'),
        url(r'/group', GroupCreate, name='group_create'),
        url(r'/group/([0-9a-f]{32})', Group, name='group'),
        url(r'/group/([0-9a-f]{32})/edit', GroupEdit, name='group_edit'),
        url(r'/group/([0-9a-f]{32})/accept', GroupAccept, name='group_accept'),
        url(r'/group/([0-9a-f]{32})/decline',
            GroupDecline, name='group_decline'),
        url(r'/group/([0-9a-f]{32})/logs', GroupLogs, name='group_logs'),
        url(r'/groups', Groups, name='groups'),
        url(r'/search', Search, name='search'),
        url(r'/login', Login, name='login'),
        url(r'/logout', Logout, name='logout'),
        url(r'/reset', Reset, name='reset'),
        url(r'/password', Password, name='password'),
        url(r'/register', Register, name='register'),
        url(r'/registered', Registered, name='registered'),
        url(r'/account/([^/]+)/enable', AccountEnable, name='account_enable'),
        url(r'/account/([^/]+)/disable', AccountDisable,name='account_disable'),
        url(r'/account/([^/]+)/updateinfo',
            AccountUpdateInfo, name='account_update_info'),
        url(r'/forms', Forms, name='forms'),
        url(r'/form/([0-9a-f]{32})', Form, name='form'),
        url(r'/api/v1/form/([0-9a-f]{32})', FormApiV1, name='form_api'),
        url(r'/form/([0-9a-f]{32})/logs', FormLogs, name='form_logs'),
        url(r'/form', FormCreate, name='form_create'),
        url(r'/form/([0-9a-f]{32})/edit', FormEdit, name='form_edit'),
        url(r'/form/([0-9a-f]{32})/clone', FormClone, name='form_clone'),
        url(r'/form/([0-9a-f]{32})/pending', FormPending, name='form_pending'),
        url(r'/form/([0-9a-f]{32})/testing', FormTesting, name='form_testing'),
        url(r'/form/([0-9a-f]{32})/enable', FormEnable, name='form_enable'),
        url(r'/form/([0-9a-f]{32})/disable', FormDisable, name='form_disable'),
        url(r'/form/([0-9a-f]{32})/field', FormFieldCreate,name='field_create'),
        url(r'/form/([0-9a-f]{32})/field/([a-zA-Z][_a-zA-Z0-9]*)',
            FormFieldEdit, name='field_edit'),
        url(r'/form/([0-9a-f]{32})/field/([a-zA-Z][_a-zA-Z0-9]*)/descr',
            FormFieldEditDescr, name='field_edit_descr'),
        url(r'/form/([0-9a-f]{32})/orders', FormOrders, name='form_orders'),
        url(r'/form/([0-9a-f]{32})/aggregate',
            FormOrdersAggregate, name='form_orders_aggregate'),
        url(r'/news', News, name='news'),
        url(r'/new/([0-9a-f]{32})', NewsEdit, name='news_edit'),
        url(r'/new', NewsCreate, name='news_create'),
        url(r'/events', Events, name='events'),
        url(r'/event/([0-9a-f]{32})', Event, name='event'),
        url(r'/event', EventCreate, name='event_create'),
        url(r'/contact', Contact, name='contact'),
        url(r'/about', About, name='about'),
        url(r'/software', Software, name='software'),
        url(r'/infos', Infos, name='infos'),
        url(r'/info', InfoCreate, name='info_create'),
        url(r'/info/([^/]+)', Info, name='info'),
        url(r'/info/([^/]+)/edit', InfoEdit, name='info_edit'),
        url(r'/info/([^/]+)/logs', InfoLogs, name='info_logs'),
        url(r'/files', Files, name='files'),
        url(r'/file', FileCreate, name='file_create'),
        url(r'/file/([^/]+)', File, name='file'),
        url(r'/file/([^/]+)/meta', FileMeta, name='file_meta'),
        url(r'/file/([^/]+)/download', FileDownload, name='file_download'),
        url(r'/file/([^/]+)/edit', FileEdit, name='file_edit'),
        url(r'/api/v1/file/([^/]+)/edit', FileEditApiV1, name='file_edit_api'),
        url(r'/file/([0-9a-f]{32})/logs', FileLogs, name='file_logs'),
        url(r'/log/([0-9a-f]{32})', Log, name='log'),
        url(r'/([0-9a-f]{32})', Entity, name='entity'),
        url(r'/admin/global_modes', GlobalModes, name='global_modes'),
        url(r'/admin/settings', Settings, name='settings'),
        url(r'/admin/text/([^/]+)', Text, name='text'),
        url(r'/admin/texts', Texts, name='texts'),
        url(r'/admin/order_statuses', OrderStatuses, name='order_statuses'),
        url(r'/admin/order_messages',
            AdminOrderMessages, name='admin_order_messages'),
        url(r'/admin/account_messages',
            AdminAccountMessages, name='admin_account_messages'),
        url(r'/site/([^/]+)', tornado.web.StaticFileHandler,
            {'path': settings['SITE_STATIC_DIR']}, name='site'),
        url(r'/api/v1/(.*)', NoSuchEntityApiV1),
        url(r'/(.*)', NoSuchEntity)]
    application = tornado.web.Application(
        handlers=handlers,
        debug=settings.get('TORNADO_DEBUG', False),
        cookie_secret=settings['COOKIE_SECRET'],
        xsrf_cookies=True,
        ui_modules=uimodules,
        template_path=os.path.join(settings['ROOT'], 'templates'),
        static_path=os.path.join(settings['ROOT'], 'static'),
        login_url=(settings['BASE_URL_PATH_PREFIX'] or '') + '/login')
    # Add href URLs for the status icons.
    # This depends on order status setup.
    for key, value in settings['ORDER_STATUSES_LOOKUP'].items():
        value['href'] = application.reverse_url('site', key + '.png')
    application.listen(settings['PORT'], xheaders=True)
    url = settings['BASE_URL']
    if settings['BASE_URL_PATH_PREFIX']:
        url += settings['BASE_URL_PATH_PREFIX']
    pid = os.getpid()
    if settings["PIDFILE"]:
        with open(settings["PIDFILE"], "w") as pf:
            pf.write(str(pid))
    logging.info(f"web server PID {pid} at {url}")
    tornado.ioloop.IOLoop.instance().start()

if __name__ == "__main__":
    main()
<commit_msg>Clarification.<commit_after>"OrderPortal web application server."

import logging
import os
import sys

import tornado.web
import tornado.ioloop

from orderportal import designs
from orderportal import settings
from orderportal import utils
from orderportal import uimodules
from orderportal.requesthandler import RequestHandler

from orderportal.home import *
from orderportal.admin import *
from orderportal.account import *
from orderportal.group import *
from orderportal.form import *
from orderportal.order import *
from orderportal.news import *
from orderportal.info import *
from orderportal.file import *
from orderportal.event import *
from orderportal.search import *

def main():
    if len(sys.argv) == 2:
        filepath = sys.argv[1]
    else:
        filepath = None
    utils.load_settings(filepath=filepath)
    designs.load_design_documents(utils.get_db())

    url = tornado.web.url
    handlers = [
        url(r'/', Home, name='home'),
        url(r'/status', Status, name="status"),
        url(r'/order/([^/.]+)', Order, name='order'),
        url(r'/api/v1/order/([^/.]+)', OrderApiV1, name='order_api'),
        url(r'/order/([^/]+).csv', OrderCsv, name='order_csv'),
        url(r'/order/([^/]+).xlsx', OrderXlsx, name='order_xlsx'),
        url(r'/order/([^/]+).zip', OrderZip, name='order_zip'),
        url(r'/order/([0-9a-f]{32})/logs', OrderLogs, name='order_logs'),
        url(r'/order', OrderCreate, name='order_create'),
        url(r'/api/v1/order', OrderCreateApiV1, name='order_create_api'),
        url(r'/order/([0-9a-f]{32})/edit', OrderEdit, name='order_edit'),
        url(r'/order/([0-9a-f]{32})/transition/(\w+)',
            OrderTransition, name='order_transition'),
        url(r'/api/v1/order/([0-9a-f]{32})/transition/(\w+)',
            OrderTransitionApiV1, name='order_transition_api'),
        url(r'/order/([0-9a-f]{32})/owner', OrderOwner, name='order_owner'),
        url(r'/order/([0-9a-f]{32})/clone', OrderClone, name='order_clone'),
        url(r'/order/([0-9a-f]{32})/file', OrderFile, name='order_file_add'),
        url(r'/order/([0-9a-f]{32})/file/([^/]+)',OrderFile,name='order_file'),
        url(r'/order/([0-9a-f]{32})/report', OrderReport, name='order_report'),
        url(r'/api/v1/order/([0-9a-f]{32})/report',
            OrderReportApiV1, name='order_report_api'),
        url(r'/order/([0-9a-f]{32})/report/edit',
            OrderReportEdit, name='order_report_edit'),
        url(r'/orders', Orders, name='orders'),
        url(r'/api/v1/orders', OrdersApiV1, name='orders_api'),
        url(r'/orders.csv', OrdersCsv, name='orders_csv'),
        url(r'/orders.xlsx', OrdersXlsx, name='orders_xlsx'),
        url(r'/accounts', Accounts, name='accounts'),
        url(r'/api/v1/accounts', AccountsApiV1, name='accounts_api'),
        url(r'/accounts.csv', AccountsCsv, name='accounts_csv'),
        url(r'/accounts.xlsx', AccountsXlsx, name='accounts_xlsx'),
        url(r'/account/([^/]+)', Account, name='account'),
        url(r'/api/v1/account/([^/]+)', AccountApiV1, name='account_api'),
        url(r'/account/([^/]+)/orders', AccountOrders, name='account_orders'),
        url(r'/api/v1/account/([^/]+)/orders',
            AccountOrdersApiV1, name='account_orders_api'),
        url(r'/account/([^/]+)/groups/orders',
            AccountGroupsOrders, name='account_groups_orders'),
        url(r'/api/v1/account/([^/]+)/groups/orders',
            AccountGroupsOrdersApiV1, name='account_groups_orders_api'),
        url(r'/account/([^/]+)/logs', AccountLogs, name='account_logs'),
        url(r'/account/([^/]+)/messages',
            AccountMessages, name='account_messages'),
        url(r'/account/([^/]+)/edit', AccountEdit, name='account_edit'),
        url(r'/group', GroupCreate, name='group_create'),
        url(r'/group/([0-9a-f]{32})', Group, name='group'),
        url(r'/group/([0-9a-f]{32})/edit', GroupEdit, name='group_edit'),
        url(r'/group/([0-9a-f]{32})/accept', GroupAccept, name='group_accept'),
        url(r'/group/([0-9a-f]{32})/decline',
            GroupDecline, name='group_decline'),
        url(r'/group/([0-9a-f]{32})/logs', GroupLogs, name='group_logs'),
        url(r'/groups', Groups, name='groups'),
        url(r'/search', Search, name='search'),
        url(r'/login', Login, name='login'),
        url(r'/logout', Logout, name='logout'),
        url(r'/reset', Reset, name='reset'),
        url(r'/password', Password, name='password'),
        url(r'/register', Register, name='register'),
        url(r'/registered', Registered, name='registered'),
        url(r'/account/([^/]+)/enable', AccountEnable, name='account_enable'),
        url(r'/account/([^/]+)/disable', AccountDisable,name='account_disable'),
        url(r'/account/([^/]+)/updateinfo',
            AccountUpdateInfo, name='account_update_info'),
        url(r'/forms', Forms, name='forms'),
        url(r'/form/([0-9a-f]{32})', Form, name='form'),
        url(r'/api/v1/form/([0-9a-f]{32})', FormApiV1, name='form_api'),
        url(r'/form/([0-9a-f]{32})/logs', FormLogs, name='form_logs'),
        url(r'/form', FormCreate, name='form_create'),
        url(r'/form/([0-9a-f]{32})/edit', FormEdit, name='form_edit'),
        url(r'/form/([0-9a-f]{32})/clone', FormClone, name='form_clone'),
        url(r'/form/([0-9a-f]{32})/pending', FormPending, name='form_pending'),
        url(r'/form/([0-9a-f]{32})/testing', FormTesting, name='form_testing'),
        url(r'/form/([0-9a-f]{32})/enable', FormEnable, name='form_enable'),
        url(r'/form/([0-9a-f]{32})/disable', FormDisable, name='form_disable'),
        url(r'/form/([0-9a-f]{32})/field', FormFieldCreate,name='field_create'),
        url(r'/form/([0-9a-f]{32})/field/([a-zA-Z][_a-zA-Z0-9]*)',
            FormFieldEdit, name='field_edit'),
        url(r'/form/([0-9a-f]{32})/field/([a-zA-Z][_a-zA-Z0-9]*)/descr',
            FormFieldEditDescr, name='field_edit_descr'),
        url(r'/form/([0-9a-f]{32})/orders', FormOrders, name='form_orders'),
        url(r'/form/([0-9a-f]{32})/aggregate',
            FormOrdersAggregate, name='form_orders_aggregate'),
        url(r'/news', News, name='news'),
        url(r'/new/([0-9a-f]{32})', NewsEdit, name='news_edit'),
        url(r'/new', NewsCreate, name='news_create'),
        url(r'/events', Events, name='events'),
        url(r'/event/([0-9a-f]{32})', Event, name='event'),
        url(r'/event', EventCreate, name='event_create'),
        url(r'/contact', Contact, name='contact'),
        url(r'/about', About, name='about'),
        url(r'/software', Software, name='software'),
        url(r'/infos', Infos, name='infos'),
        url(r'/info', InfoCreate, name='info_create'),
        url(r'/info/([^/]+)', Info, name='info'),
        url(r'/info/([^/]+)/edit', InfoEdit, name='info_edit'),
        url(r'/info/([^/]+)/logs', InfoLogs, name='info_logs'),
        url(r'/files', Files, name='files'),
        url(r'/file', FileCreate, name='file_create'),
        url(r'/file/([^/]+)', File, name='file'),
        url(r'/file/([^/]+)/meta', FileMeta, name='file_meta'),
        url(r'/file/([^/]+)/download', FileDownload, name='file_download'),
        url(r'/file/([^/]+)/edit', FileEdit, name='file_edit'),
        url(r'/api/v1/file/([^/]+)/edit', FileEditApiV1, name='file_edit_api'),
        url(r'/file/([0-9a-f]{32})/logs', FileLogs, name='file_logs'),
        url(r'/log/([0-9a-f]{32})', Log, name='log'),
        url(r'/([0-9a-f]{32})', Entity, name='entity'),
        url(r'/admin/global_modes', GlobalModes, name='global_modes'),
        url(r'/admin/settings', Settings, name='settings'),
        url(r'/admin/text/([^/]+)', Text, name='text'),
        url(r'/admin/texts', Texts, name='texts'),
        url(r'/admin/order_statuses', OrderStatuses, name='order_statuses'),
        url(r'/admin/order_messages',
            AdminOrderMessages, name='admin_order_messages'),
        url(r'/admin/account_messages',
            AdminAccountMessages, name='admin_account_messages'),
        url(r'/site/([^/]+)', tornado.web.StaticFileHandler,
            {'path': settings['SITE_STATIC_DIR']}, name='site'),
        url(r'/api/v1/(.*)', NoSuchEntityApiV1),
        url(r'/(.*)', NoSuchEntity)]
    application = tornado.web.Application(
        handlers=handlers,
        debug=settings.get('TORNADO_DEBUG', False),
        cookie_secret=settings['COOKIE_SECRET'],
        xsrf_cookies=True,
        ui_modules=uimodules,
        template_path=os.path.join(settings['ROOT'], 'templates'),
        static_path=os.path.join(settings['ROOT'], 'static'),
        login_url=(settings['BASE_URL_PATH_PREFIX'] or '') + '/login')
    # Add href URLs for the status icons data in settings.
    # This depends on order status setup.
    for key, value in settings['ORDER_STATUSES_LOOKUP'].items():
        value['href'] = application.reverse_url('site', key + '.png')
    application.listen(settings['PORT'], xheaders=True)
    url = settings['BASE_URL']
    if settings['BASE_URL_PATH_PREFIX']:
        url += settings['BASE_URL_PATH_PREFIX']
    pid = os.getpid()
    if settings["PIDFILE"]:
        with open(settings["PIDFILE"], "w") as pf:
            pf.write(str(pid))
    logging.info(f"web server PID {pid} at {url}")
    tornado.ioloop.IOLoop.instance().start()

if __name__ == "__main__":
    main()
<|endoftext|>


<commit_before>import abc
from decimal import Decimal

from core import Key, Keyboard

class StandardKeyboard(Keyboard):
    """ A StandardKeyboard is a keyboard with standard Cherry MX key sizes and spacings. (see: http://www.fentek-ind.com/images/CHERRY_MX_keyswitch.pdf)

    """
    def __init__(self):
        self.unit_height = Decimal('19.05')
        self.unit_width = Decimal('19.05')
        self.separator = '|'
        self.comment = '-'
        self.padding = 'x'
        self._keys = None

    @property
    def keys(self):
        if self._keys == None:
            self._keys = self.load_schema()
        return self._keys

    def load_schema(self):
        keys = list()
        offset_y = Decimal(0)
        for line in self.schema.splitlines():
            # don't process lines starting with the comment prefix
            if line.startswith(self.comment):
                continue
            offset_x = Decimal(0)
            for key in line.strip(self.separator).split(self.separator):
                # only add the key if it isn't padding
                if self.padding not in key:
                    keys.append(Key(x=offset_x, y=offset_y))
                unit = Decimal(len(key) * 0.25 + 1)
                offset_x += Decimal(self.unit_width * unit)
            offset_y += Decimal(self.unit_height)
        return keys

    @abc.abstractproperty
    def schema(self):
        pass

class ANSI(StandardKeyboard):
    def __init__(self):
        super().__init__()

    @property
    def schema(self):
        return """\
-------------------------------------------------------------
|   |   |   |   |   |   |   |   |   |   |   |   |   |       |
-------------------------------------------------------------
|     |   |   |   |   |   |   |   |   |   |   |   |   |     |
-------------------------------------------------------------
|      |   |   |   |   |   |   |   |   |   |   |   |        |
-------------------------------------------------------------
|        |   |   |   |   |   |   |   |   |   |   |          |
-------------------------------------------------------------
|    |    |    |                        |    |    |    |    |
-------------------------------------------------------------"""

class Core33(StandardKeyboard):
    def __init__(self):
        super().__init__()

    @property
    def schema(self):
        return """\
-------------------------------------------------------------
|  x  |   |   |   |   |   |   |   |   |   |   |   |   |  x  |
-------------------------------------------------------------
|   x  |   |   |   |   |   |   |   |   |   |   |   |    x   |
-------------------------------------------------------------
|     x  |   |   |   |   |   |   |   |   |   |   |    x     |
-------------------------------------------------------------"""

class SixKey(StandardKeyboard):
    def __init__(self):
        super().__init__()

    @property
    def schema(self):
        return """\
-------------
|   |   |   |
-------------
|   |   |   |
-------------"""
<commit_msg>Temporarily only use alphabet keys in Core33<commit_after>import abc
from decimal import Decimal

from core import Key, Keyboard

class StandardKeyboard(Keyboard):
    """ A StandardKeyboard is a keyboard with standard Cherry MX key sizes and spacings. (see: http://www.fentek-ind.com/images/CHERRY_MX_keyswitch.pdf)

    """
    def __init__(self):
        self.unit_height = Decimal('19.05')
        self.unit_width = Decimal('19.05')
        self.separator = '|'
        self.comment = '-'
        self.padding = 'x'
        self._keys = None

    @property
    def keys(self):
        if self._keys == None:
            self._keys = self.load_schema()
        return self._keys

    def load_schema(self):
        keys = list()
        offset_y = Decimal(0)
        for line in self.schema.splitlines():
            # don't process lines starting with the comment prefix
            if line.startswith(self.comment):
                continue
            offset_x = Decimal(0)
            for key in line.strip(self.separator).split(self.separator):
                # only add the key if it isn't padding
                if self.padding not in key:
                    keys.append(Key(x=offset_x, y=offset_y))
                unit = Decimal(len(key) * 0.25 + 1)
                offset_x += Decimal(self.unit_width * unit)
            offset_y += Decimal(self.unit_height)
        return keys

    @abc.abstractproperty
    def schema(self):
        pass

class ANSI(StandardKeyboard):
    def __init__(self):
        super().__init__()

    @property
    def schema(self):
        return """\
-------------------------------------------------------------
|   |   |   |   |   |   |   |   |   |   |   |   |   |       |
-------------------------------------------------------------
|     |   |   |   |   |   |   |   |   |   |   |   |   |     |
-------------------------------------------------------------
|      |   |   |   |   |   |   |   |   |   |   |   |        |
-------------------------------------------------------------
|        |   |   |   |   |   |   |   |   |   |   |          |
-------------------------------------------------------------
|    |    |    |                        |    |    |    |    |
-------------------------------------------------------------"""

class Core33(StandardKeyboard):
    def __init__(self):
        super().__init__()

    @property
    def schema(self):
        return """\
-------------------------------------------------------------
|  x  |   |   |   |   |   |   |   |   |   |   | x | x |  x  |
-------------------------------------------------------------
|   x  |   |   |   |   |   |   |   |   |   | x | x |    x   |
-------------------------------------------------------------
|     x  |   |   |   |   |   |   |   | x | x | x |    x     |
-------------------------------------------------------------"""

class SixKey(StandardKeyboard):
    def __init__(self):
        super().__init__()

    @property
    def schema(self):
        return """\
-------------
|   |   |   |
-------------
|   |   |   |
-------------"""
<|endoftext|>


<commit_before>"""
Extract FEZ .pak files
"""

import sys
import os
import time

from binstream import BinaryReader

def unpack(in_file, out_dir):
    with open(in_file, 'rb') as f:
        d = f.read()
    stream = BinaryReader(d)
    capacity = stream.read('u4')
    for _ in range(capacity):
        filename = os.path.normpath(stream.read('str') + '.xnb')
        filesize = stream.read('u4')
        filedata = stream.pull(filesize)
        print '"%s" : %d' % (filename, filesize)
        filename = os.path.join(out_dir, filename)
        filedir = os.path.dirname(filename)
        if filedir:
            if not os.path.isdir(filedir):
                os.makedirs(filedir)
        with open(filename, 'wb') as out_file:
            out_file.write(filedata)

def main():
    if len(sys.argv) == 3:
        totaltime = time.time()
        unpack(os.path.normpath(sys.argv[1]), os.path.normpath(sys.argv[2]))
        print '> Done in %.2f seconds' % (time.time() - totaltime)
    else:
        print 'fez_unpack.py in.pak out_dir'

if __name__ == '__main__':
    main()
<commit_msg>fiddling with os.path order<commit_after>"""
Extract FEZ .pak files
"""

import sys
import os
import time

from binstream import BinaryReader

def unpack(in_file, out_dir):
    with open(in_file, 'rb') as f:
        d = f.read()
    stream = BinaryReader(d)
    capacity = stream.read('u4')
    for _ in range(capacity):
        filename = stream.read('str')
        filesize = stream.read('u4')
        filedata = stream.pull(filesize)
        print '"%s" : %d' % (filename, filesize)
        filename = os.path.normpath(filename + '.xnb')
        filename = os.path.join(out_dir, filename)
        filedir = os.path.dirname(filename)
        if filedir:
            if not os.path.isdir(filedir):
                os.makedirs(filedir)
        with open(filename, 'wb') as out_file:
            out_file.write(filedata)

def main():
    if len(sys.argv) == 3:
        totaltime = time.time()
        unpack(os.path.normpath(sys.argv[1]), os.path.normpath(sys.argv[2]))
        print '> Done in %.2f seconds' % (time.time() - totaltime)
    else:
        print 'fez_unpack.py in.pak out_dir'

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


<commit_before>#!/usr/bin/python2
"OrderPortal web application server."

from __future__ import print_function, absolute_import

import logging
import os
import sys

import tornado.web
import tornado.ioloop

from orderportal import settings
from orderportal import utils
from orderportal import uimodules
from orderportal.requesthandler import RequestHandler

from orderportal.home import *
from orderportal.admin import *
from orderportal.account import *
from orderportal.group import *
from orderportal.form import *
from orderportal.order import *
from orderportal.news import *
from orderportal.info import *
from orderportal.file import *
from orderportal.event import *
from orderportal.search import *

def main():
    parser = utils.get_command_line_parser(description='OrderPortal server.')
    (options, args) = parser.parse_args()
    utils.load_settings(filepath=options.settings)
    utils.initialize()

    url = tornado.web.url
    handlers = [url(r'/', Home, name='home')]
    try:
        regexp = settings['ORDER_IDENTIFIER_REGEXP']
    except KeyError:
        pass
    else:
        handlers.append(url(r"/order/({0})".format(regexp),
                            Order, name='order_id'))
        handlers.append(url(r"/api/v1/order/({0})".format(regexp),
                            OrderApiV1, name='order_id_api'))

    handlers.extend([
        url(r'/order/([0-9a-f]{32})', Order, name='order'),
        url(r'/api/v1/order/([0-9a-f]{32})', OrderApiV1, name='order_api'),
        url(r'/order/([^/]+).csv', OrderCsv, name='order_csv'),
        url(r'/order/([^/]+).zip', OrderZip, name='order_zip'),
        url(r'/order/([0-9a-f]{32})/logs', OrderLogs, name='order_logs'),
        url(r'/order', OrderCreate, name='order_create'),
        url(r'/api/v1/order', OrderCreateApiV1, name='order_create_api'),
        url(r'/order/([0-9a-f]{32})/edit', OrderEdit, name='order_edit'),
        url(r'/order/([0-9a-f]{32})/transition/(\w+)',
            OrderTransition, name='order_transition'),
        url(r'/api/v1/order/([0-9a-f]{32})/transition/(\w+)',
            OrderTransitionApiV1, name='order_transition_api'),
        url(r'/order/([0-9a-f]{32})/clone', OrderClone, name='order_clone'),
        url(r'/order/([0-9a-f]{32})/file', OrderFile, name='order_file_add'),
        url(r'/order/([0-9a-f]{32})/file/([^/]+)',OrderFile,name='order_file'),
        url(r'/order/([0-9a-f]{32})/report', OrderReport, name='order_report'),
        url(r'/api/v1/order/([0-9a-f]{32})/report',
            OrderReportApiV1, name='order_report_api'),
        url(r'/order/([0-9a-f]{32})/report/edit',
            OrderReportEdit, name='order_report_edit'),
        url(r'/orders', Orders, name='orders'),
        url(r'/api/v1/orders', OrdersApiV1, name='orders_api'),
        url(r'/orders.csv', OrdersCsv, name='orders_csv'),
        url(r'/accounts', Accounts, name='accounts'),
        url(r'/api/v1/accounts', AccountsApiV1, name='accounts_api'),
        url(r'/accounts.csv', AccountsCsv, name='accounts_csv'),
        url(r'/account/([^/]+)', Account, name='account'),
        url(r'/api/v1/account/([^/]+)', AccountApiV1, name='account_api'),
        url(r'/account/([^/]+)/orders', AccountOrders, name='account_orders'),
        url(r'/api/v1/account/([^/]+)/orders',
            AccountOrdersApiV1, name='account_orders_api'),
        url(r'/account/([^/]+)/groups/orders',
            AccountGroupsOrders, name='account_groups_orders'),
        url(r'/api/v1/account/([^/]+)/groups/orders',
            AccountGroupsOrdersApiV1, name='account_groups_orders_api'),
        url(r'/account/([^/]+)/logs', AccountLogs, name='account_logs'),
        url(r'/account/([^/]+)/messages',
            AccountMessages, name='account_messages'),
        url(r'/account/([^/]+)/edit', AccountEdit, name='account_edit'),
        url(r'/group', GroupCreate, name='group_create'),
        url(r'/group/([0-9a-f]{32})', Group, name='group'),
        url(r'/group/([0-9a-f]{32})/edit', GroupEdit, name='group_edit'),
        url(r'/group/([0-9a-f]{32})/accept', GroupAccept, name='group_accept'),
        url(r'/group/([0-9a-f]{32})/decline',
            GroupDecline, name='group_decline'),
        url(r'/group/([0-9a-f]{32})/logs', GroupLogs, name='group_logs'),
        url(r'/groups', Groups, name='groups'),
        url(r'/search', Search, name='search'),
        url(r'/login', Login, name='login'),
        url(r'/logout', Logout, name='logout'),
        url(r'/reset', Reset, name='reset'),
        url(r'/password', Password, name='password'),
        url(r'/register', Register, name='register'),
        url(r'/registered', Registered, name='registered'),
        url(r'/account/([^/]+)/enable', AccountEnable, name='account_enable'),
        url(r'/account/([^/]+)/disable', AccountDisable,name='account_disable'),
        url(r'/account/([^/]+)/updateinfo',
            AccountUpdateInfo, name='account_update_info'),
        url(r'/forms', Forms, name='forms'),
        url(r'/form/([0-9a-f]{32})', Form, name='form'),
        url(r'/api/v1/form/([0-9a-f]{32})', FormApiV1, name='form_api'),
        url(r'/form/([0-9a-f]{32})/logs', FormLogs, name='form_logs'),
        url(r'/form', FormCreate, name='form_create'),
        url(r'/form/([0-9a-f]{32})/edit', FormEdit, name='form_edit'),
        url(r'/form/([0-9a-f]{32})/clone', FormClone, name='form_clone'),
        url(r'/form/([0-9a-f]{32})/pending', FormPending, name='form_pending'),
        url(r'/form/([0-9a-f]{32})/testing', FormTesting, name='form_testing'),
        url(r'/form/([0-9a-f]{32})/enable', FormEnable, name='form_enable'),
        url(r'/form/([0-9a-f]{32})/disable', FormDisable, name='form_disable'),
        url(r'/form/([0-9a-f]{32})/field', FormFieldCreate,name='field_create'),
        url(r'/form/([0-9a-f]{32})/field/([a-zA-Z][_a-zA-Z0-9]*)',
            FormFieldEdit, name='field_edit'),
        url(r'/form/([0-9a-f]{32})/field/([a-zA-Z][_a-zA-Z0-9]*)/descr',
            FormFieldEditDescr, name='field_edit_descr'),
        url(r'/form/([0-9a-f]{32})/orders', FormOrders, name='form_orders'),
        url(r'/form/([0-9a-f]{32})/aggregate',
            FormOrdersAggregate, name='form_orders_aggregate'),
        url(r'/news', News, name='news'),
        url(r'/new/([0-9a-f]{32})', NewsEdit, name='news_edit'),
        url(r'/new', NewsCreate, name='news_create'),
        url(r'/events', Events, name='events'),
        url(r'/event/([0-9a-f]{32})', Event, name='event'),
        url(r'/event', EventCreate, name='event_create'),
        url(r'/contact', Contact, name='contact'),
        url(r'/about', About, name='about'),
        url(r'/software', Software, name='software'),
        url(r'/infos', Infos, name='infos'),
        url(r'/info', InfoCreate, name='info_create'),
        url(r'/info/([^/]+)', Info, name='info'),
        url(r'/info/([^/]+)/edit', InfoEdit, name='info_edit'),
        url(r'/info/([^/]+)/logs', InfoLogs, name='info_logs'),
        url(r'/files', Files, name='files'),
        url(r'/file', FileCreate, name='file_create'),
        url(r'/file/([^/]+)', File, name='file'),
        url(r'/file/([^/]+)/meta', FileMeta, name='file_meta'),
        url(r'/file/([^/]+)/download', FileDownload, name='file_download'),
        url(r'/file/([^/]+)/edit', FileEdit, name='file_edit'),
        url(r'/api/v1/file/([^/]+)/edit', FileEditApiV1, name='file_edit_api'),
        url(r'/file/([0-9a-f]{32})/logs', FileLogs, name='file_logs'),
        url(r'/log/([0-9a-f]{32})', Log, name='log'),
        url(r'/([0-9a-f]{32})', Entity, name='entity'),
        url(r'/admin/global_modes', GlobalModes, name='global_modes'),
        url(r'/admin/settings', Settings, name='settings'),
        url(r'/admin/text/([^/]+)', Text, name='text'),
        url(r'/admin/texts', Texts, name='texts'),
        url(r'/admin/order_statuses', OrderStatuses, name='order_statuses'),
        url(r'/admin/order_messages',
            AdminOrderMessages, name='admin_order_messages'),
        url(r'/admin/account_messages',
            AdminAccountMessages, name='admin_account_messages'),
        url(r'/site/([^/]+)', tornado.web.StaticFileHandler,
            {'path': utils.expand_filepath(settings['SITE_DIR'])},
            name='site'),
        ])
    handlers.append(url(r'/api/v1/(.*)', NoSuchEntityApiV1))
    handlers.append(url(r'/(.*)', NoSuchEntity))
    application = tornado.web.Application(
        handlers=handlers,
        debug=settings.get('TORNADO_DEBUG', False),
        cookie_secret=settings['COOKIE_SECRET'],
        xsrf_cookies=True,
        ui_modules=uimodules,
        template_path=os.path.join(settings['ROOT_DIR'], 'html'),
        static_path=os.path.join(settings['ROOT_DIR'], 'static'),
        login_url=r'/login')
    # Add href URLs for the status icons.
    # This depends on order status setup.
    for key, value in settings['ORDER_STATUSES_LOOKUP'].iteritems():
        value['href'] = application.reverse_url('site', key + '.png')
    application.listen(settings['PORT'], xheaders=True)
    pid = os.getpid()
    logging.info("web server %s (PID %s)", settings['BASE_URL'], pid)
    if options.pidfile:
        with open(options.pidfile, 'w') as pf:
            pf.write(str(pid))
    tornado.ioloop.IOLoop.instance().start()

if __name__ == "__main__":
    main()
<commit_msg>Changed hash-bang.<commit_after>#!/usr/bin/env python2
"OrderPortal web application server."

from __future__ import print_function, absolute_import

import logging
import os
import sys

import tornado.web
import tornado.ioloop

from orderportal import settings
from orderportal import utils
from orderportal import uimodules
from orderportal.requesthandler import RequestHandler

from orderportal.home import *
from orderportal.admin import *
from orderportal.account import *
from orderportal.group import *
from orderportal.form import *
from orderportal.order import *
from orderportal.news import *
from orderportal.info import *
from orderportal.file import *
from orderportal.event import *
from orderportal.search import *

def main():
    parser = utils.get_command_line_parser(description='OrderPortal server.')
    (options, args) = parser.parse_args()
    utils.load_settings(filepath=options.settings)
    utils.initialize()

    url = tornado.web.url
    handlers = [url(r'/', Home, name='home')]
    try:
        regexp = settings['ORDER_IDENTIFIER_REGEXP']
    except KeyError:
        pass
    else:
        handlers.append(url(r"/order/({0})".format(regexp),
                            Order, name='order_id'))
        handlers.append(url(r"/api/v1/order/({0})".format(regexp),
                            OrderApiV1, name='order_id_api'))

    handlers.extend([
        url(r'/order/([0-9a-f]{32})', Order, name='order'),
        url(r'/api/v1/order/([0-9a-f]{32})', OrderApiV1, name='order_api'),
        url(r'/order/([^/]+).csv', OrderCsv, name='order_csv'),
        url(r'/order/([^/]+).zip', OrderZip, name='order_zip'),
        url(r'/order/([0-9a-f]{32})/logs', OrderLogs, name='order_logs'),
        url(r'/order', OrderCreate, name='order_create'),
        url(r'/api/v1/order', OrderCreateApiV1, name='order_create_api'),
        url(r'/order/([0-9a-f]{32})/edit', OrderEdit, name='order_edit'),
        url(r'/order/([0-9a-f]{32})/transition/(\w+)',
            OrderTransition, name='order_transition'),
        url(r'/api/v1/order/([0-9a-f]{32})/transition/(\w+)',
            OrderTransitionApiV1, name='order_transition_api'),
        url(r'/order/([0-9a-f]{32})/clone', OrderClone, name='order_clone'),
        url(r'/order/([0-9a-f]{32})/file', OrderFile, name='order_file_add'),
        url(r'/order/([0-9a-f]{32})/file/([^/]+)',OrderFile,name='order_file'),
        url(r'/order/([0-9a-f]{32})/report', OrderReport, name='order_report'),
        url(r'/api/v1/order/([0-9a-f]{32})/report',
            OrderReportApiV1, name='order_report_api'),
        url(r'/order/([0-9a-f]{32})/report/edit',
            OrderReportEdit, name='order_report_edit'),
        url(r'/orders', Orders, name='orders'),
        url(r'/api/v1/orders', OrdersApiV1, name='orders_api'),
        url(r'/orders.csv', OrdersCsv, name='orders_csv'),
        url(r'/accounts', Accounts, name='accounts'),
        url(r'/api/v1/accounts', AccountsApiV1, name='accounts_api'),
        url(r'/accounts.csv', AccountsCsv, name='accounts_csv'),
        url(r'/account/([^/]+)', Account, name='account'),
        url(r'/api/v1/account/([^/]+)', AccountApiV1, name='account_api'),
        url(r'/account/([^/]+)/orders', AccountOrders, name='account_orders'),
        url(r'/api/v1/account/([^/]+)/orders',
            AccountOrdersApiV1, name='account_orders_api'),
        url(r'/account/([^/]+)/groups/orders',
            AccountGroupsOrders, name='account_groups_orders'),
        url(r'/api/v1/account/([^/]+)/groups/orders',
            AccountGroupsOrdersApiV1, name='account_groups_orders_api'),
        url(r'/account/([^/]+)/logs', AccountLogs, name='account_logs'),
        url(r'/account/([^/]+)/messages',
            AccountMessages, name='account_messages'),
        url(r'/account/([^/]+)/edit', AccountEdit, name='account_edit'),
        url(r'/group', GroupCreate, name='group_create'),
        url(r'/group/([0-9a-f]{32})', Group, name='group'),
        url(r'/group/([0-9a-f]{32})/edit', GroupEdit, name='group_edit'),
        url(r'/group/([0-9a-f]{32})/accept', GroupAccept, name='group_accept'),
        url(r'/group/([0-9a-f]{32})/decline',
            GroupDecline, name='group_decline'),
        url(r'/group/([0-9a-f]{32})/logs', GroupLogs, name='group_logs'),
        url(r'/groups', Groups, name='groups'),
        url(r'/search', Search, name='search'),
        url(r'/login', Login, name='login'),
        url(r'/logout', Logout, name='logout'),
        url(r'/reset', Reset, name='reset'),
        url(r'/password', Password, name='password'),
        url(r'/register', Register, name='register'),
        url(r'/registered', Registered, name='registered'),
        url(r'/account/([^/]+)/enable', AccountEnable, name='account_enable'),
        url(r'/account/([^/]+)/disable', AccountDisable,name='account_disable'),
        url(r'/account/([^/]+)/updateinfo',
            AccountUpdateInfo, name='account_update_info'),
        url(r'/forms', Forms, name='forms'),
        url(r'/form/([0-9a-f]{32})', Form, name='form'),
        url(r'/api/v1/form/([0-9a-f]{32})', FormApiV1, name='form_api'),
        url(r'/form/([0-9a-f]{32})/logs', FormLogs, name='form_logs'),
        url(r'/form', FormCreate, name='form_create'),
        url(r'/form/([0-9a-f]{32})/edit', FormEdit, name='form_edit'),
        url(r'/form/([0-9a-f]{32})/clone', FormClone, name='form_clone'),
        url(r'/form/([0-9a-f]{32})/pending', FormPending, name='form_pending'),
        url(r'/form/([0-9a-f]{32})/testing', FormTesting, name='form_testing'),
        url(r'/form/([0-9a-f]{32})/enable', FormEnable, name='form_enable'),
        url(r'/form/([0-9a-f]{32})/disable', FormDisable, name='form_disable'),
        url(r'/form/([0-9a-f]{32})/field', FormFieldCreate,name='field_create'),
        url(r'/form/([0-9a-f]{32})/field/([a-zA-Z][_a-zA-Z0-9]*)',
            FormFieldEdit, name='field_edit'),
        url(r'/form/([0-9a-f]{32})/field/([a-zA-Z][_a-zA-Z0-9]*)/descr',
            FormFieldEditDescr, name='field_edit_descr'),
        url(r'/form/([0-9a-f]{32})/orders', FormOrders, name='form_orders'),
        url(r'/form/([0-9a-f]{32})/aggregate',
            FormOrdersAggregate, name='form_orders_aggregate'),
        url(r'/news', News, name='news'),
        url(r'/new/([0-9a-f]{32})', NewsEdit, name='news_edit'),
        url(r'/new', NewsCreate, name='news_create'),
        url(r'/events', Events, name='events'),
        url(r'/event/([0-9a-f]{32})', Event, name='event'),
        url(r'/event', EventCreate, name='event_create'),
        url(r'/contact', Contact, name='contact'),
        url(r'/about', About, name='about'),
        url(r'/software', Software, name='software'),
        url(r'/infos', Infos, name='infos'),
        url(r'/info', InfoCreate, name='info_create'),
        url(r'/info/([^/]+)', Info, name='info'),
        url(r'/info/([^/]+)/edit', InfoEdit, name='info_edit'),
        url(r'/info/([^/]+)/logs', InfoLogs, name='info_logs'),
        url(r'/files', Files, name='files'),
        url(r'/file', FileCreate, name='file_create'),
        url(r'/file/([^/]+)', File, name='file'),
        url(r'/file/([^/]+)/meta', FileMeta, name='file_meta'),
        url(r'/file/([^/]+)/download', FileDownload, name='file_download'),
        url(r'/file/([^/]+)/edit', FileEdit, name='file_edit'),
        url(r'/api/v1/file/([^/]+)/edit', FileEditApiV1, name='file_edit_api'),
        url(r'/file/([0-9a-f]{32})/logs', FileLogs, name='file_logs'),
        url(r'/log/([0-9a-f]{32})', Log, name='log'),
        url(r'/([0-9a-f]{32})', Entity, name='entity'),
        url(r'/admin/global_modes', GlobalModes, name='global_modes'),
        url(r'/admin/settings', Settings, name='settings'),
        url(r'/admin/text/([^/]+)', Text, name='text'),
        url(r'/admin/texts', Texts, name='texts'),
        url(r'/admin/order_statuses', OrderStatuses, name='order_statuses'),
        url(r'/admin/order_messages',
            AdminOrderMessages, name='admin_order_messages'),
        url(r'/admin/account_messages',
            AdminAccountMessages, name='admin_account_messages'),
        url(r'/site/([^/]+)', tornado.web.StaticFileHandler,
            {'path': utils.expand_filepath(settings['SITE_DIR'])},
            name='site'),
        ])
    handlers.append(url(r'/api/v1/(.*)', NoSuchEntityApiV1))
    handlers.append(url(r'/(.*)', NoSuchEntity))
    application = tornado.web.Application(
        handlers=handlers,
        debug=settings.get('TORNADO_DEBUG', False),
        cookie_secret=settings['COOKIE_SECRET'],
        xsrf_cookies=True,
        ui_modules=uimodules,
        template_path=os.path.join(settings['ROOT_DIR'], 'html'),
        static_path=os.path.join(settings['ROOT_DIR'], 'static'),
        login_url=r'/login')
    # Add href URLs for the status icons.
    # This depends on order status setup.
    for key, value in settings['ORDER_STATUSES_LOOKUP'].iteritems():
        value['href'] = application.reverse_url('site', key + '.png')
    application.listen(settings['PORT'], xheaders=True)
    pid = os.getpid()
    logging.info("web server %s (PID %s)", settings['BASE_URL'], pid)
    if options.pidfile:
        with open(options.pidfile, 'w') as pf:
            pf.write(str(pid))
    tornado.ioloop.IOLoop.instance().start()

if __name__ == "__main__":
    main()
<|endoftext|>


<commit_before># This file is part of IoT Partner Integration kit software (a set of tools for FIWARE Orion ContextBroker and IDAS2.6).
#
# IoT Partner Integration kit is free software: you can redistribute it and/or modify it under the terms of the GNU
# Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# IoT Partner Integration kit is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
# even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License along with IoT Partner Integration kit.
# If not, see http://www.gnu.org/licenses/
#
# For those usages not covered by the GNU Affero General Public License please contact with iot_support@tid.es
#
# Developed by @IndustrialIoT Team (mail:iot_support@tid.es)

import webapp2
import json
import urllib2
import yaml
from paste import httpserver
import uuid
import datetime
import unicodedata
import string

#print Logs
def print_log(message,lvl):
    d = datetime.datetime.now()
    ref=uuid.uuid4()
    log=str("time="+str(d.isoformat("T"))+"|lvl="+lvl+"|corr="+str(ref)+"|trans="+str(ref)+"|ob=ES|comp=ORION_TO_CARTODB|op="+message)
    print(log)

#Normalize strings
def string_normalizer(message):

    # Convert to unicode format
    message = message.decode()

    # Lower-case
    message=message.lower()

    # Replace some characters
    message=message.replace('.','_')
    message=message.replace(' ','_')

    # Get NFKD unicode format
    message=unicodedata.normalize('NFKD', message)

    # Delete not ascii_letters
    message=''.join(x for x in message if x in string.ascii_letters or x=="_" or x.isdigit())
    return message

# Load properties
print_log("Loading properties from orion2cartodb.yaml","INFO")
file = open("orion2cartodb.yaml")
properties = yaml.load(file)
print_log("Loaded","INFO")

# Class for communications
class DefaultHandler(webapp2.RequestHandler):

    #Send Info to CartoDB
    def send2CartoDB(self, url):
        print_log("Sending '"+str(url)+"' to CartoDB...","INFO")

        # Initializations
        error=False
        total_rows=0

        try:
            # Send data
            req = urllib2.Request(url)
            f = urllib2.urlopen(req)

            # Get response
            response=f.read()
            resp=json.loads(str(response))

            print_log("Response: '"+str(resp)+ "'","INFO")

            # If there is an error -> Error Control
            if "error" in resp:
                error=True

            # Get rows updated
            if "total_rows" in resp:
                total_rows=int(resp["total_rows"])
            f.close()

            print_log("Sent to CartoDB","INFO")

        # If it is not possible to send the data -> Error Control
        except:
            print_log("An error occurred while trying to send info to CartoDB","WARNING")
            error=True

        # Return number of ROWs updated and if there was an error
        return error, total_rows

    # Update ROW
    def Update(self,tablename, entity_name, attributes):

        print_log("Updating attributes '" + str(attributes)+"'","INFO")

        # Get Attributes and concatenate them
        attributes_values=""
        for key in attributes.keys():

            # If it is not a position attribute concatenate it
            if key!="position":
                attributes_values=attributes_values+str(key)+"=%20'"+str(attributes[key])+"',"

            # If it is a position attribute split and concatenate it
            else:
                position=str(attributes[key]).split(',')
                latitude=position[0]
                longitude=position[1]
                attributes_values=attributes_values+"the_geom=ST_SetSRID(ST_Point("+str(longitude)+","+str(latitude)+"),4326)"+","

        # URL for updating attributes
        url=str(properties["cartodb_base_endpoint"]) + "/api/v2/sql?q="+"UPDATE%20" + tablename + "%20SET%20"+ attributes_values[:-1] +"%20WHERE%20name='" + entity_name + "'%20&api_key=" + properties["cartodb_apikey"]

        # Update attributes
        error, total_rows=self.send2CartoDB(url)

        if error==False:
            print_log("Updated","INFO")
        else:
            print_log("Attributes could not be updated","WARNING")

        # Return if it was possible to update and the number of ROWs updated
        return error,total_rows

    # Create new table and/or new ROW
    def create_table(self, name, entity_name,attributes, types):

        print_log("Creating table '" + str(name)+"' ...","INFO")

        #Initialization
        error=False
        attributes2create="name%20varchar,"     #String with new attributes and their types
        keys="name,"                            #String with new attributes
        values="'"+entity_name+"',"             #String with the values

        # Loop for attributes
        for key in types.keys():

            # If attribute type is not position (Position is automatically created)
            if key!="position":

                # Concatenate attribute names
                keys=keys+str(key)+","

                # If attribute type is Quantity indicate it to CartoDB
                if types[key]=="Quantity":

                    # Concatenate attribute and its type
                    attributes2create=attributes2create+str(key)+"%20float,"

                    # Concatenate value
                    values=values+attributes[key]+","

                # If attribute type is Boolean indicate it to CartoDB
                elif types[key]=="Boolean":

                    # Concatenate attribute and its type
                    attributes2create=attributes2create+str(key)+"%20boolean,"

                    # Concatenate value
                    values=values+attributes[key]+","

                # If attribute type is not Quantity or Boolean, It is string
                else:

                    # Concatenate attribute and its type
                    attributes2create=attributes2create+str(key)+"%20varchar,"

                    # Concatenate value
                    values=values+"'"+attributes[key]+"'"+","

        # URL to create table
        url = str(properties["cartodb_base_endpoint"]) + "/api/v2/sql?q=CREATE%20TABLE%20"+name+"("+attributes2create[:-1]+")"+"%20&api_key=" + properties["cartodb_apikey"]

        # Create table
        error,total_rows=self.send2CartoDB(url)

        # If table is created
        if error==False:

            print_log("Displaying table '" + str(name)+"'","INFO")
            # URL to display it in the interface
            url = str(properties["cartodb_base_endpoint"]) + "/api/v2/sql?q=SELECT%20cdb_cartodbfytable('"+name+"')"+"&api_key="+properties["cartodb_apikey"]

            # Send it to CartoDB
            error,total_rows=self.send2CartoDB(url)

            if error==True:
                print_log("Table '" + str(name)+ "' could not be displayed","WARNING")
            else:
                print_log("Table '" + str(name)+ "' displayed","INFO")

        else:
            print_log("Table '" + str(name)+"' could not be created","WARNING")

        print_log("Creating ROW " + str(entity_name)+" ...","INFO")

        # URL to create a new ROW
        url = str(properties["cartodb_base_endpoint"]) + "/api/v2/sql?q=INSERT%20INTO%20" + name + "%20("+keys[:-1]+")%20VALUES("+values[:-1]+")%20&api_key=" + properties["cartodb_apikey"]

        # Create new ROW
        error,total_rows=self.send2CartoDB(url)

        if error==False:
            print_log("Created ROW '" + str(entity_name)+"'","INFO")
        else:
            print_log("ROW '" + str(entity_name)+"' could not be created","WARNING")

        # Return if it was possible to create table or ROW
        return error

    # Create new attributes in CartoDB
    def create_attributes(self, tablename, entity_name, attributes, types):
        print_log("Creating attributes '"+str(attributes)+"'","INFO")

        # Initializations
        error=False
        cont=0

        # Loop for attributes
        for key in attributes.keys():

            # Strings with attribute name + attribute type
            attribute2create=""

            # If attribute type is not position (Position has not to be manually created)
            if key!="position":

                # If attribute type is Quantity  indicate it
                if types[key]=="Quantity":
                    attribute2create=str(key)+"%20float"

                # If attribute type is Boolean  indicate it
                elif types[key]=="Boolean":
                    attribute2create=str(key)+"%20boolean"

                # If attribute is not Quantity or Boolean it is string
                else:
                    attribute2create=str(key)+"%20varchar"

            # URL to create new attribute
            url = str(properties["cartodb_base_endpoint"]) + "/api/v2/sql?q=ALTER%20TABLE%20IF%20EXISTS%20"+tablename+"%20ADD%20"+attribute2create+"%20&api_key=" + properties["cartodb_apikey"]

            # Create new attribute
            error,total_rows=self.send2CartoDB(url)

            # If attribute has been created count it
            if error==False:
                print_log("Created attribute '"+str(key)+"'","INFO")
                cont=cont+1
            else:
                print_log("Attribute "+str(key)+"' could not be created","WARNING")

         # Return number of attributes created
        return cont

    def post(self):
        # Get URL path
        path = self.request.path

        #Get JSON Data
        data = json.loads(self.request.body)

        #Get Fiware-Service header = Table name
        tablename=str(self.request.headers.get('Fiware-Service'))

        #Loop for entities
        for entity_id in data["contextResponses"]:

            # Get entity name (replace '.' and ' ' and lower-case)
            entity_name=string_normalizer(entity_id["contextElement"]["id"])

            # Loop for attributes and their types to append them into a dictionary
            attributes={}       #Initialization
            types={}            #Initialization
            for attritube_id in entity_id['contextElement']['attributes']:

                # Append
                attributes[str(attritube_id["name"])]=str(attritube_id["value"])
                types[str(attritube_id["name"])]=string_normalizer(str(attritube_id["type"]))

            # Try to update the attributes
            error,total_rows=self.Update(tablename,entity_name,attributes)

            # If there is an error -> Table is not created or ROW is not created or there are new attributes
            if error==True or total_rows==0:

                # Create table and/or ROW
                error=self.create_table(tablename, entity_name,attributes,types)

                # If it's not possible to create table and/or ROW -> Table and ROW are created but there are new attributes
                if error==True:

                    # Create new attributes in CartoDB
                    total_rows=self.create_attributes(tablename, entity_name, attributes, types)

                    print_log("Created "+str(total_rows)+" rows","INFO")

                # Try to Update attributes again
                error,total_rows=self.Update(tablename,entity_name,attributes)

                print_log("Updated "+str(total_rows)+" rows","INFO")
            else:
                print_log("Updated "+str(total_rows)+" rows","INFO")

def main():
    application = webapp2.WSGIApplication([
                                          (r'/.*', DefaultHandler)
                                      ], debug=True)

    httpserver.serve(application, host=properties["orion2cartodb_host"], port=properties["orion2cartodb_port"])

if __name__ == '__main__':
    main()
<commit_msg>Normalize tablename<commit_after># This file is part of IoT Partner Integration kit software (a set of tools for FIWARE Orion ContextBroker and IDAS2.6).
#
# IoT Partner Integration kit is free software: you can redistribute it and/or modify it under the terms of the GNU
# Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# IoT Partner Integration kit is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
# even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License along with IoT Partner Integration kit.
# If not, see http://www.gnu.org/licenses/
#
# For those usages not covered by the GNU Affero General Public License please contact with iot_support@tid.es
#
# Developed by @IndustrialIoT Team (mail:iot_support@tid.es)

import webapp2
import json
import urllib2
import yaml
from paste import httpserver
import uuid
import datetime
import unicodedata
import string

#print Logs
def print_log(message,lvl):
    d = datetime.datetime.now()
    ref=uuid.uuid4()
    log=str("time="+str(d.isoformat("T"))+"|lvl="+lvl+"|corr="+str(ref)+"|trans="+str(ref)+"|ob=ES|comp=ORION_TO_CARTODB|op="+message)
    print(log)

#Normalize strings
def string_normalizer(message):

    # Convert to unicode format
    message = message.decode()

    # Lower-case
    message=message.lower()

    # Replace some characters
    message=message.replace('.','_')
    message=message.replace(' ','_')

    # Get NFKD unicode format
    message=unicodedata.normalize('NFKD', message)

    # Delete not ascii_letters
    message=''.join(x for x in message if x in string.ascii_letters or x=="_" or x.isdigit())
    return message

# Load properties
print_log("Loading properties from orion2cartodb.yaml","INFO")
file = open("orion2cartodb.yaml")
properties = yaml.load(file)
print_log("Loaded","INFO")

# Class for communications
class DefaultHandler(webapp2.RequestHandler):

    #Send Info to CartoDB
    def send2CartoDB(self, url):
        print_log("Sending '"+str(url)+"' to CartoDB...","INFO")

        # Initializations
        error=False
        total_rows=0

        try:
            # Send data
            req = urllib2.Request(url)
            f = urllib2.urlopen(req)

            # Get response
            response=f.read()
            resp=json.loads(str(response))

            print_log("Response: '"+str(resp)+ "'","INFO")

            # If there is an error -> Error Control
            if "error" in resp:
                error=True

            # Get rows updated
            if "total_rows" in resp:
                total_rows=int(resp["total_rows"])
            f.close()

            print_log("Sent to CartoDB","INFO")

        # If it is not possible to send the data -> Error Control
        except:
            print_log("An error occurred while trying to send info to CartoDB","WARNING")
            error=True

        # Return number of ROWs updated and if there was an error
        return error, total_rows

    # Update ROW
    def Update(self,tablename, entity_name, attributes):

        print_log("Updating attributes '" + str(attributes)+"'","INFO")

        # Get Attributes and concatenate them
        attributes_values=""
        for key in attributes.keys():

            # If it is not a position attribute concatenate it
            if key!="position":
                attributes_values=attributes_values+str(key)+"=%20'"+str(attributes[key])+"',"

            # If it is a position attribute split and concatenate it
            else:
                position=str(attributes[key]).split(',')
                latitude=position[0]
                longitude=position[1]
                attributes_values=attributes_values+"the_geom=ST_SetSRID(ST_Point("+str(longitude)+","+str(latitude)+"),4326)"+","

        # URL for updating attributes
        url=str(properties["cartodb_base_endpoint"]) + "/api/v2/sql?q="+"UPDATE%20" + tablename + "%20SET%20"+ attributes_values[:-1] +"%20WHERE%20name='" + entity_name + "'%20&api_key=" + properties["cartodb_apikey"]

        # Update attributes
        error, total_rows=self.send2CartoDB(url)

        if error==False:
            print_log("Updated","INFO")
        else:
            print_log("Attributes could not be updated","WARNING")

        # Return if it was possible to update and the number of ROWs updated
        return error,total_rows

    # Create new table and/or new ROW
    def create_table(self, name, entity_name,attributes, types):

        print_log("Creating table '" + str(name)+"' ...","INFO")

        #Initialization
        error=False
        attributes2create="name%20varchar,"     #String with new attributes and their types
        keys="name,"                            #String with new attributes
        values="'"+entity_name+"',"             #String with the values

        # Loop for attributes
        for key in types.keys():

            # If attribute type is not position (Position is automatically created)
            if key!="position":

                # Concatenate attribute names
                keys=keys+str(key)+","

                # If attribute type is Quantity indicate it to CartoDB
                if types[key]=="Quantity":

                    # Concatenate attribute and its type
                    attributes2create=attributes2create+str(key)+"%20float,"

                    # Concatenate value
                    values=values+attributes[key]+","

                # If attribute type is Boolean indicate it to CartoDB
                elif types[key]=="Boolean":

                    # Concatenate attribute and its type
                    attributes2create=attributes2create+str(key)+"%20boolean,"

                    # Concatenate value
                    values=values+attributes[key]+","

                # If attribute type is not Quantity or Boolean, It is string
                else:

                    # Concatenate attribute and its type
                    attributes2create=attributes2create+str(key)+"%20varchar,"

                    # Concatenate value
                    values=values+"'"+attributes[key]+"'"+","

        # URL to create table
        url = str(properties["cartodb_base_endpoint"]) + "/api/v2/sql?q=CREATE%20TABLE%20"+name+"("+attributes2create[:-1]+")"+"%20&api_key=" + properties["cartodb_apikey"]

        # Create table
        error,total_rows=self.send2CartoDB(url)

        # If table is created
        if error==False:

            print_log("Displaying table '" + str(name)+"'","INFO")
            # URL to display it in the interface
            url = str(properties["cartodb_base_endpoint"]) + "/api/v2/sql?q=SELECT%20cdb_cartodbfytable('"+name+"')"+"&api_key="+properties["cartodb_apikey"]

            # Send it to CartoDB
            error,total_rows=self.send2CartoDB(url)

            if error==True:
                print_log("Table '" + str(name)+ "' could not be displayed","WARNING")
            else:
                print_log("Table '" + str(name)+ "' displayed","INFO")

        else:
            print_log("Table '" + str(name)+"' could not be created","WARNING")

        print_log("Creating ROW " + str(entity_name)+" ...","INFO")

        # URL to create a new ROW
        url = str(properties["cartodb_base_endpoint"]) + "/api/v2/sql?q=INSERT%20INTO%20" + name + "%20("+keys[:-1]+")%20VALUES("+values[:-1]+")%20&api_key=" + properties["cartodb_apikey"]

        # Create new ROW
        error,total_rows=self.send2CartoDB(url)

        if error==False:
            print_log("Created ROW '" + str(entity_name)+"'","INFO")
        else:
            print_log("ROW '" + str(entity_name)+"' could not be created","WARNING")

        # Return if it was possible to create table or ROW
        return error

    # Create new attributes in CartoDB
    def create_attributes(self, tablename, entity_name, attributes, types):
        print_log("Creating attributes '"+str(attributes)+"'","INFO")

        # Initializations
        error=False
        cont=0

        # Loop for attributes
        for key in attributes.keys():

            # Strings with attribute name + attribute type
            attribute2create=""

            # If attribute type is not position (Position has not to be manually created)
            if key!="position":

                # If attribute type is Quantity  indicate it
                if types[key]=="Quantity":
                    attribute2create=str(key)+"%20float"

                # If attribute type is Boolean  indicate it
                elif types[key]=="Boolean":
                    attribute2create=str(key)+"%20boolean"

                # If attribute is not Quantity or Boolean it is string
                else:
                    attribute2create=str(key)+"%20varchar"

            # URL to create new attribute
            url = str(properties["cartodb_base_endpoint"]) + "/api/v2/sql?q=ALTER%20TABLE%20IF%20EXISTS%20"+tablename+"%20ADD%20"+attribute2create+"%20&api_key=" + properties["cartodb_apikey"]

            # Create new attribute
            error,total_rows=self.send2CartoDB(url)

            # If attribute has been created count it
            if error==False:
                print_log("Created attribute '"+str(key)+"'","INFO")
                cont=cont+1
            else:
                print_log("Attribute "+str(key)+"' could not be created","WARNING")

         # Return number of attributes created
        return cont

    def post(self):
        # Get URL path
        path = self.request.path

        #Get JSON Data
        data = json.loads(self.request.body)

        #Get Fiware-Service header = Table name
        tablename=string_normalizer(str(self.request.headers.get('Fiware-Service')))

        #Loop for entities
        for entity_id in data["contextResponses"]:

            # Get entity name (replace '.' and ' ' and lower-case)
            entity_name=string_normalizer(entity_id["contextElement"]["id"])

            # Loop for attributes and their types to append them into a dictionary
            attributes={}       #Initialization
            types={}            #Initialization
            for attritube_id in entity_id['contextElement']['attributes']:

                # Append
                attributes[str(attritube_id["name"])]=str(attritube_id["value"])
                types[str(attritube_id["name"])]=string_normalizer(str(attritube_id["type"]))

            # Try to update the attributes
            error,total_rows=self.Update(tablename,entity_name,attributes)

            # If there is an error -> Table is not created or ROW is not created or there are new attributes
            if error==True or total_rows==0:

                # Create table and/or ROW
                error=self.create_table(tablename, entity_name,attributes,types)

                # If it's not possible to create table and/or ROW -> Table and ROW are created but there are new attributes
                if error==True:

                    # Create new attributes in CartoDB
                    total_rows=self.create_attributes(tablename, entity_name, attributes, types)

                    print_log("Created "+str(total_rows)+" rows","INFO")

                # Try to Update attributes again
                error,total_rows=self.Update(tablename,entity_name,attributes)

                print_log("Updated "+str(total_rows)+" rows","INFO")
            else:
                print_log("Updated "+str(total_rows)+" rows","INFO")

def main():
    application = webapp2.WSGIApplication([
                                          (r'/.*', DefaultHandler)
                                      ], debug=True)

    httpserver.serve(application, host=properties["orion2cartodb_host"], port=properties["orion2cartodb_port"])

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