<commit_before>"""
Road network formation
======================

"""
<commit_msg>Implement the network module<commit_after>"""
Road network formation
======================

The primary purpose of this model is to abstract a road connectivity network
from the complicated OSM raw GIS data. The network is going to be stored as a
NetworkX graph.

The nodes are going to be just the traffic junctions and the dead ends of the
road traffic system. And each node has the original id in the raw OSM data as
their identity, and the coordinate stored in the attribute ``coord``.

Each edge is going to be an undirected edge connecting the nodes. They all have
got the attribute of ``name`` for the name of the road, and the attribute of
``travel_time`` for the time needed to traverse the edge by a common traveller.

"""

import networkx as nx
from geopy.distance import vincenty

#
# Constants controlling the bahaviour of the code
# -----------------------------------------------
#

# if the ``highway`` key contains the follow value for a node in raw OSM, then
# it is considered a node in the network.
_NODES_TAGS = [
    'traffic_signals',
    'crossing',
    'turning_circle',
    'motorway_junction',
    ]

# The speed to travel on each kind of highways
# In miles per hour
_HIGHWAY_SPEEDS = {
    'residential': 20.0,
    'primary': 40.0,
    'primary_link': 40.0,
    'secondary': 35.0,
    'tertiary': 30.0,
    'footway': 35.0,
    'service': 35.0,
    'motorway': 70.0,
}

#
# Utility functions
# -----------------
#

def _test_if_node(node):

    """Tests if a node in the raw OSM data a node in the network"""

    tags = node.tags
    return 'highway' in tags and tags['highway'] in _NODES_TAGS

def _calc_distance(coord1, coord2):

    """Calculates the distance between two points

    A shallow wrapper of the geopy Vicinty distance calculator, returns the
    distance in miles.

    """

    return vincenty(coord1, coord2).miles

#
# The driver function
# -------------------
#

def form_network_from_osm(raw_osm):

    """Forms a road network from the raw OSM data

    :param raw_osm: A :py:class:`readosm.RawOSM` instance for the raw data
    :returns: A networkX graph for the road connectivity

    """

    net = nx.Graph()

    # nodes formation
    nodes = raw_osm.nodes
    for node_id, node in nodes.iteritems():
        if _test_if_node(node):
            net.add_node(node_id)
            net.node[node_id]['coord'] = node.coord
        continue

    # edge formation
    for way in raw_osm.ways.itervalues():

        # test if it is actually a road
        tags = way.tags
        if 'highway' in tags:
            highway = tags['highway']
        else:
            continue  # building or something like that

        # connect the nodes in the network

        prev_node_id = None  # The previous node in the network
        # The coordinate of the previous raw node in the OSM data
        prev_coord = way.nodes[0].coord
        distance = 0.0

        for node_id in way.nodes:
            node = nodes[node_id]

            # Update the distance
            curr_coord = node.coord
            distance += _calc_distance(curr_coord, prev_coord)
            prev_coord = curr_coord

            if _test_if_node(node):
                # add edge if there is a previous node
                if prev_node_id is not None:
                    # Add the new edge
                    try:
                        travel_time = distance / _HIGHWAY_SPEEDS[highway]
                    except IndexError:
                        raise IndexError(
                            'Unknown highway type %s' % highway
                            )
                    net.add_edge(
                        node_id, prev_node_id,
                        travel_time=travel_time,
                        name=tags.get('name', '')
                        )
                # Update previous node no matter there is a previous one
                prev_node_id = node_id
                distance = 0.0

    return net
<|endoftext|>


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

"""Test general health of the fonts."""

import unittest

from robofab.world import OpenFont
from nototools.unittests import font_tests

import roboto_data

FONTS = font_tests.load_fonts(
    ['out/RobotoTTF/*.ttf', 'out/RobotoCondensedTTF/*.ttf'],
    expected_count=18)

UFOS = font_tests.load_fonts(
    ['out/RobotoUFO/*.ufo', 'out/RobotoCondensedUFO/*.ufo'],
    expected_count=18,
    font_class=OpenFont)

UFO_MASTERS = font_tests.load_fonts(
    ['src/v2/*.ufo'],
    expected_count=3,
    font_class=OpenFont)

class TestItalicAngle(font_tests.TestItalicAngle):
    loaded_fonts = FONTS
    expected_italic_angle = -12.0

class TestMetaInfo(font_tests.TestMetaInfo):
    """Bugs:
    https://github.com/google/roboto/issues/142
    https://code.google.com/a/google.com/p/roboto/issues/detail?id=8
    https://code.google.com/a/google.com/p/roboto/issues/detail?id=29
    """

    loaded_fonts = FONTS
    mark_heavier_as_bold = False
    test_us_weight = None

    #expected_version = '2.' + roboto_data.get_build_number()
    test_version_numbers = None

    # fsType of 0 marks the font free for installation, embedding, etc.
    expected_os2_fsType = 0
    expected_os2_achVendID = 'GOOG'

class TestNames(font_tests.TestNames):
    """Bugs:
    https://github.com/google/roboto/issues/37
    """

    loaded_fonts = FONTS
    family_name = 'Roboto'
    mark_heavier_as_bold = False
    expected_copyright = 'Font data copyright Google 2015'

    def expected_unique_id(self, family, style):
        return 'Google:%s:2015' % family

class TestDigitWidths(font_tests.TestDigitWidths):
    loaded_fonts = FONTS

class TestCharacterCoverage(font_tests.TestCharacterCoverage):
    loaded_fonts = FONTS

    include = frozenset([
        0x2117,  # SOUND RECORDING COPYRIGHT
        0xEE01, 0xEE02, 0xF6C3])  # legacy PUA

    exclude = frozenset([
        0x2072, 0x2073, 0x208F] +  # unassigned characters
        range(0xE000, 0xF8FF + 1) + range(0xF0000, 0x10FFFF + 1)  # other PUA
        ) - include  # don't exclude legacy PUA

class TestLigatures(font_tests.TestLigatures):
    loaded_fonts = FONTS

class TestFeatures(font_tests.TestFeatures):
    loaded_fonts = FONTS

class TestVerticalMetrics(font_tests.TestVerticalMetrics):
    loaded_fonts = FONTS
    test_ymin_ymax = None
    test_hhea_table_metrics = None
    test_os2_metrics = None

    expected_head_yMin = -555
    expected_head_yMax = 2163

class TestGlyphAreas(font_tests.TestGlyphAreas):
    master_weights_to_test = ['Thin', 'Bold']
    instance_weights_to_test = ['Thin', 'Regular', 'Bold']
    exclude = ['Condensed', 'Italic']

    master_glyph_sets = [
        f.replace('_', '-') for f in UFO_MASTERS[0]], UFO_MASTERS[1]
    instance_glyph_sets = FONTS[0], [f.getGlyphSet() for f in FONTS[1]]

    master_glyphs_to_test = UFO_MASTERS[1][0].keys()
    instance_glyphs_to_test = FONTS[1][0].getGlyphOrder()

    #TODO maybe fix masters so that whitelisting isn't necessary
    whitelist = [
        'uni0488',  # offset 20 units b/w masters, interpolated points are off
        'uni2050'  # has flipped component, so contour is backwards in master
    ]

if __name__ == '__main__':
    unittest.main()
<commit_msg>Test for correct copyright message<commit_after>#!/usr/bin/python
#
# Copyright 2015 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Test general health of the fonts."""

import unittest

from robofab.world import OpenFont
from nototools.unittests import font_tests

import roboto_data

FONTS = font_tests.load_fonts(
    ['out/RobotoTTF/*.ttf', 'out/RobotoCondensedTTF/*.ttf'],
    expected_count=18)

UFOS = font_tests.load_fonts(
    ['out/RobotoUFO/*.ufo', 'out/RobotoCondensedUFO/*.ufo'],
    expected_count=18,
    font_class=OpenFont)

UFO_MASTERS = font_tests.load_fonts(
    ['src/v2/*.ufo'],
    expected_count=3,
    font_class=OpenFont)

class TestItalicAngle(font_tests.TestItalicAngle):
    loaded_fonts = FONTS
    expected_italic_angle = -12.0

class TestMetaInfo(font_tests.TestMetaInfo):
    """Bugs:
    https://github.com/google/roboto/issues/142
    https://code.google.com/a/google.com/p/roboto/issues/detail?id=8
    https://code.google.com/a/google.com/p/roboto/issues/detail?id=29
    """

    loaded_fonts = FONTS
    mark_heavier_as_bold = False
    test_us_weight = None

    #expected_version = '2.' + roboto_data.get_build_number()
    test_version_numbers = None

    # fsType of 0 marks the font free for installation, embedding, etc.
    expected_os2_fsType = 0
    expected_os2_achVendID = 'GOOG'

class TestNames(font_tests.TestNames):
    """Bugs:
    https://github.com/google/roboto/issues/37
    """

    loaded_fonts = FONTS
    family_name = 'Roboto'
    mark_heavier_as_bold = False
    expected_copyright = 'Copyright 2011 Google Inc. All Rights Reserved.'

    def expected_unique_id(self, family, style):
        return 'Google:%s:2015' % family

class TestDigitWidths(font_tests.TestDigitWidths):
    loaded_fonts = FONTS

class TestCharacterCoverage(font_tests.TestCharacterCoverage):
    loaded_fonts = FONTS

    include = frozenset([
        0x2117,  # SOUND RECORDING COPYRIGHT
        0xEE01, 0xEE02, 0xF6C3])  # legacy PUA

    exclude = frozenset([
        0x2072, 0x2073, 0x208F] +  # unassigned characters
        range(0xE000, 0xF8FF + 1) + range(0xF0000, 0x10FFFF + 1)  # other PUA
        ) - include  # don't exclude legacy PUA

class TestLigatures(font_tests.TestLigatures):
    loaded_fonts = FONTS

class TestFeatures(font_tests.TestFeatures):
    loaded_fonts = FONTS

class TestVerticalMetrics(font_tests.TestVerticalMetrics):
    loaded_fonts = FONTS
    test_ymin_ymax = None
    test_hhea_table_metrics = None
    test_os2_metrics = None

    expected_head_yMin = -555
    expected_head_yMax = 2163

class TestGlyphAreas(font_tests.TestGlyphAreas):
    master_weights_to_test = ['Thin', 'Bold']
    instance_weights_to_test = ['Thin', 'Regular', 'Bold']
    exclude = ['Condensed', 'Italic']

    master_glyph_sets = [
        f.replace('_', '-') for f in UFO_MASTERS[0]], UFO_MASTERS[1]
    instance_glyph_sets = FONTS[0], [f.getGlyphSet() for f in FONTS[1]]

    master_glyphs_to_test = UFO_MASTERS[1][0].keys()
    instance_glyphs_to_test = FONTS[1][0].getGlyphOrder()

    #TODO maybe fix masters so that whitelisting isn't necessary
    whitelist = [
        'uni0488',  # offset 20 units b/w masters, interpolated points are off
        'uni2050'  # has flipped component, so contour is backwards in master
    ]

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


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

import sys

from twisted.internet import reactor
from txpostgres import txpostgres
from psycopg2.extensions import AsIs
from sgg.clopts import ArgumentParser
from sgg.log import bind_log

DESCRIPTION = """
%s - The Spiral Galaxy Game dbadmin

Configure postgresql database.
""" % (sys.argv[0],)

@bind_log
def main(log, args = sys.argv[1:]):
    opts = parse_args(args)

    conn = txpostgres.Connection()

    def then(d, f, *args, **kw):
        return d.addCallback(lambda _: f(*args, **kw))

    log.info('Connecting to database.')
    d = conn.connect(dbname='postgres')

    then(d, log.info, 'Creating user %r with password <redacted>.', opts.dbuser)
    then(d, conn.runOperation, 'CREATE USER %s WITH PASSWORD %s', [AsIs(opts.dbuser), opts.dbpw])
    then(d, log.info, 'Creating databse %r owned by %r.', opts.dbname, opts.dbuser)
    then(d, conn.runOperation, 'CREATE DATABASE %s OWNER %s', [AsIs(opts.dbname), AsIs(opts.dbuser)])
    then(d, log.info, 'Finished.')

    d.addErrback(lambda v: log.error('%s', v))
    d.addBoth(lambda _: reactor.stop())

    reactor.run()

def parse_args(args):
    p = ArgumentParser(DESCRIPTION)

    p.add_argument('--dbname',
                   default='sgg_dev',
                   help='database name')

    p.add_argument('--dbuser',
                   default='sgg_dev',
                   help='database user')

    p.add_argument('--dbpw',
                   default='sgg_dev',
                   help='database password')

    return p.parse_args(args)

if __name__ == '__main__':
    main()
<commit_msg>Update the usage description of sgg-create-db-user.<commit_after>#! /usr/bin/env python

import sys

from twisted.internet import reactor
from txpostgres import txpostgres
from psycopg2.extensions import AsIs
from sgg.clopts import ArgumentParser
from sgg.log import bind_log

DESCRIPTION = """
%s - Create the db user and database.

Configure postgresql database.
""" % (sys.argv[0],)

@bind_log
def main(log, args = sys.argv[1:]):
    opts = parse_args(args)

    conn = txpostgres.Connection()

    def then(d, f, *args, **kw):
        return d.addCallback(lambda _: f(*args, **kw))

    log.info('Connecting to database.')
    d = conn.connect(dbname='postgres')

    then(d, log.info, 'Creating user %r with password <redacted>.', opts.dbuser)
    then(d, conn.runOperation, 'CREATE USER %s WITH PASSWORD %s', [AsIs(opts.dbuser), opts.dbpw])
    then(d, log.info, 'Creating databse %r owned by %r.', opts.dbname, opts.dbuser)
    then(d, conn.runOperation, 'CREATE DATABASE %s OWNER %s', [AsIs(opts.dbname), AsIs(opts.dbuser)])
    then(d, log.info, 'Finished.')

    d.addErrback(lambda v: log.error('%s', v))
    d.addBoth(lambda _: reactor.stop())

    reactor.run()

def parse_args(args):
    p = ArgumentParser(DESCRIPTION)

    p.add_argument('--dbname',
                   default='sgg_dev',
                   help='database name')

    p.add_argument('--dbuser',
                   default='sgg_dev',
                   help='database user')

    p.add_argument('--dbpw',
                   default='sgg_dev',
                   help='database password')

    return p.parse_args(args)

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


<commit_before>from subprocess import Popen, PIPE
from django.conf import settings

def getVersion():
    """Try to get a version string from git, otherwise use a default"""
    command = ("git", "describe", "--tags")
    try:
        result = Popen(command, stdout=PIPE).communicate()[0]
    except OSError:
        result = settings.PACKAGE_VERSION
    return result
<commit_msg>make sure the git command is executed inside the git directory<commit_after>from subprocess import Popen, PIPE
from django.conf import settings
import os

def getVersion():
    """Try to get a version string from git, otherwise use a default"""
    command = ("git", "describe", "--tags")
    try:
        cwd = os.getcwd()
        os.chdir(settings.PROJECT_DIR)
        result = Popen(command, stdout=PIPE).communicate()[0]
        os.chdir(cwd)
    except OSError:
        result = settings.PACKAGE_VERSION
    return result
<|endoftext|>


<commit_before>#!/usr/bin/python -tt
# Copyright 2010 Google Inc.
# Licensed under the Apache License, Version 2.0
# http://www.apache.org/licenses/LICENSE-2.0

# Google's Python Class
# http://code.google.com/edu/languages/google-python-class/

"""A tiny Python program to check that Python is working.
Try running this program from the command line like this:
  python hello.py
  python hello.py Alice
That should print:
  Hello World -or- Hello Alice
Try changing the 'Hello' to 'Howdy' and run again.
Once you have that working, you're ready for class -- you can edit
and run Python code; now you just need to learn Python!
"""

import sys

# # Define a main() function that prints a little greeting.
# def main():
#   # Get the name from the command line, using 'World' as a fallback.
#   if len(sys.argv) >= 2:
#     name = len(sys.argv[1])
#   else:
#     name = len('World'
  print 'Hello', name

# # This is the standard boilerplate that calls the main() function.
# if __name__ == '__main__':
  main()
def main():
  print repeat('Yay',False)
  print repeat('Woo Hoo', True)

def repeat(s,exlaim):
  result = "s * 3"
  if exclaim:
    result = result + '!!!'
  return result

//ll
def main():
    if name == 'Guido':
        print repeeeet(name) + '!!!'
    else:
        print repeat(name)

s = 'hi'
print s[1]
print len(s)
print s + ' more'

# import sys

# sys.exit(0)

#sys - access to exit(),argv,stdin,stdout
#re - regex
#os - os interface, file system
p1 = 3.14
## the vlue is pi
text = 'the value io pie is' + str(p1)

raw = r'this\t\n and that'
print raw     ## this\t\n and that

multi = """It was the best of times.
It was the worst of times."""
print multi
# s.lower(),s.uper()
# s.strip() - removes whitespace
# s.isalpha()/s.isdidgit(),s.isspace() - test is string chars are in character class
# s.startswith('other'),s.endwith('other') - test for start or end of string
# s.find('other') - searches for 'other' within s, returns 1st index if found otherwise -1
# s.replace('old','new') - resturns replacedment string
# s.split('delim') - returns substrings split by delim - no args splits on whitespace
# s.join(list) - opposite of split ( array ) joins elements
# slice.s[start:end] - refer to sub parts of sequences 0 strings and lists
#    H E L L O
#    0 1 2 3 4
#   -5-4-3-2-1
# % operator
text = "%d little pigs come out or I'll %s and %s and %s" % (3, 'huff', 'puff', 'blow down')
print text
 # add parens to make the long-line work:
text = ("%d little pigs come out or I'll %s and %s and i'll %s your house %s" %
    (3, 'huff', 'puff', 'blow', 'down'))
print text

<commit_msg>pyhton tests<commit_after>#!/usr/bin/python -tt
# Copyright 2010 Google Inc.
# Licensed under the Apache License, Version 2.0
# http://www.apache.org/licenses/LICENSE-2.0

# Google's Python Class
# http://code.google.com/edu/languages/google-python-class/

"""A tiny Python program to check that Python is working.
Try running this program from the command line like this:
  python hello.py
  python hello.py Alice
That should print:
  Hello World -or- Hello Alice
Try changing the 'Hello' to 'Howdy' and run again.
Once you have that working, you're ready for class -- you can edit
and run Python code; now you just need to learn Python!
"""

import sys

# # Define a main() function that prints a little greeting.
# def main():
#   # Get the name from the command line, using 'World' as a fallback.
#   if len(sys.argv) >= 2:
#     name = len(sys.argv[1])
#   else:
#     name = len('World'
  print 'Hello', name

# # This is the standard boilerplate that calls the main() function.
# if __name__ == '__main__':
#   main()
def main():
  print repeat('Yay',False)
  print repeat('Woo Hoo', True)

def repeat(s,exlaim):
  result = "s * 3"
  if exclaim:
    result = result + '!!!'
  return result

//ll
def main():
    if name == 'Guido':
        print repeeeet(name) + '!!!'
    else:
        print repeat(name)

s = 'hi'
print s[1]
print len(s)
print s + ' more'

# import sys

# sys.exit(0)

#sys - access to exit(),argv,stdin,stdout
#re - regex
#os - os interface, file system
p1 = 3.14
## the vlue is pi
text = 'the value io pie is' + str(p1)

raw = r'this\t\n and that'
print raw     ## this\t\n and that

multi = """It was the best of times.
It was the worst of times."""
print multi
# s.lower(),s.uper()
# s.strip() - removes whitespace
# s.isalpha()/s.isdidgit(),s.isspace() - test is string chars are in character class
# s.startswith('other'),s.endwith('other') - test for start or end of string
# s.find('other') - searches for 'other' within s, returns 1st index if found otherwise -1
# s.replace('old','new') - resturns replacedment string
# s.split('delim') - returns substrings split by delim - no args splits on whitespace
# s.join(list) - opposite of split ( array ) joins elements
# slice.s[start:end] - refer to sub parts of sequences 0 strings and lists
#    H E L L O
#    0 1 2 3 4
#   -5-4-3-2-1
# % operator
text = "%d little pigs come out or I'll %s and %s and %s" % (3, 'huff', 'puff', 'blow down')
print text
 # add parens to make the long-line work:
text = ("%d little pigs come out or I'll %s and %s and i'll %s your house %s" %
    (3, 'huff', 'puff', 'blow', 'down'))
print text

<|endoftext|>


<commit_before>def tokenize(program):
    """
    I: (+ 2 (- 4 2))
    O: [(, +, 2, (, -, 4, 2, ), )]
    """
    return program.replace(')', ' ) ').replace('(', ' ( ').split()

def read(tokens):
    """
    I: [(, +, 2, (, -, 4, 2, ), )]
    O: [+, 2, [-, 4, 2]]
    """
    def proceed_list(tokens):
        l = []
        while tokens[0] != ')':
            l.append(read(tokens))
        tokens.pop(0)
        return l

    if not len(tokens):
        raise SyntaxError('Empty program')

    t = tokens.pop(0)

    if t == '(':
        return proceed_list(tokens)
    elif t == ')':
        raise SyntaxError()
    else:
        return t

def evaluate(exp):
    """
    I: [+, 2, [-, 4, 2]]
    O: 4
    """
    operations = {
        '+': lambda x, y: evaluate(x) + evaluate(y),
        '-': lambda x, y: evaluate(x) - evaluate(y),
        '*': lambda x, y: evaluate(x) * evaluate(y),
        '/': lambda x, y: evaluate(x) / evaluate(y),
    }

    def function_call(function, *args):
        return function(*args)

    def atom(exp):
        try:
            return int(exp)
        except ValueError:
            try:
                return float(exp)
            except ValueError:
                return exp

    if exp[0] in operations:
        return function_call(operations[exp[0]], exp[1], exp[2])
    else:
        return atom(exp)

def parse(program):
    tokens = tokenize(program)
    ast = read(tokens)
    return ast

if __name__ == '__main__':
    ast = parse('(+ 2 (- 4 (* 2 1)))')
    print(evaluate(ast))
<commit_msg>Refactor eval procedure, add basic arithmetic operations<commit_after>import operator

def tokenize(program):
    """
    I: (+ 2 (- 4 2))
    O: [(, +, 2, (, -, 4, 2, ), )]
    """
    return program.replace(')', ' ) ').replace('(', ' ( ').split()

def atomize(token):
    try:
        return int(token)
    except ValueError:
        try:
            return float(token)
        except ValueError:
            return token

def read(tokens):
    """
    I: [(, +, 2, (, -, 4, 2, ), )]
    O: [+, 2, [-, 4, 2]]
    """
    def proceed_list(tokens):
        l = []
        while tokens[0] != ')':
            l.append(read(tokens))
        tokens.pop(0)
        return l

    if not len(tokens):
        raise SyntaxError('Empty program')

    t = tokens.pop(0)

    if t == '(':
        return proceed_list(tokens)
    elif t == ')':
        raise SyntaxError()
    else:
        return atomize(t)

def evaluate(exp):
    """
    I: [+, 2, [-, 4, 2]]
    O: 4
    """
    operations = {
        '+': operator.add,
        '-': operator.sub,
        '*': operator.mul,
        '/': operator.truediv,
        '>': operator.gt,
        '<': operator.lt,
        '>=': operator.ge,
        '<=': operator.le,
        '=': operator.eq,
    }

    def is_operation(exp):
        return isinstance(exp, list) and exp[0] in operations

    def function_call(exp):
        function = operations[exp[0]]
        args = [evaluate(x) for x in exp[1:]]
        return function(*args)

    if is_operation(exp):
        return function_call(exp)
    else:
        return exp

def parse(program):
    tokens = tokenize(program)
    ast = read(tokens)
    print(ast)
    return ast

if __name__ == '__main__':
    ast = parse('(+ 2 (- 4 (* 2 1)))')
    print(evaluate(ast))
<|endoftext|>


<commit_before><commit_msg>- Small bug fix (Not really a bug)<commit_after><|endoftext|>


<commit_before>from .enums import GameMode, Mod
import lzma, struct

class ReplayEvent(object):
    def __init__(self, time_since_previous_action, x, y, keys_pressed):
        self.time_since_previous_action = time_since_previous_action
        self.x = x
        self.y = y
        self.keys_pressed = keys_pressed

class Replay(object):
    __BYTE = 1
    __SHORT = 2
    __INT = 4
    __LONG = 8

    #Order of field initilization matters.
    def __init__(self, replay_data):
        self.offset = 0
        self.game_mode = None
        self.game_version = None
        self.beatmap_hash = None
        self.player_name = None
        self.replay_hash = None
        self.number_300s = None
        self.number_100s = None
        self.number_50s = None
        self.gekis = None
        self.katus = None
        self.misses = None
        self.score = None
        self.max_combo = None
        self.is_perfect_combo = None
        self.mod_combination = None
        self.life_bar_graph = None
        self.timestamp = None
        self.play_data = None
        self.parse_replay_and_initialize_fields(replay_data)

    def parse_replay_and_initialize_fields(self, replay_data):
        self.parse_game_mode_and_version(replay_data)
        self.parse_beatmap_hash(replay_data)
        self.parse_player_name(replay_data)
        self.parse_replay_hash(replay_data)
        self.parse_score_stats(replay_data)
        self.parse_life_bar_graph(replay_data)
        self.parse_timestamp_and_replay_length(replay_data)
        self.parse_play_data(replay_data)

    def parse_game_mode_and_version(self, replay_data):
        format_specifier = "<bi"
        data = struct.unpack_from(format_specifier, replay_data, self.offset)
        self.offset += struct.calcsize(format_specifier)
        self.game_mode, self.game_version = (GameMode(data[0]), data[1])

    def unpack_game_stats(self, game_stats):
        self.number_300s, self.number_100s, self.number_50s, self.gekis, self.katus, self.misses, self.score, self.max_combo, self.is_perfect_combo, self.mod_combination = game_stats

    def parse_mod_combination(self):
        # Generator yielding value of each bit in an integer if it's set + value
        # of LSB no matter what .
        def bits(n):
            if n == 0:
                yield 0
            while n:
                b = n & (~n+1)
                yield b
                n ^= b

        bit_values_gen = bits(self.mod_combination)
        self.mod_combination = frozenset(Mod(mod_val) for mod_val in bit_values_gen)

    def parse_score_stats(self, replay_data):
        format_specifier = "<hhhhhhih?i"
        data = struct.unpack_from(format_specifier, replay_data, self.offset)
        self.unpack_game_stats(data)
        self.parse_mod_combination()
        self.offset += struct.calcsize(format_specifier)

    @staticmethod
    def __parse_as_int(bytestring):
        return int.from_bytes(bytestring, byteorder='little')

    def __decode(self, binarystream):
        result = 0
        shift = 0
        while True:
            byte = binarystream[self.offset]
            self.offset += 1
            result = result |((byte & 0b01111111) << shift)
            if (byte & 0b10000000) == 0x00:
                break
            shift += 7
        return result

    def parse_player_name(self, replay_data):
        self.player_name = self.parse_string(replay_data)

    def parse_string(self, replay_data):
        if replay_data[self.offset] == 0x00:
            self.offset += Replay.__BYTE
        elif replay_data[self.offset] == 0x0b:
            self.offset += Replay.__BYTE
            string_length = self.__decode(replay_data)
            offset_end = self.offset + string_length
            string = replay_data[self.offset:offset_end].decode("utf-8")
            self.offset = offset_end
            return string
        else:
            #TODO: Replace with custom exception
            raise Exception("Invalid replay")

    def parse_beatmap_hash(self, replay_data):
        self.beatmap_hash = self.parse_string(replay_data)

    def parse_replay_hash(self, replay_data):
        self.replay_hash = self.parse_string(replay_data)

    def parse_life_bar_graph(self, replay_data):
        self.life_bar_graph = self.parse_string(replay_data)

    def parse_timestamp_and_replay_length(self, replay_data):
        format_specifier = "<qi"
        (t, self.__replay_length) = struct.unpack_from(format_specifier, replay_data, self.offset)
        self.timestamp = datetime.datetime(1, 1, 1) + datetime.timedelta(microseconds=t/10)
        self.offset += struct.calcsize(format_specifier)

    def parse_play_data(self, replay_data):
        offset_end = self.offset+self.__replay_length
        if self.game_mode != GameMode.Standard:
            self.play_data = None
        else:
            datastring = lzma.decompress(replay_data[self.offset:offset_end], format=lzma.FORMAT_AUTO).decode('ascii')[:-1]
            events = [eventstring.split('|') for eventstring in datastring.split(',')]
            self.play_data = [ReplayEvent(int(event[0]), float(event[1]), float(event[2]), int(event[3])) for event in events]
        self.offset = offset_end

def parse_replay(replay_data):
    return Replay(replay_data)

def parse_replay_file(replay_path):
    with open(replay_path, 'rb') as f:
        data = f.read()
    return parse_replay(data)
<commit_msg>Added missing datetime import<commit_after>from .enums import GameMode, Mod
import lzma, struct, datetime

class ReplayEvent(object):
    def __init__(self, time_since_previous_action, x, y, keys_pressed):
        self.time_since_previous_action = time_since_previous_action
        self.x = x
        self.y = y
        self.keys_pressed = keys_pressed

class Replay(object):
    __BYTE = 1
    __SHORT = 2
    __INT = 4
    __LONG = 8

    #Order of field initilization matters.
    def __init__(self, replay_data):
        self.offset = 0
        self.game_mode = None
        self.game_version = None
        self.beatmap_hash = None
        self.player_name = None
        self.replay_hash = None
        self.number_300s = None
        self.number_100s = None
        self.number_50s = None
        self.gekis = None
        self.katus = None
        self.misses = None
        self.score = None
        self.max_combo = None
        self.is_perfect_combo = None
        self.mod_combination = None
        self.life_bar_graph = None
        self.timestamp = None
        self.play_data = None
        self.parse_replay_and_initialize_fields(replay_data)

    def parse_replay_and_initialize_fields(self, replay_data):
        self.parse_game_mode_and_version(replay_data)
        self.parse_beatmap_hash(replay_data)
        self.parse_player_name(replay_data)
        self.parse_replay_hash(replay_data)
        self.parse_score_stats(replay_data)
        self.parse_life_bar_graph(replay_data)
        self.parse_timestamp_and_replay_length(replay_data)
        self.parse_play_data(replay_data)

    def parse_game_mode_and_version(self, replay_data):
        format_specifier = "<bi"
        data = struct.unpack_from(format_specifier, replay_data, self.offset)
        self.offset += struct.calcsize(format_specifier)
        self.game_mode, self.game_version = (GameMode(data[0]), data[1])

    def unpack_game_stats(self, game_stats):
        self.number_300s, self.number_100s, self.number_50s, self.gekis, self.katus, self.misses, self.score, self.max_combo, self.is_perfect_combo, self.mod_combination = game_stats

    def parse_mod_combination(self):
        # Generator yielding value of each bit in an integer if it's set + value
        # of LSB no matter what .
        def bits(n):
            if n == 0:
                yield 0
            while n:
                b = n & (~n+1)
                yield b
                n ^= b

        bit_values_gen = bits(self.mod_combination)
        self.mod_combination = frozenset(Mod(mod_val) for mod_val in bit_values_gen)

    def parse_score_stats(self, replay_data):
        format_specifier = "<hhhhhhih?i"
        data = struct.unpack_from(format_specifier, replay_data, self.offset)
        self.unpack_game_stats(data)
        self.parse_mod_combination()
        self.offset += struct.calcsize(format_specifier)

    @staticmethod
    def __parse_as_int(bytestring):
        return int.from_bytes(bytestring, byteorder='little')

    def __decode(self, binarystream):
        result = 0
        shift = 0
        while True:
            byte = binarystream[self.offset]
            self.offset += 1
            result = result |((byte & 0b01111111) << shift)
            if (byte & 0b10000000) == 0x00:
                break
            shift += 7
        return result

    def parse_player_name(self, replay_data):
        self.player_name = self.parse_string(replay_data)

    def parse_string(self, replay_data):
        if replay_data[self.offset] == 0x00:
            self.offset += Replay.__BYTE
        elif replay_data[self.offset] == 0x0b:
            self.offset += Replay.__BYTE
            string_length = self.__decode(replay_data)
            offset_end = self.offset + string_length
            string = replay_data[self.offset:offset_end].decode("utf-8")
            self.offset = offset_end
            return string
        else:
            #TODO: Replace with custom exception
            raise Exception("Invalid replay")

    def parse_beatmap_hash(self, replay_data):
        self.beatmap_hash = self.parse_string(replay_data)

    def parse_replay_hash(self, replay_data):
        self.replay_hash = self.parse_string(replay_data)

    def parse_life_bar_graph(self, replay_data):
        self.life_bar_graph = self.parse_string(replay_data)

    def parse_timestamp_and_replay_length(self, replay_data):
        format_specifier = "<qi"
        (t, self.__replay_length) = struct.unpack_from(format_specifier, replay_data, self.offset)
        self.timestamp = datetime.datetime(1, 1, 1) + datetime.timedelta(microseconds=t/10)
        self.offset += struct.calcsize(format_specifier)

    def parse_play_data(self, replay_data):
        offset_end = self.offset+self.__replay_length
        if self.game_mode != GameMode.Standard:
            self.play_data = None
        else:
            datastring = lzma.decompress(replay_data[self.offset:offset_end], format=lzma.FORMAT_AUTO).decode('ascii')[:-1]
            events = [eventstring.split('|') for eventstring in datastring.split(',')]
            self.play_data = [ReplayEvent(int(event[0]), float(event[1]), float(event[2]), int(event[3])) for event in events]
        self.offset = offset_end

def parse_replay(replay_data):
    return Replay(replay_data)

def parse_replay_file(replay_path):
    with open(replay_path, 'rb') as f:
        data = f.read()
    return parse_replay(data)
<|endoftext|>


<commit_before>
import mapscript
import mx.DateTime, sys, os
from PIL import Image, ImageDraw, ImageFont
from pyIEM import iemdb
i = iemdb.iemdb()
postgis = i['postgis']
postgis.query("SET TIME ZONE 'GMT'")

# Preparation
sortOpt = sys.argv[1]
ts = mx.DateTime.gmt() - mx.DateTime.RelativeDateTime(hours=1)
if (len(sys.argv) == 5):
  ts = mx.DateTime.DateTime( int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3]) )
  sortOpt = sys.argv[4]

opts = {'W': {'fnadd': '-wfo', 'sortby': 'wfo ASC, phenomena ASC, eventid ASC'},
        'S': {'fnadd': '', 'sortby': 'size DESC'},
        'T': {'fnadd': '-time', 'sortby': 'issue ASC'} }

# Defaults
thumbpx = 100
cols = 10

# Find largest polygon either in height or width
sql = "SELECT *, area2d(transform(geom,2163)) as size, \
  (xmax(transform(geom,2163)) - xmin(transform(geom,2163))) as width, \
  (ymax(transform(geom,2163)) - ymin(transform(geom,2163))) as height \
  from warnings_%s WHERE gtype = 'P' and date(issue) = '%s' and \
  phenomena IN ('TO','SV') " % (ts.year, ts.strftime("%Y-%m-%d") )
rs = postgis.query(sql).dictresult()
maxDimension = 0
buffer = 10000
i = 0
torCount = 0
torSize = 0
svrCount = 0
svrSize = 0
for i in range(len(rs)):
  w = float(rs[i]['width'])
  h = float(rs[i]['height'])
  if (w > maxDimension): maxDimension = w
  if (h > maxDimension): maxDimension = h

  if (rs[i]['phenomena'] == "SV"):
    svrCount += 1
    svrSize += float(rs[i]['size'])
  if (rs[i]['phenomena'] == "TO"):
    torCount += 1
    torSize += float(rs[i]['size'])

#print "Largest Dimension %s m" % (maxDimension,)

sql = "SELECT phenomena, sum( area2d(transform(geom,2163)) ) as size \
   from warnings_%s WHERE gtype = 'C' and date(issue) = '%s' and significance = 'W' and \
  phenomena IN ('TO','SV') GROUP by phenomena" % (ts.year, ts.strftime("%Y-%m-%d") )
rs = postgis.query(sql).dictresult()
for q in range(len(rs)):
  if (rs[q]['phenomena'] == "TO"):
    totalTorCar = 100.0* (1.0 - (torSize / float(rs[q]['size'])))
  if (rs[q]['phenomena'] == "SV"):
    totalSvrCar = 100.0* (1.0 - (svrSize / float(rs[q]['size'])))

# Make mosaic image
header = 35
mosaic = Image.new('RGB', (thumbpx*cols, ((int(i/cols)+1)*thumbpx )+header ))
font = ImageFont.truetype('../../data/fonts/veramono.ttf', 12)
font10 = ImageFont.truetype('../../data/fonts/veramono.ttf', 10)
font2 = ImageFont.truetype('../../data/fonts/veramono.ttf', 18)
draw = ImageDraw.Draw(mosaic)

imagemap = open('imap.txt', 'w')
imagemap.write("<!-- %s -->\n" % (mx.DateTime.gmt().strftime("%Y-%m-%d %H:%M:%S"),) )
imagemap.write("<MAP NAME='mymap'>\n")

# Find my polygons
sql = "SELECT *, area2d(transform(geom,2163)) as size, \
  (xmax(transform(geom,2163)) + xmin(transform(geom,2163))) /2.0 as xc, \
  (ymax(transform(geom,2163)) + ymin(transform(geom,2163))) /2.0 as yc \
  from warnings_%s WHERE gtype = 'P' and date(issue) = '%s' and \
  phenomena IN ('TO','SV') and eventid is not null ORDER by %s" % \
  (ts.year, ts.strftime("%Y-%m-%d"), opts[sortOpt]['sortby'] )
rs = postgis.query(sql).dictresult()

# Write metadata to image
tmp = Image.open("logo_small.png")
mosaic.paste( tmp, (3,2))
s = "IEM Summary of NWS Storm Based Warnings issued %s UTC" % (ts.strftime("%d %b %Y"), )
(w, h) = font2.getsize(s)
draw.text((54,3), s, font=font2)

s = "Generated: %s UTC" % (mx.DateTime.gmt().strftime("%d %b %Y %H:%M:%S"),  )
draw.text((54,3+h), s, font=font10)

if (svrCount > 0):
  s = "%3i SVR: Avg Size %5.0f km^2 CAR: %.0f%%" % (svrCount, (svrSize/float(svrCount)) / 1000000 , totalSvrCar)
  draw.text((54+w+10,8), s, font=font10, fill="#ffff00")

if (torCount > 0):
  s = "%3i TOR: Avg Size %5.0f km^2 CAR: %.0f%%" % (torCount, (torSize/float(torCount)) / 1000000, totalTorCar )
  draw.text((54+w+10,22), s, font=font10, fill="#ff0000")

if (len(rs) == 0):
  s = "No warnings in database for this date"
  draw.text((100,78), s, font=font2, fill="#ffffff")

for i in range(len(rs)):
  # - Map each polygon
  x0 = float(rs[i]['xc']) - (maxDimension/2.0) - buffer
  x1 = float(rs[i]['xc']) + (maxDimension/2.0) + buffer
  y0 = float(rs[i]['yc']) - (maxDimension/2.0) - 2 * buffer
  y1 = float(rs[i]['yc']) + (maxDimension/2.0)
  map = mapscript.mapObj("polygon.map")
  map.setSize(thumbpx,thumbpx)
  map.setExtent(x0,y0,x1,y1)
  sbw = map.getLayerByName("sbw")
  sbw.data = "geom from (select phenomena, significance, geom, oid from warnings_%s WHERE gtype = 'P' and phenomena = '%s' and significance = '%s' and eventid = %s and wfo = '%s') as foo using unique oid using SRID=4326" % (ts.year, rs[i]['phenomena'], rs[i]['significance'], rs[i]['eventid'], rs[i]['wfo'])
  img = map.prepareImage()
  sbw.draw(map, img)
  my = int(i / cols) * thumbpx + header
  mx0 = (i % cols) * thumbpx
  img.save("tmp.png")
  del img, map
  # - Add each polygon to mosaic
  tmp = Image.open("tmp.png")
  mosaic.paste( tmp, (mx0,my))
  del tmp
  os.remove("tmp.png")

  # Compute CAR!
  sql = "SELECT sum( area2d(transform(geom,2163))) as csize from \
   (select distinct geom from warnings_%s WHERE gtype = 'C' and \
   phenomena = '%s' and significance = '%s' and eventid = %s and wfo = '%s') \
   as foo" % (ts.year, rs[i]['phenomena'], rs[i]['significance'], rs[i]['eventid'], rs[i]['wfo'])
  rs2 = postgis.query(sql).dictresult()
  car = "NA"
  carColor = (255,255,255)
  if (len(rs2) > 0 and rs2[0]['csize'] is not None):
    csize = float( rs2[0]['csize'] )
    carF = 100.0* (1.0 - (rs[i]['size'] / csize))
    car = "%.0f" % (carF,)
    if (carF > 75):
      carColor = (0,255,0)
    if (carF < 25):
      carColor = (255,0,0)

  # Draw Text!
  issue = mx.DateTime.strptime( rs[i]['issue'][:16], "%Y-%m-%d %H:%M" )
  s = "%s.%s.%s.%s" % (rs[i]['wfo'], rs[i]['phenomena'], rs[i]['eventid'], issue.strftime("%H%M") )
  (w, h) = font10.getsize(s)
  draw.text((mx0+2,my+thumbpx-h), s, font=font10)
  s = "%.0f sq km %s%%" % (rs[i]['size']/1000000.0, car)
  draw.text((mx0+2,my+thumbpx-(2*h)), s, font=font10, fill=carColor)

  # Image map
  url = "http://mesonet.agron.iastate.edu/vtec/#%s-O-NEW-K%s-%s-%s-%04i" % (ts.year, rs[i]['wfo'], rs[i]['phenomena'], rs[i]['significance'], rs[i]['eventid'] )
  altxt = "Click for text/image"
  imagemap.write("<AREA HREF=\"%s\" ALT=\"%s\" TITLE=\"%s\" SHAPE=RECT COORDS=\"%s,%s,%s,%s\">\n" % (url, altxt, altxt, mx0, my, mx0+thumbpx, my+thumbpx) )

for i in range(len(rs)):
  my = int(i / cols) * thumbpx + header
  mx0 = (i % cols) * thumbpx
  if (mx0 == 0):
    draw.line( (0,my+thumbpx+2, (thumbpx*cols),my+thumbpx+2), (0,120,200) )

mosaic.save("test.png")
del mosaic

imagemap.write("</map>")
imagemap.close()

cmd = "/home/ldm/bin/pqinsert -p 'plot a %s0000 blah sbwsum%s.png png' test.png" % (ts.strftime("%Y%m%d"), opts[sortOpt]['fnadd'])
os.system( cmd )

cmd = "/home/ldm/bin/pqinsert -p 'plot a %s0000 blah sbwsum-imap%s.txt txt' imap.txt" % (ts.strftime("%Y%m%d"), opts[sortOpt]['fnadd'])
os.system( cmd )

os.remove("test.png")
os.remove("imap.txt")
<commit_msg>Avoid missing imap files<commit_after>
import mapscript
import mx.DateTime, sys, os
from PIL import Image, ImageDraw, ImageFont
from pyIEM import iemdb
i = iemdb.iemdb()
postgis = i['postgis']
postgis.query("SET TIME ZONE 'GMT'")

# Preparation
sortOpt = sys.argv[1]
ts = mx.DateTime.gmt() - mx.DateTime.RelativeDateTime(hours=1)
if (len(sys.argv) == 5):
  ts = mx.DateTime.DateTime( int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3]) )
  sortOpt = sys.argv[4]

opts = {'W': {'fnadd': '-wfo', 'sortby': 'wfo ASC, phenomena ASC, eventid ASC'},
        'S': {'fnadd': '', 'sortby': 'size DESC'},
        'T': {'fnadd': '-time', 'sortby': 'issue ASC'} }

# Defaults
thumbpx = 100
cols = 10

# Find largest polygon either in height or width
sql = "SELECT *, area2d(transform(geom,2163)) as size, \
  (xmax(transform(geom,2163)) - xmin(transform(geom,2163))) as width, \
  (ymax(transform(geom,2163)) - ymin(transform(geom,2163))) as height \
  from warnings_%s WHERE gtype = 'P' and date(issue) = '%s' and \
  phenomena IN ('TO','SV') " % (ts.year, ts.strftime("%Y-%m-%d") )
rs = postgis.query(sql).dictresult()
maxDimension = 0
buffer = 10000
i = 0
torCount = 0
torSize = 0
svrCount = 0
svrSize = 0
for i in range(len(rs)):
  w = float(rs[i]['width'])
  h = float(rs[i]['height'])
  if (w > maxDimension): maxDimension = w
  if (h > maxDimension): maxDimension = h

  if (rs[i]['phenomena'] == "SV"):
    svrCount += 1
    svrSize += float(rs[i]['size'])
  if (rs[i]['phenomena'] == "TO"):
    torCount += 1
    torSize += float(rs[i]['size'])

#print "Largest Dimension %s m" % (maxDimension,)

sql = "SELECT phenomena, sum( area2d(transform(geom,2163)) ) as size \
   from warnings_%s WHERE gtype = 'C' and date(issue) = '%s' and significance = 'W' and \
  phenomena IN ('TO','SV') GROUP by phenomena" % (ts.year, ts.strftime("%Y-%m-%d") )
rs = postgis.query(sql).dictresult()
for q in range(len(rs)):
  if (rs[q]['phenomena'] == "TO"):
    totalTorCar = 100.0* (1.0 - (torSize / float(rs[q]['size'])))
  if (rs[q]['phenomena'] == "SV"):
    totalSvrCar = 100.0* (1.0 - (svrSize / float(rs[q]['size'])))

# Make mosaic image
header = 35
mosaic = Image.new('RGB', (thumbpx*cols, ((int(i/cols)+1)*thumbpx )+header ))
font = ImageFont.truetype('../../data/fonts/veramono.ttf', 12)
font10 = ImageFont.truetype('../../data/fonts/veramono.ttf', 10)
font2 = ImageFont.truetype('../../data/fonts/veramono.ttf', 18)
draw = ImageDraw.Draw(mosaic)

imagemap = open('imap.txt', 'w')
imagemap.write("<!-- %s %s -->\n" % (mx.DateTime.gmt().strftime("%Y-%m-%d %H:%M:%S"), sortOpt) )
imagemap.write("<MAP NAME='mymap'>\n")

# Find my polygons
sql = "SELECT *, area2d(transform(geom,2163)) as size, \
  (xmax(transform(geom,2163)) + xmin(transform(geom,2163))) /2.0 as xc, \
  (ymax(transform(geom,2163)) + ymin(transform(geom,2163))) /2.0 as yc \
  from warnings_%s WHERE gtype = 'P' and date(issue) = '%s' and \
  phenomena IN ('TO','SV') and eventid is not null ORDER by %s" % \
  (ts.year, ts.strftime("%Y-%m-%d"), opts[sortOpt]['sortby'] )
rs = postgis.query(sql).dictresult()

# Write metadata to image
tmp = Image.open("logo_small.png")
mosaic.paste( tmp, (3,2))
s = "IEM Summary of NWS Storm Based Warnings issued %s UTC" % (ts.strftime("%d %b %Y"), )
(w, h) = font2.getsize(s)
draw.text((54,3), s, font=font2)

s = "Generated: %s UTC" % (mx.DateTime.gmt().strftime("%d %b %Y %H:%M:%S"),  )
draw.text((54,3+h), s, font=font10)

if (svrCount > 0):
  s = "%3i SVR: Avg Size %5.0f km^2 CAR: %.0f%%" % (svrCount, (svrSize/float(svrCount)) / 1000000 , totalSvrCar)
  draw.text((54+w+10,8), s, font=font10, fill="#ffff00")

if (torCount > 0):
  s = "%3i TOR: Avg Size %5.0f km^2 CAR: %.0f%%" % (torCount, (torSize/float(torCount)) / 1000000, totalTorCar )
  draw.text((54+w+10,22), s, font=font10, fill="#ff0000")

if (len(rs) == 0):
  s = "No warnings in database for this date"
  draw.text((100,78), s, font=font2, fill="#ffffff")

for i in range(len(rs)):
  # - Map each polygon
  x0 = float(rs[i]['xc']) - (maxDimension/2.0) - buffer
  x1 = float(rs[i]['xc']) + (maxDimension/2.0) + buffer
  y0 = float(rs[i]['yc']) - (maxDimension/2.0) - 2 * buffer
  y1 = float(rs[i]['yc']) + (maxDimension/2.0)
  map = mapscript.mapObj("polygon.map")
  map.setSize(thumbpx,thumbpx)
  map.setExtent(x0,y0,x1,y1)
  sbw = map.getLayerByName("sbw")
  sbw.data = "geom from (select phenomena, significance, geom, oid from warnings_%s WHERE gtype = 'P' and phenomena = '%s' and significance = '%s' and eventid = %s and wfo = '%s') as foo using unique oid using SRID=4326" % (ts.year, rs[i]['phenomena'], rs[i]['significance'], rs[i]['eventid'], rs[i]['wfo'])
  img = map.prepareImage()
  sbw.draw(map, img)
  my = int(i / cols) * thumbpx + header
  mx0 = (i % cols) * thumbpx
  img.save("tmp.png")
  del img, map
  # - Add each polygon to mosaic
  tmp = Image.open("tmp.png")
  mosaic.paste( tmp, (mx0,my))
  del tmp
  os.remove("tmp.png")

  # Compute CAR!
  sql = "SELECT sum( area2d(transform(geom,2163))) as csize from \
   (select distinct geom from warnings_%s WHERE gtype = 'C' and \
   phenomena = '%s' and significance = '%s' and eventid = %s and wfo = '%s') \
   as foo" % (ts.year, rs[i]['phenomena'], rs[i]['significance'], rs[i]['eventid'], rs[i]['wfo'])
  rs2 = postgis.query(sql).dictresult()
  car = "NA"
  carColor = (255,255,255)
  if (len(rs2) > 0 and rs2[0]['csize'] is not None):
    csize = float( rs2[0]['csize'] )
    carF = 100.0* (1.0 - (rs[i]['size'] / csize))
    car = "%.0f" % (carF,)
    if (carF > 75):
      carColor = (0,255,0)
    if (carF < 25):
      carColor = (255,0,0)

  # Draw Text!
  issue = mx.DateTime.strptime( rs[i]['issue'][:16], "%Y-%m-%d %H:%M" )
  s = "%s.%s.%s.%s" % (rs[i]['wfo'], rs[i]['phenomena'], rs[i]['eventid'], issue.strftime("%H%M") )
  (w, h) = font10.getsize(s)
  draw.text((mx0+2,my+thumbpx-h), s, font=font10)
  s = "%.0f sq km %s%%" % (rs[i]['size']/1000000.0, car)
  draw.text((mx0+2,my+thumbpx-(2*h)), s, font=font10, fill=carColor)

  # Image map
  url = "http://mesonet.agron.iastate.edu/vtec/#%s-O-NEW-K%s-%s-%s-%04i" % (ts.year, rs[i]['wfo'], rs[i]['phenomena'], rs[i]['significance'], rs[i]['eventid'] )
  altxt = "Click for text/image"
  imagemap.write("<AREA HREF=\"%s\" ALT=\"%s\" TITLE=\"%s\" SHAPE=RECT COORDS=\"%s,%s,%s,%s\">\n" % (url, altxt, altxt, mx0, my, mx0+thumbpx, my+thumbpx) )

for i in range(len(rs)):
  my = int(i / cols) * thumbpx + header
  mx0 = (i % cols) * thumbpx
  if (mx0 == 0):
    draw.line( (0,my+thumbpx+2, (thumbpx*cols),my+thumbpx+2), (0,120,200) )

mosaic.save("test.png")
del mosaic

imagemap.write("</map>")
imagemap.close()

cmd = "/home/ldm/bin/pqinsert -p 'plot a %s0000 blah sbwsum%s.png png' test.png" % (ts.strftime("%Y%m%d"), opts[sortOpt]['fnadd'])
os.system( cmd )

cmd = "/home/ldm/bin/pqinsert -p 'plot a %s0000 blah sbwsum-imap%s.txt txt' imap.txt" % (ts.strftime("%Y%m%d"), opts[sortOpt]['fnadd'])
os.system( cmd )

os.remove("test.png")
os.remove("imap.txt")
<|endoftext|>


<commit_before>ZULIP_VERSION = "1.5.1+git"
PROVISION_VERSION = '5.1'
<commit_msg>deps: Update PROVISION_VERSION for webpack upgrade.<commit_after>ZULIP_VERSION = "1.5.1+git"
PROVISION_VERSION = '5.2'
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from datetime import datetime, timedelta
import os

from flask import Flask, send_from_directory, g, request
from flask.ext.sqlalchemy import SQLAlchemy

import database

web_app = Flask(__name__)
web_app.config.from_object(os.environ['APP_SETTINGS'])
database.AppRepository.db = SQLAlchemy(web_app)
app_directory = os.path.join(os.getcwd(), 'app')
template_directory = os.path.join(app_directory, 'templates')
static_directory = os.path.join(app_directory, 'static')

import api, models
api.create_api(web_app)

DOMAIN = 'concept2.com.br'
# DOMAIN = 'localhost:8000'

@web_app.after_request
def add_header(r):
    """
    Add headers to both force latest IE rendering engine or Chrome Frame,
    and also to cache the rendered page for 10 minutes.
    """
    r.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
    r.headers["Pragma"] = "no-cache"
    r.headers["Expires"] = "0"
    r.headers['Access-Control-Allow-Origin'] = 'http://{}'.format(DOMAIN)
    r.headers['Access-Control-Allow-Credentials'] = 'true'
    r.headers['Access-Control-Allow-Headers'] = 'Content-Type,Authorization,Set-Cookie'
    r.headers['Access-Control-Expose-Headers'] = 'true'
    r.headers['Access-Control-Allow-Methods'] = ','.join(['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS'])
    r.headers['Access-Control-Max-Age'] = 21600
    user = g.get('user', None)
    if user is not None:
        token = user.gera_token_aut()
        expiration = datetime.utcnow() + timedelta(seconds=600)
        r.headers['TOKEN'] = token
        r.headers['USER'] = user.id
    else:
        r.headers['TOKEN'] = ''
        r.headers['USER'] = ''
    return r

@web_app.route('/', methods=['GET', 'POST'])
def index():
    return send_from_directory(template_directory, 'index.html')

@web_app.route('/angular/<path:template_path>', methods=['GET', 'POST'])
def angular_template(template_path):
    return send_from_directory(template_directory, template_path)

@web_app.route('/json/<json_name>', methods=['GET', 'POST'])
def angular_json(json_name):
    return web_app.send_static_file("js/app/jsons/{}".format(json_name))

@web_app.route('/favicon.ico', methods=['GET'])
def favicon():
    return web_app.send_static_file("img/favicon.ico")

@web_app.before_request
def before_request():
    token = request.cookies.get('XSRF-TOKEN', None)
    atleta = None
    if token:
        atleta = models.Atleta.verifica_token_aut(token)
    if atleta:
        g.user = atleta

@web_app.after_request
def after_request(resp):
    user = g.get('user', None)
    if user is not None:
        token = user.gera_token_aut()
        expiration = datetime.utcnow() + timedelta(seconds=600)
        resp.set_cookie('XSRF-TOKEN', token.decode('ascii'), expires=expiration, domain=DOMAIN)
        resp.set_cookie('USER_ID', str(user.id), expires=expiration, domain=DOMAIN)
    else:
        resp.set_cookie('XSRF-TOKEN', '', expires=0, domain=DOMAIN)
        resp.set_cookie('USER_ID', '', expires=0, domain=DOMAIN)
    return resp

def run():
    web_app.run(host='0.0.0.0', port=5000, debug=True)
<commit_msg>Problema no login<commit_after># -*- coding: utf-8 -*-
from datetime import datetime, timedelta
import os

from flask import Flask, send_from_directory, g, request
from flask.ext.sqlalchemy import SQLAlchemy

import database

web_app = Flask(__name__)
web_app.config.from_object(os.environ['APP_SETTINGS'])
database.AppRepository.db = SQLAlchemy(web_app)
app_directory = os.path.join(os.getcwd(), 'app')
template_directory = os.path.join(app_directory, 'templates')
static_directory = os.path.join(app_directory, 'static')

import api, models
api.create_api(web_app)

DOMAIN = 'concept2.com.br'
# DOMAIN = 'localhost:8000'

@web_app.after_request
def add_header(r):
    """
    Add headers to both force latest IE rendering engine or Chrome Frame,
    and also to cache the rendered page for 10 minutes.
    """
    r.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
    r.headers["Pragma"] = "no-cache"
    r.headers["Expires"] = "0"
    r.headers['Access-Control-Allow-Origin'] = 'http://{}'.format(DOMAIN)
    r.headers['Access-Control-Allow-Credentials'] = 'true'
    r.headers['Access-Control-Allow-Headers'] = 'Content-Type,Authorization,Set-Cookie'
    r.headers['Access-Control-Expose-Headers'] = 'Content-Type,Authorization,Set-Cookie,TOKEN,USER'
    r.headers['Access-Control-Allow-Methods'] = ','.join(['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS'])
    r.headers['Access-Control-Max-Age'] = 21600
    user = g.get('user', None)
    if user is not None:
        token = user.gera_token_aut()
        expiration = datetime.utcnow() + timedelta(seconds=600)
        r.headers['TOKEN'] = token
        r.headers['USER'] = user.id
    else:
        r.headers['TOKEN'] = ''
        r.headers['USER'] = ''
    return r

@web_app.route('/', methods=['GET', 'POST'])
def index():
    return send_from_directory(template_directory, 'index.html')

@web_app.route('/angular/<path:template_path>', methods=['GET', 'POST'])
def angular_template(template_path):
    return send_from_directory(template_directory, template_path)

@web_app.route('/json/<json_name>', methods=['GET', 'POST'])
def angular_json(json_name):
    return web_app.send_static_file("js/app/jsons/{}".format(json_name))

@web_app.route('/favicon.ico', methods=['GET'])
def favicon():
    return web_app.send_static_file("img/favicon.ico")

@web_app.before_request
def before_request():
    token = request.cookies.get('XSRF-TOKEN', None)
    atleta = None
    if token:
        atleta = models.Atleta.verifica_token_aut(token)
    if atleta:
        g.user = atleta

@web_app.after_request
def after_request(resp):
    user = g.get('user', None)
    if user is not None:
        token = user.gera_token_aut()
        expiration = datetime.utcnow() + timedelta(seconds=600)
        resp.set_cookie('XSRF-TOKEN', token.decode('ascii'), expires=expiration, domain=DOMAIN)
        resp.set_cookie('USER_ID', str(user.id), expires=expiration, domain=DOMAIN)
    else:
        resp.set_cookie('XSRF-TOKEN', '', expires=0, domain=DOMAIN)
        resp.set_cookie('USER_ID', '', expires=0, domain=DOMAIN)
    return resp

def run():
    web_app.run(host='0.0.0.0', port=5000, debug=True)
<|endoftext|>


<commit_before>import ustruct

from adafruit_bus_device import i2c_device
from micropython import const

_REGISTER_STATUS       = const(0x00)
_REGISTER_WHO_AM_I     = const(0x0D)
_REGISTER_XYZ_DATA_CFG = const(0x0E)
_REGISTER_CTRL_REG1    = const(0x2A)
_REGISTER_CTRL_REG2    = const(0x2B)
_REGISTER_MCTRL_REG1   = const(0x5B)
_REGISTER_MCTRL_REG2   = const(0x5C)

class FXOS8700:
    def __init__(self, i2c):
        self._buffer = bytearray(16)
        self._i2c = i2c_device.I2CDevice(i2c, 0x1F)

        # Make sure we have the correct chip ID
        ok = self._read_register(_REGISTER_WHO_AM_I, 1)[0] == 0xC7
        if not ok:
            print(self._buffer)
            raise ValueError("Unable to find FXOS8700 at i2c address 0x1F")

        # Set to standby mode (required to make changes to this register)
        self._write_register_byte(_REGISTER_CTRL_REG1, 0)

        # Configure the accelerometer
        self._write_register_byte(_REGISTER_XYZ_DATA_CFG, 0)

        # High resolution
        self._write_register_byte(_REGISTER_CTRL_REG2, 0x02)
        # Active, Normal Mode, Low Noise, 100Hz in Hybrid Mode
        self._write_register_byte(_REGISTER_CTRL_REG1, 0x15)

        # Configure the magnetometer
        # - Hybrid Mode, Over Sampling Rate = 16
        self._write_register_byte(_REGISTER_MCTRL_REG1, 0x1F)
        # - Jump to reg 0x33 after reading 0x06
        self._write_register_byte(_REGISTER_MCTRL_REG2, 0x20)

    def _read_register(self, register, length):
        self._buffer[0] = register & 0xFF
        with self._i2c as i2c:
            i2c.write(self._buffer, start=0, end=1, stop=False)
            i2c.read_into(self._buffer, start=0, end=length)
            return self._buffer

    def _write_register_byte(self, register, value):
        self._buffer[0] = register & 0xFF
        self._buffer[1] = value & 0xFF
        with self._i2c as i2c:
            i2c.write(self._buffer, start=0, end=2)

    @property
    def acceleration(self):
        self._read_register(_REGISTER_STATUS, 13)
        accelDataX, accelDataY, accelDataZ = ustruct.unpack('>hhh', self._buffer[1:7])
        d = 9.80665 * 0.000244 / 4
        return (d * accelDataX, d * accelDataY, d * accelDataZ)
<commit_msg>cleanup<commit_after>import ustruct

from adafruit_bus_device import i2c_device
from micropython import const

_REGISTER_STATUS       = const(0x00)
_REGISTER_WHO_AM_I     = const(0x0D)
_REGISTER_XYZ_DATA_CFG = const(0x0E)
_REGISTER_CTRL_REG1    = const(0x2A)
_REGISTER_CTRL_REG2    = const(0x2B)
_REGISTER_MCTRL_REG1   = const(0x5B)
_REGISTER_MCTRL_REG2   = const(0x5C)

class FXOS8700:
    def __init__(self, i2c):
        self._buffer = bytearray(16)
        self._i2c = i2c_device.I2CDevice(i2c, 0x1F)

        # Make sure we have the correct chip ID
        ok = self._read_register(_REGISTER_WHO_AM_I, 1)[0] == 0xC7
        if not ok:
            raise ValueError("Unable to find FXOS8700 at i2c address 0x1F")

        # Set to standby mode (required to make changes to this register)
        self._write_register_byte(_REGISTER_CTRL_REG1, 0)

        # Configure the accelerometer
        self._write_register_byte(_REGISTER_XYZ_DATA_CFG, 0)

        # High resolution
        self._write_register_byte(_REGISTER_CTRL_REG2, 0x02)
        # Active, Normal Mode, Low Noise, 100Hz in Hybrid Mode
        self._write_register_byte(_REGISTER_CTRL_REG1, 0x15)

        # Configure the magnetometer
        # - Hybrid Mode, Over Sampling Rate = 16
        self._write_register_byte(_REGISTER_MCTRL_REG1, 0x1F)
        # - Jump to reg 0x33 after reading 0x06
        self._write_register_byte(_REGISTER_MCTRL_REG2, 0x20)

    def _read_register(self, register, length):
        self._buffer[0] = register & 0xFF
        with self._i2c as i2c:
            i2c.write(self._buffer, start=0, end=1, stop=False)
            i2c.read_into(self._buffer, start=0, end=length)
            return self._buffer

    def _write_register_byte(self, register, value):
        self._buffer[0] = register & 0xFF
        self._buffer[1] = value & 0xFF
        with self._i2c as i2c:
            i2c.write(self._buffer, start=0, end=2)

    @property
    def acceleration(self):
        self._read_register(_REGISTER_STATUS, 13)
        accelDataX, accelDataY, accelDataZ = ustruct.unpack('>hhh', self._buffer[1:7])
        d = 9.80665 * 0.000244 / 4
        return (d * accelDataX, d * accelDataY, d * accelDataZ)
<|endoftext|>


<commit_before>from rpm2scl.decorators import matches
from rpm2scl.transformers.transformer import Transformer

class RubyTransformer(Transformer):
    def __init__(self, spec, options = None):
        super(RubyTransformer, self).__init__(spec, options)

    @matches(r'(gem (?:install)|(?:unpack)|(?:build))', one_line = False)
    @matches(r'(testrb )', one_line = False)
    @matches(r'(testrb2 )', one_line = False)
    @matches(r'((?<!-)rspec )', one_line = False) # avoid matching stuff like 'rubygem-rspec ' here
    def handle_ruby_specific_commands(self, pattern, text):
        return self.sclize_whole_command(pattern, text)
<commit_msg>Some minor adjustments in ruby specific patterns<commit_after>from rpm2scl.decorators import matches
from rpm2scl.transformers.transformer import Transformer

class RubyTransformer(Transformer):
    def __init__(self, spec, options = None):
        super(RubyTransformer, self).__init__(spec, options)

    @matches(r'gem (?:(?:install)|(?:unpack)|(?:build))', one_line = False)
    @matches(r'testrb ', one_line = False)
    @matches(r'testrb2 ', one_line = False)
    @matches(r'(?<!-)rspec ', one_line = False) # avoid matching stuff like 'rubygem-rspec ' here
    def handle_ruby_specific_commands(self, pattern, text):
        print pattern.search(text).groups()
        return self.sclize_whole_command(pattern, text)
<|endoftext|>


<commit_before># The MIT License (MIT)

# Copyright (c) 2014 Samuel Lucidi

# 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.

"""
validator.py

A library for validating that dictionary
values fit inside of certain sets of parameters.

Author: Samuel Lucidi <sam@samlucidi.com>

"""

__version__ = "1.1.0"

import re
from collections import defaultdict
from abc import ABCMeta, abstractmethod

def _isstr(s):
    """
    Python 2/3 compatible check to see
    if an object is a string type.

    """

    try:
        return isinstance(s, basestring)
    except NameError:
        return isinstance(s, str)

class Validator(object):
    """
    Abstract class that advanced
    validators can inherit from in order
    to set custom error messages and such.

    """

    __metaclass__ = ABCMeta

    err_message = "failed validation"
    not_message = "failed validation"

    @abstractmethod
    def __call__(self, *args, **kwargs):
        raise NotImplemented

class In(Validator):
    """
    Use to specify that the
    value of the key being
    validated must exist
    within the collection
    passed to this validator.

    # Example:
        validations = {
            "field": [In([1, 2, 3])]
        }
        passes = {"field":1}
        fails  = {"field":4}

    """

    def __init__(self, collection):
        self.collection = collection
        self.err_message = "must be one of %r" % collection
        self.not_message = "must not be one of %r" % collection

    def __call__(self, value):
        return (value in self.collection)

class Not(Validator):
    """
    Use to negate the requirement
    of another validator. Does not
    work with Required.

    """

    def __init__(self, validator):
        self.validator = validator
        self.err_message = getattr(validator, "not_message", "failed validation")
        self.not_message = getattr(validator, "err_message", "failed validation")

    def __call__(self, value):
        return not self.validator(value)

class Range(Validator):
    """
    Use to specify that the value of the
    key being validated must fall between
    the start and end values. By default
    the range is inclusive, though the
    range can be made excusive by setting
    inclusive to false.

    # Example:
        validations = {
            "field": [Range(0, 10)]
        }
        passes = {"field": 10}
        fails = {"field" : 11}

    """

    def __init__(self, start, end, inclusive=True):
        self.start = start
        self.end = end
        self.inclusive = inclusive
        self.err_message = "must fall between %s and %s" % (start, end)
        self.not_message = "must not fall between %s and %s" % (start, end)

    def __call__(self, value):
        if self.inclusive:
            return self.start <= value <= self.end
        else:
            return self.start < value < self.end

class Equals(Validator):
    """
    Use to specify that the
    value of the key being
    validated must be equal to
    the value that was passed
    to this validator.

    # Example:
        validations = {
            "field": [Equals(1)]
        }
        passes = {"field":1}
        fails  = {"field":4}

    """

    def __init__(self, obj):
        self.obj = obj
        self.err_message = "must be equal to %r" % obj
        self.not_message = "must not be equal to %r" % obj

    def __call__(self, value):
        return value == self.obj

class Blank(Validator):
    """
    Use to specify that the
    value of the key being
    validated must be equal to
    the empty string.

    This is a shortcut for saying
    Equals("").

    # Example:
        validations = {
            "field": [Blank()]
        }
        passes = {"field":""}
        fails  = {"field":"four"}

    """

    def __init__(self):
        self.err_message = "must be an empty string"
        self.not_message = "must not be an empty string"

    def __call__(self, value):
        return value == ""

class Truthy(Validator):
    """
    Use to specify that the
    value of the key being
    validated must be truthy,
    i.e. would cause an if statement
    to evaluate to True.

    # Example:
        validations = {
            "field": [Truthy()]
        }
        passes = {"field": 1}
        fails  = {"field": 0}

    """

    def __init__(self):
        self.err_message = "must be True-equivalent value"
        self.not_message = "must be False-equivalent value"

    def __call__(self, value):
        if value:
            return True
        else:
            return False

def Required(field, dictionary):
    """
    When added to a list of validations
    for a dictionary key indicates that
    the key must be present. This
    should not be called, just inserted
    into the list of validations.

    # Example:
        validations = {
            "field": [Required, Equals(2)]
        }

    By default, keys are considered
    optional and their validations
    will just be ignored if the field
    is not present in the dictionary
    in question.

    """

    return (field in dictionary)

class InstanceOf(Validator):
    """
    Use to specify that the
    value of the key being
    validated must be an instance
    of the passed in base class
    or its subclasses.

    # Example:
        validations = {
            "field": [InstanceOf(basestring)]
        }
        passes = {"field": ""} # is a <'str'>, subclass of basestring
        fails  = {"field": str} # is a <'type'>

    """

    def __init__(self, base_class):
        self.base_class = base_class
        self.err_message = "must be an instance of %s or its subclasses" % base_class.__name__
        self.not_message = "must not be an instance of %s or its subclasses" % base_class.__name__

    def __call__(self, value):
        return isinstance(value, self.base_class)

class SubclassOf(Validator):
    """
    Use to specify that the
    value of the key being
    validated must be a subclass
    of the passed in base class.

    # Example:
        validations = {
            "field": [SubclassOf(basestring)]
        }
        passes = {"field": str} # is a subclass of basestring
        fails  = {"field": int}

    """

    def __init__(self, base_class):
        self.base_class = base_class
        self.err_message = "must be a subclass of %s" % base_class.__name__
        self.not_message = "must not be a subclass of %s" % base_class.__name__

    def __call__(self, class_):
        return issubclass(class_, self.base_class)

class Pattern(Validator):
    """
    Use to specify that the
    value of the key being
    validated must match the
    pattern provided to the
    validator.

    # Example:
        validations = {
            "field": [Pattern('\d\d\%')]
        }
        passes = {"field": "30%"}
        fails  = {"field": "30"}

    """

    def __init__(self, pattern):
        self.pattern = pattern
        self.err_message = "must match regex pattern %s" % pattern
        self.not_message = "must not match regex pattern %s" % pattern
        self.compiled = re.compile(pattern)

    def __call__(self, value):
        return self.compiled.match(value)

class Then(Validator):
    """
    Special validator for use as
    part of the If rule.
    If the conditional part of the validation
    passes, then this is used to apply another
    set of dependent rules.

    # Example:
        validations = {
            "foo": [If(Equals(1), Then({"bar": [Equals(2)]}))]
        }
        passes = {"foo": 1, "bar": 2}
        also_passes = {"foo": 2, "bar": 3}
        fails = {"foo": 1, "bar": 3}
    """

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

    def __call__(self, dictionary):
        return validate(self.validation, dictionary)

class If(Validator):
    """
    Special conditional validator.
    If the validator passed as the first
    parameter to this function passes,
    then a second set of rules will be
    applied to the dictionary.

    # Example:
        validations = {
            "foo": [If(Equals(1), Then({"bar": [Equals(2)]}))]
        }
        passes = {"foo": 1, "bar": 2}
        also_passes = {"foo": 2, "bar": 3}
        fails = {"foo": 1, "bar": 3}
    """

    def __init__(self, validator, then_clause):
        self.validator = validator
        self.then_clause = then_clause

    def __call__(self, value, dictionary):
        conditional = False
        dependent = None
        if self.validator(value):
            conditional = True
            dependent = self.then_clause(dictionary)
        return conditional, dependent

class Length(Validator):
    """
    Use to specify that the
    value of the key being
    validated must have at least
    `minimum` elements and optionally
    at most `maximum` elements.

    At least one of the parameters
    to this validator must be non-zero,
    and neither may be negative.

    # Example:
        validations = {
            "field": [Length(0, maximum=5)]
        }
        passes = {"field": "hello"}
        fails  = {"field": "hello world"}

    """

    err_messages = {
        "maximum": "must be at most {0} elements in length",
        "minimum": "must be at least {0} elements in length",
        "range": "must{0}be between {1} and {2} elements in length"
    }

    def __init__(self, minimum, maximum=0):
        if not minimum and not maximum:
            raise ValueError("Length must have a non-zero minimum or maximum parameter.")
        if minimum < 0 or maximum < 0:
            raise ValueError("Length cannot have negative parameters.")

        self.minimum = minimum
        self.maximum = maximum
        if minimum and maximum:
            self.err_message = self.err_messages["range"].format(' ', minimum, maximum)
            self.not_message = self.err_messages["range"].format(' not ', minimum, maximum)
        elif minimum:
            self.err_message = self.err_messages["minimum"].format(minimum)
            self.not_message = self.err_messages["maximum"].format(minimum - 1)
        elif maximum:
            self.err_message = self.err_messages["maximum"].format(maximum)
            self.not_message = self.err_messages["minimum"].format(maximum + 1)

    def __call__(self, value):
        if self.maximum:
            return self.minimum <= len(value) <= self.maximum
        else:
            return self.minimum <= len(value)

class Contains(Validator):
    """
    Use to ensure that the value of the key
    being validated contains the value passed
    into the Contains validator. Works with
    any type that supports the 'in' syntax.

    # Example:
        validations = {
            "field": [Contains(3)]
        }
        passes = {"field": [1, 2, 3]}
        fails  = {"field": [4, 5, 6]}

    """

    def __init__(self, contained):
        self.contained = contained
        self.err_message = "must contain {0}".format(contained)
        self.not_message = "must not contain {0}".format(contained)

    def __call__(self, container):
        return self.contained in container

class Each(Validator):
    """
    Use to ensure that

    If Each is passed a list of validators, it
    just applies each of them to each element in
    the list.

    If it's instead passed a *dictionary*, it treats
    it as a validation to be applied to each element in
    the dictionary.

    """

    def __init__(self, validations):
        assert isinstance(validations, (list, tuple, set, dict))
        self.validations = validations

    def __call__(self, container):
        assert isinstance(container, (list, tuple, set))

        # handle the "apply simple validation to each in list"
        # use case
        if isinstance(self.validations, (list, tuple, set)):
            errors = []
            for item in container:
                for v in self.validations:
                    valid = v(item)
                    if not valid:
                        errors.append("all values " + v.err_message)

        # handle the somewhat messier list of dicts case
        if isinstance(self.validations, dict):
            errors = defaultdict(list)
            for index, item in enumerate(container):
                valid, err = validate(self.validations, item)
                if not valid:
                    errors[index] = err
            errors = dict(errors)

        return (len(errors) == 0, errors)

def validate(validation, dictionary):
    """
    Validate that a dictionary passes a set of
    key-based validators. If all of the keys
    in the dictionary are within the parameters
    specified by the validation mapping, then
    the validation passes.

    :param validation: a mapping of keys to validators
    :type validation: dict

    :param dictionary: dictionary to be validated
    :type dictionary: dict

    :return: a tuple containing a bool indicating
    success or failure and a mapping of fields
    to error messages.

    """

    errors = defaultdict(list)
    for key in validation:
        if isinstance(validation[key], (list, tuple)):
            if Required in validation[key]:
                if not Required(key, dictionary):
                    errors[key] = "must be present"
                    continue
            _validate_list_helper(validation, dictionary, key, errors)
        else:
            v = validation[key]
            if v == Required:
                if not Required(key, dictionary):
                    errors[key] = "must be present"
            else:
                _validate_and_store_errs(v, dictionary, key, errors)
    if len(errors) > 0:
        return False, dict(errors)
    else:
        return True, {}

def _validate_and_store_errs(validator, dictionary, key, errors):
    valid = validator(dictionary[key])
    if isinstance(valid, tuple):
        valid, errs = valid
        if errs and isinstance(errs, list):
            errors[key] += errs
        elif errs:
            errors[key].append(errs)
    elif not valid:
        # set a default error message for things like lambdas
        # and other callables that won't have an err_message set.
        msg = getattr(validator, "err_message", "failed validation")
        errors[key].append(msg)

def _validate_list_helper(validation, dictionary, key, errors):
    for v in validation[key]:
        # don't break on optional keys
        if key in dictionary:
            # Ok, need to deal with nested
            # validations.
            if isinstance(v, dict):
                valid, nested_errors = validate(v, dictionary[key])
                if nested_errors:
                    errors[key].append(nested_errors)
                continue

            # Done with that, on to the actual
            # validating bit.
            # Skip Required, since it was already
            # handled before this point.
            elif not v == Required:
                # special handling for the
                # If(Then()) form
                if isinstance(v, If):
                    conditional, dependent = v(dictionary[key], dictionary)
                    # if the If() condition passed and there were errors
                    # in the second set of rules, then add them to the
                    # list of errors for the key with the condtional
                    # as a nested dictionary of errors.
                    if conditional and dependent[1]:
                        errors[key].append(dependent[1])
                # handling for normal validators
                else:
                    _validate_and_store_errs(v, dictionary, key, errors)
<commit_msg>Undo remnants of removed change.<commit_after># The MIT License (MIT)

# Copyright (c) 2014 Samuel Lucidi

# 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.

"""
validator.py

A library for validating that dictionary
values fit inside of certain sets of parameters.

Author: Samuel Lucidi <sam@samlucidi.com>

"""

__version__ = "1.1.0"

import re
from collections import defaultdict
from abc import ABCMeta, abstractmethod

def _isstr(s):
    """
    Python 2/3 compatible check to see
    if an object is a string type.

    """

    try:
        return isinstance(s, basestring)
    except NameError:
        return isinstance(s, str)

class Validator(object):
    """
    Abstract class that advanced
    validators can inherit from in order
    to set custom error messages and such.

    """

    __metaclass__ = ABCMeta

    err_message = "failed validation"
    not_message = "failed validation"

    @abstractmethod
    def __call__(self, *args, **kwargs):
        raise NotImplemented

class In(Validator):
    """
    Use to specify that the
    value of the key being
    validated must exist
    within the collection
    passed to this validator.

    # Example:
        validations = {
            "field": [In([1, 2, 3])]
        }
        passes = {"field":1}
        fails  = {"field":4}

    """

    def __init__(self, collection):
        self.collection = collection
        self.err_message = "must be one of %r" % collection
        self.not_message = "must not be one of %r" % collection

    def __call__(self, value):
        return (value in self.collection)

class Not(Validator):
    """
    Use to negate the requirement
    of another validator. Does not
    work with Required.

    """

    def __init__(self, validator):
        self.validator = validator
        self.err_message = getattr(validator, "not_message", "failed validation")
        self.not_message = getattr(validator, "err_message", "failed validation")

    def __call__(self, value):
        return not self.validator(value)

class Range(Validator):
    """
    Use to specify that the value of the
    key being validated must fall between
    the start and end values. By default
    the range is inclusive, though the
    range can be made excusive by setting
    inclusive to false.

    # Example:
        validations = {
            "field": [Range(0, 10)]
        }
        passes = {"field": 10}
        fails = {"field" : 11}

    """

    def __init__(self, start, end, inclusive=True):
        self.start = start
        self.end = end
        self.inclusive = inclusive
        self.err_message = "must fall between %s and %s" % (start, end)
        self.not_message = "must not fall between %s and %s" % (start, end)

    def __call__(self, value):
        if self.inclusive:
            return self.start <= value <= self.end
        else:
            return self.start < value < self.end

class Equals(Validator):
    """
    Use to specify that the
    value of the key being
    validated must be equal to
    the value that was passed
    to this validator.

    # Example:
        validations = {
            "field": [Equals(1)]
        }
        passes = {"field":1}
        fails  = {"field":4}

    """

    def __init__(self, obj):
        self.obj = obj
        self.err_message = "must be equal to %r" % obj
        self.not_message = "must not be equal to %r" % obj

    def __call__(self, value):
        return value == self.obj

class Blank(Validator):
    """
    Use to specify that the
    value of the key being
    validated must be equal to
    the empty string.

    This is a shortcut for saying
    Equals("").

    # Example:
        validations = {
            "field": [Blank()]
        }
        passes = {"field":""}
        fails  = {"field":"four"}

    """

    def __init__(self):
        self.err_message = "must be an empty string"
        self.not_message = "must not be an empty string"

    def __call__(self, value):
        return value == ""

class Truthy(Validator):
    """
    Use to specify that the
    value of the key being
    validated must be truthy,
    i.e. would cause an if statement
    to evaluate to True.

    # Example:
        validations = {
            "field": [Truthy()]
        }
        passes = {"field": 1}
        fails  = {"field": 0}

    """

    def __init__(self):
        self.err_message = "must be True-equivalent value"
        self.not_message = "must be False-equivalent value"

    def __call__(self, value):
        if value:
            return True
        else:
            return False

def Required(field, dictionary):
    """
    When added to a list of validations
    for a dictionary key indicates that
    the key must be present. This
    should not be called, just inserted
    into the list of validations.

    # Example:
        validations = {
            "field": [Required, Equals(2)]
        }

    By default, keys are considered
    optional and their validations
    will just be ignored if the field
    is not present in the dictionary
    in question.

    """

    return (field in dictionary)

class InstanceOf(Validator):
    """
    Use to specify that the
    value of the key being
    validated must be an instance
    of the passed in base class
    or its subclasses.

    # Example:
        validations = {
            "field": [InstanceOf(basestring)]
        }
        passes = {"field": ""} # is a <'str'>, subclass of basestring
        fails  = {"field": str} # is a <'type'>

    """

    def __init__(self, base_class):
        self.base_class = base_class
        self.err_message = "must be an instance of %s or its subclasses" % base_class.__name__
        self.not_message = "must not be an instance of %s or its subclasses" % base_class.__name__

    def __call__(self, value):
        return isinstance(value, self.base_class)

class SubclassOf(Validator):
    """
    Use to specify that the
    value of the key being
    validated must be a subclass
    of the passed in base class.

    # Example:
        validations = {
            "field": [SubclassOf(basestring)]
        }
        passes = {"field": str} # is a subclass of basestring
        fails  = {"field": int}

    """

    def __init__(self, base_class):
        self.base_class = base_class
        self.err_message = "must be a subclass of %s" % base_class.__name__
        self.not_message = "must not be a subclass of %s" % base_class.__name__

    def __call__(self, class_):
        return issubclass(class_, self.base_class)

class Pattern(Validator):
    """
    Use to specify that the
    value of the key being
    validated must match the
    pattern provided to the
    validator.

    # Example:
        validations = {
            "field": [Pattern('\d\d\%')]
        }
        passes = {"field": "30%"}
        fails  = {"field": "30"}

    """

    def __init__(self, pattern):
        self.pattern = pattern
        self.err_message = "must match regex pattern %s" % pattern
        self.not_message = "must not match regex pattern %s" % pattern
        self.compiled = re.compile(pattern)

    def __call__(self, value):
        return self.compiled.match(value)

class Then(Validator):
    """
    Special validator for use as
    part of the If rule.
    If the conditional part of the validation
    passes, then this is used to apply another
    set of dependent rules.

    # Example:
        validations = {
            "foo": [If(Equals(1), Then({"bar": [Equals(2)]}))]
        }
        passes = {"foo": 1, "bar": 2}
        also_passes = {"foo": 2, "bar": 3}
        fails = {"foo": 1, "bar": 3}
    """

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

    def __call__(self, dictionary):
        return validate(self.validation, dictionary)

class If(Validator):
    """
    Special conditional validator.
    If the validator passed as the first
    parameter to this function passes,
    then a second set of rules will be
    applied to the dictionary.

    # Example:
        validations = {
            "foo": [If(Equals(1), Then({"bar": [Equals(2)]}))]
        }
        passes = {"foo": 1, "bar": 2}
        also_passes = {"foo": 2, "bar": 3}
        fails = {"foo": 1, "bar": 3}
    """

    def __init__(self, validator, then_clause):
        self.validator = validator
        self.then_clause = then_clause

    def __call__(self, value, dictionary):
        conditional = False
        dependent = None
        if self.validator(value):
            conditional = True
            dependent = self.then_clause(dictionary)
        return conditional, dependent

class Length(Validator):
    """
    Use to specify that the
    value of the key being
    validated must have at least
    `minimum` elements and optionally
    at most `maximum` elements.

    At least one of the parameters
    to this validator must be non-zero,
    and neither may be negative.

    # Example:
        validations = {
            "field": [Length(0, maximum=5)]
        }
        passes = {"field": "hello"}
        fails  = {"field": "hello world"}

    """

    err_messages = {
        "maximum": "must be at most {0} elements in length",
        "minimum": "must be at least {0} elements in length",
        "range": "must{0}be between {1} and {2} elements in length"
    }

    def __init__(self, minimum, maximum=0):
        if not minimum and not maximum:
            raise ValueError("Length must have a non-zero minimum or maximum parameter.")
        if minimum < 0 or maximum < 0:
            raise ValueError("Length cannot have negative parameters.")

        self.minimum = minimum
        self.maximum = maximum
        if minimum and maximum:
            self.err_message = self.err_messages["range"].format(' ', minimum, maximum)
            self.not_message = self.err_messages["range"].format(' not ', minimum, maximum)
        elif minimum:
            self.err_message = self.err_messages["minimum"].format(minimum)
            self.not_message = self.err_messages["maximum"].format(minimum - 1)
        elif maximum:
            self.err_message = self.err_messages["maximum"].format(maximum)
            self.not_message = self.err_messages["minimum"].format(maximum + 1)

    def __call__(self, value):
        if self.maximum:
            return self.minimum <= len(value) <= self.maximum
        else:
            return self.minimum <= len(value)

class Contains(Validator):
    """
    Use to ensure that the value of the key
    being validated contains the value passed
    into the Contains validator. Works with
    any type that supports the 'in' syntax.

    # Example:
        validations = {
            "field": [Contains(3)]
        }
        passes = {"field": [1, 2, 3]}
        fails  = {"field": [4, 5, 6]}

    """

    def __init__(self, contained):
        self.contained = contained
        self.err_message = "must contain {0}".format(contained)
        self.not_message = "must not contain {0}".format(contained)

    def __call__(self, container):
        return self.contained in container

class Each(Validator):
    """
    Use to ensure that

    If Each is passed a list of validators, it
    just applies each of them to each element in
    the list.

    If it's instead passed a *dictionary*, it treats
    it as a validation to be applied to each element in
    the dictionary.

    """

    def __init__(self, validations):
        assert isinstance(validations, (list, tuple, set, dict))
        self.validations = validations

    def __call__(self, container):
        assert isinstance(container, (list, tuple, set))

        # handle the "apply simple validation to each in list"
        # use case
        if isinstance(self.validations, (list, tuple, set)):
            errors = []
            for item in container:
                for v in self.validations:
                    valid = v(item)
                    if not valid:
                        errors.append("all values " + v.err_message)

        # handle the somewhat messier list of dicts case
        if isinstance(self.validations, dict):
            errors = defaultdict(list)
            for index, item in enumerate(container):
                valid, err = validate(self.validations, item)
                if not valid:
                    errors[index] = err
            errors = dict(errors)

        return (len(errors) == 0, errors)

def validate(validation, dictionary):
    """
    Validate that a dictionary passes a set of
    key-based validators. If all of the keys
    in the dictionary are within the parameters
    specified by the validation mapping, then
    the validation passes.

    :param validation: a mapping of keys to validators
    :type validation: dict

    :param dictionary: dictionary to be validated
    :type dictionary: dict

    :return: a tuple containing a bool indicating
    success or failure and a mapping of fields
    to error messages.

    """

    errors = defaultdict(list)
    for key in validation:
        if isinstance(validation[key], (list, tuple)):
            if Required in validation[key]:
                if not Required(key, dictionary):
                    errors[key] = "must be present"
                    continue
            _validate_list_helper(validation, dictionary, key, errors)
        else:
            v = validation[key]
            if v == Required:
                if not Required(key, dictionary):
                    errors[key] = "must be present"
            else:
                _validate_and_store_errs(v, dictionary, key, errors)
    if len(errors) > 0:
        return False, dict(errors)
    else:
        return True, {}

def _validate_and_store_errs(validator, dictionary, key, errors):
    valid = validator(dictionary[key])
    if isinstance(valid, tuple):
        valid, errs = valid
        if errs and isinstance(errs, list):
            errors[key] += errs
        elif errs:
            errors[key].append(errs)
    elif not valid:
        # set a default error message for things like lambdas
        # and other callables that won't have an err_message set.
        msg = getattr(validator, "err_message", "failed validation")
        errors[key].append(msg)

def _validate_list_helper(validation, dictionary, key, errors):
    for v in validation[key]:
        # don't break on optional keys
        if key in dictionary:
            # Ok, need to deal with nested
            # validations.
            if isinstance(v, dict):
                valid, nested_errors = validate(v, dictionary[key])
                if nested_errors:
                    errors[key].append(nested_errors)
                continue
            # Done with that, on to the actual
            # validating bit.
            # Skip Required, since it was already
            # handled before this point.
            if not v == Required:
                # special handling for the
                # If(Then()) form
                if isinstance(v, If):
                    conditional, dependent = v(dictionary[key], dictionary)
                    # if the If() condition passed and there were errors
                    # in the second set of rules, then add them to the
                    # list of errors for the key with the condtional
                    # as a nested dictionary of errors.
                    if conditional and dependent[1]:
                        errors[key].append(dependent[1])
                # handling for normal validators
                else:
                    _validate_and_store_errs(v, dictionary, key, errors)
<|endoftext|>