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

#This software is distributed under the Creative Commons license (CC0) version 1.0. A copy of this license should have been distributed with this software.
#The license can also be read online: <https://creativecommons.org/publicdomain/zero/1.0/>. If this online license differs from the license provided with this software, the license provided with this software should be applied.

import luna.plugins #To log messages, and raise a MetadataValidationError if the metadata is invalid.

_configurations = {}
"""
The configuration classes that have been registered here so far, keyed by their
identities.
"""

def register(identity, metadata):
	"""
	Registers a new configuration plug-in to track configuration with.

	This expects the metadata to already be verified as configuration's
	metadata.

	:param identity: The identity of the plug-in to register.
	:param metadata: The metadata of a configuration plug-in.
	"""
	if identity in _configurations:
		luna.plugins.api("logger").warning("Configuration {configuration} is already registered.", configuration=identity)
		return
	_configurations[identity] = metadata["configuration"]["class"]

def unregister(identity):
	"""
	Undoes the registration of a configuration plug-in.

	The configuration plug-in will no longer keep track of any configuration.
	Existing configuration will be stored persistently.

	:param identity: The identity of the plug-in to unregister.
	"""
	if identity not in _configurations:
		luna.plugins.api("logger").warning("Configuration {configuration} is not registered, so I can't unregister it.", configuration=identity)
		return
	del _configurations[identity] #The actual unregistration.

def validate_metadata(metadata):
	"""
	Validates whether the specified metadata is valid for configuration
	plug-ins.

	Configuration's metadata must have a ``configuration`` field, which must
	have a ``name`` entry and an ``instance`` entry. The ``instance`` entry must
	implement ``__getattr__``, ``serialise`` and ``deserialise``.

	:param metadata: The metadata to validate.
	:raises luna.plugins.MetadataValidationError: The metadata was invalid.
	"""
	if "configuration" not in metadata:
		raise luna.plugins.MetadataValidationError("This is not a configuration plug-in.")

	try:
		if "name" not in metadata["configuration"]:
			raise luna.plugins.MetadataValidationError("The configuration plug-in doesn't specify a name.")

		if "instance" not in metadata["configuration"]:
			raise luna.plugins.MetadataValidationError("The configuration plug-in doesn't specify an instance to keep track of the configuration.")
		instance_attributes = set(dir(metadata["configuration"]["instance"]))
		required_functions = {"__getattr__", "serialise", "deserialise"}
		if required_functions > instance_attributes: #Instance is not implementing all required functions.
			raise luna.plugins.MetadataValidationError("The configuration instance doesn't implement the required functions {functions}.".format(functions=", ".join(required_functions - instance_attributes)))
	except TypeError:
		raise luna.plugins.MetadataValidationError("The configuration metadata entry is not a dictionary.")<commit_msg>Move function check out of try-except block<commit_after>#!/usr/bin/env python
#-*- coding: utf-8 -*-

#This software is distributed under the Creative Commons license (CC0) version 1.0. A copy of this license should have been distributed with this software.
#The license can also be read online: <https://creativecommons.org/publicdomain/zero/1.0/>. If this online license differs from the license provided with this software, the license provided with this software should be applied.

import luna.plugins #To log messages, and raise a MetadataValidationError if the metadata is invalid.

_configurations = {}
"""
The configuration classes that have been registered here so far, keyed by their
identities.
"""

def register(identity, metadata):
	"""
	Registers a new configuration plug-in to track configuration with.

	This expects the metadata to already be verified as configuration's
	metadata.

	:param identity: The identity of the plug-in to register.
	:param metadata: The metadata of a configuration plug-in.
	"""
	if identity in _configurations:
		luna.plugins.api("logger").warning("Configuration {configuration} is already registered.", configuration=identity)
		return
	_configurations[identity] = metadata["configuration"]["class"]

def unregister(identity):
	"""
	Undoes the registration of a configuration plug-in.

	The configuration plug-in will no longer keep track of any configuration.
	Existing configuration will be stored persistently.

	:param identity: The identity of the plug-in to unregister.
	"""
	if identity not in _configurations:
		luna.plugins.api("logger").warning("Configuration {configuration} is not registered, so I can't unregister it.", configuration=identity)
		return
	del _configurations[identity] #The actual unregistration.

def validate_metadata(metadata):
	"""
	Validates whether the specified metadata is valid for configuration
	plug-ins.

	Configuration's metadata must have a ``configuration`` field, which must
	have a ``name`` entry and an ``instance`` entry. The ``instance`` entry must
	implement ``__getattr__``, ``serialise`` and ``deserialise``.

	:param metadata: The metadata to validate.
	:raises luna.plugins.MetadataValidationError: The metadata was invalid.
	"""
	if "configuration" not in metadata:
		raise luna.plugins.MetadataValidationError("This is not a configuration plug-in.")

	try:
		if "name" not in metadata["configuration"]:
			raise luna.plugins.MetadataValidationError("The configuration plug-in doesn't specify a name.")

		if "instance" not in metadata["configuration"]:
			raise luna.plugins.MetadataValidationError("The configuration plug-in doesn't specify an instance to keep track of the configuration.")
	except TypeError:
		raise luna.plugins.MetadataValidationError("The configuration metadata entry is not a dictionary.")
	instance_attributes = set(dir(metadata["configuration"]["instance"]))
	required_functions = {"__getattr__", "serialise", "deserialise"}
	if required_functions > instance_attributes: #Instance is not implementing all required functions.
		raise luna.plugins.MetadataValidationError("The configuration instance doesn't implement the required functions {functions}.".format(functions=", ".join(required_functions - instance_attributes)))<|endoftext|>


<commit_before>import datetime
import logging
import os

from collections import defaultdict
from typing import Dict, List, Union

from rubin_changelog.config import DEBUG, TARGET_DIR
from rubin_changelog.eups import Eups, EupsTag
from rubin_changelog.jira import JiraCache
from rubin_changelog.output import format_output
from rubin_changelog.products import Products
from rubin_changelog.repos_yaml import ReposYaml
from rubin_changelog.repository import Repository
from rubin_changelog.utils import tag_key

def print_tag(tag: EupsTag, added: List[str], dropped: List[str], tickets: Dict[str, List[str]]):
    print(f"
{tag.name}
")
    if tag.date:
        print(f"Released {tag.date}.")
    if not added and not dropped and not tickets:
        print("No changes in this version.")
    if added:
        print("
Products added
")
        print("
")
        for product_name in added:
            print(f"
{product_name}
")
        print("
")
    if dropped:
        print("
Products removed
")
        print("
")
        for product_name in dropped:
            print(f"
{product_name}
")
        print("
")
    if tickets:
        jira = JiraCache()
        print("
Tickets merged
")
        print("
")
        for ticket_id, products in tickets.items():
            print(f"
{ticket_id}: {jira[ticket_id]} [{', '.join(products)}]
")
        print("
")

def print_changelog(changelog: Dict[str, Dict[str, Union[str, List[str]]]]):
    print("")
    print("<title>Rubin Science Pipelines Weekly Changelog</title>")
    print("")
    print("
Rubin Science Pipelines Weekly Changelog
")

    for tag, values in changelog.items():
        print_tag(tag, **values)

    gen_date = datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M +00:00")
    print(f"
Generated at {gen_date} by considering {', '.join(eups.all_products)}.
")
    print("")
    print("")

def generate_changelog(eups: Eups) -> Dict[EupsTag, Dict[str, Union[str, List[str]]]]:
    products = Products()
    tags = sorted(eups.values(), reverse=True)
    tags.insert(0, EupsTag("master", None, tags[0].products))
    changelog = {}
    for new_tag, old_tag in zip(tags, tags[1:]):
        added = set(new_tag.products) - set(old_tag.products)
        dropped = set(old_tag.products) - set(new_tag.products)
        tickets = defaultdict(list)

        if new_tag.name != "master":
            # Timestamps on old EUPS tag lists are crazy; grab the true date from
            # an example repo (assuming that afw is universal!).
            try:
                new_tag.date = products['afw'].tag_date(new_tag.name.replace('_', '.'))
            except ValueError:
                pass

        for product_name in set(new_tag.products) & set(old_tag.products):
            try:
                product = products[product_name]
            except KeyError:
                logging.debug(f"Skipping ticket list on {product_name} (probably skiplisted)")
                continue
            old_ref_name = f"refs/tags/{old_tag.name.replace('_', '.')}"
            new_ref_name = f"refs/tags/{new_tag.name.replace('_', '.')}" if new_tag.name != "master" else products[product_name].branch_name
            merges = products[product_name].merges_between(old_ref_name, new_ref_name)
            for sha in merges:
                ticket = products[product_name].ticket(products[product_name].message(sha))
                if ticket:
                    tickets[ticket].append(product_name)
        changelog[new_tag] = {"added": added, "dropped": dropped, "tickets": tickets}
    return changelog

if __name__ == "__main__":
    if DEBUG:
        logging.basicConfig(level=logging.DEBUG)
    eups = Eups()
    print_changelog(generate_changelog(eups))
<commit_msg>Sort package list for printing<commit_after>import datetime
import logging
import os

from collections import defaultdict
from typing import Dict, List, Union

from rubin_changelog.config import DEBUG, TARGET_DIR
from rubin_changelog.eups import Eups, EupsTag
from rubin_changelog.jira import JiraCache
from rubin_changelog.output import format_output
from rubin_changelog.products import Products
from rubin_changelog.repos_yaml import ReposYaml
from rubin_changelog.repository import Repository
from rubin_changelog.utils import tag_key

def print_tag(tag: EupsTag, added: List[str], dropped: List[str], tickets: Dict[str, List[str]]):
    print(f"
{tag.name}
")
    if tag.date:
        print(f"Released {tag.date}.")
    if not added and not dropped and not tickets:
        print("No changes in this version.")
    if added:
        print("
Products added
")
        print("
")
        for product_name in added:
            print(f"
{product_name}
")
        print("
")
    if dropped:
        print("
Products removed
")
        print("
")
        for product_name in dropped:
            print(f"
{product_name}
")
        print("
")
    if tickets:
        jira = JiraCache()
        print("
Tickets merged
")
        print("
")
        for ticket_id, products in tickets.items():
            print(f"
{ticket_id}: {jira[ticket_id]} [{', '.join(products)}]
")
        print("
")

def print_changelog(changelog: Dict[str, Dict[str, Union[str, List[str]]]]):
    print("")
    print("<title>Rubin Science Pipelines Weekly Changelog</title>")
    print("")
    print("
Rubin Science Pipelines Weekly Changelog
")

    for tag, values in changelog.items():
        print_tag(tag, **values)

    gen_date = datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M +00:00")
    print(f"
Generated at {gen_date} by considering {', '.join(sorted(eups.all_products))}.
")
    print("")
    print("")

def generate_changelog(eups: Eups) -> Dict[EupsTag, Dict[str, Union[str, List[str]]]]:
    products = Products()
    tags = sorted(eups.values(), reverse=True)
    tags.insert(0, EupsTag("master", None, tags[0].products))
    changelog = {}
    for new_tag, old_tag in zip(tags, tags[1:]):
        added = set(new_tag.products) - set(old_tag.products)
        dropped = set(old_tag.products) - set(new_tag.products)
        tickets = defaultdict(list)

        if new_tag.name != "master":
            # Timestamps on old EUPS tag lists are crazy; grab the true date from
            # an example repo (assuming that afw is universal!).
            try:
                new_tag.date = products['afw'].tag_date(new_tag.name.replace('_', '.'))
            except ValueError:
                pass

        for product_name in set(new_tag.products) & set(old_tag.products):
            try:
                product = products[product_name]
            except KeyError:
                logging.debug(f"Skipping ticket list on {product_name} (probably skiplisted)")
                continue
            old_ref_name = f"refs/tags/{old_tag.name.replace('_', '.')}"
            new_ref_name = f"refs/tags/{new_tag.name.replace('_', '.')}" if new_tag.name != "master" else products[product_name].branch_name
            merges = products[product_name].merges_between(old_ref_name, new_ref_name)
            for sha in merges:
                ticket = products[product_name].ticket(products[product_name].message(sha))
                if ticket:
                    tickets[ticket].append(product_name)
        changelog[new_tag] = {"added": added, "dropped": dropped, "tickets": tickets}
    return changelog

if __name__ == "__main__":
    if DEBUG:
        logging.basicConfig(level=logging.DEBUG)
    eups = Eups()
    print_changelog(generate_changelog(eups))
<|endoftext|>


<commit_before>

import random

def Point(position):
    """ Create a valid GeoJSON Point geometry. """
    return {
       "type": "Point",
       "coordinates": position
    }

def Feature(geometry, properties=None):
    """ Create a valid GeoJSON Feature. """
    return {
        "type": "Feature",
        "geometry": geometry,
        "properties": properties
    }

def FeatureCollection(features=None):
    """ Create a valid GeoJSON FeatureCollection. """
    return {
        "type": "FeatureCollection",
        "features": [] if features is None else features
    }

def GeometryCollection(geometries=None):
    """ Create a valid GeoJSON GeometryCollection. """
    return {
        "type": "GeometryCollection",
        "geometries": [] if geometries is None else geometries
    }

def randomPosition():
    length = (round(random.random()*100)%6)+2
    return [(random.random()-0.5)*100 for i in range(int(length))]

def randomPointCoordinates():
    return randomPosition()

def randomMultiPointCoordinates():
    length = (round(random.random()*100)%6)+1
    return [randomPosition() for i in range(int(length))]

def randomLineStringCoordinates():
    length = (round(random.random()*100)%6)+2
    return [randomPosition() for i in range(int(length))]

def randomLinearRingCoordinates():
    origin = randomPosition()
    return [origin]+randomLineStringCoordinates()+[origin]

def randomMultiLineStringCoordinates():
    length = (round(random.random()*100)%6)+1
    return [randomLineStringCoordinates() for i in range(int(length))]

def randomPolygonCoordinates():  # TODO
    return [randomLinearRingCoordinates()] if random.random() < 0.5 else [
      [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ],
      [ [100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2] ]
    ]

def randomMultiPolygonCoordinates():
    length = (round(random.random()*100)%6)+1
    return [randomPolygonCoordinates() for i in range(int(length))]

def randomGeometry():
    return random.choice([
      randomPoint,
      randomMultiPoint,
      randomLineString,
      randomMultiLineString,
      randomPolygon,
      randomMultiPolygon,
      randomGeometryCollection
    ])()

def randomPoint():
    return {
        "type": "Point",
        "coordinates": randomPointCoordinates()
    }

def randomMultiPoint():
    return {
      "type": "MultiPoint",
      "coordinates": randomMultiPointCoordinates()
    }

def randomLineString():
    return {
      "type": "LineString",
      "coordinates": randomLineStringCoordinates()
    }

def randomMultiLineString():
    return {
      "type": "MultiLineString",
      "coordinates": randomMultiLineStringCoordinates()
    }

def randomPolygon():
    return {
      "type": "Polygon",
      "coordinates": randomPolygonCoordinates()
    }

def randomMultiPolygon():
    return {
      "type": "MultiPolygon",
      "coordinates": randomMultiPolygonCoordinates()
    }

def randomGeometryCollection():
    length = round(random.random()*100)%3
    return {
      "type": "GeometryCollection",
      "geometries": [randomGeometry() for i in range(int(length))]
    }

def randomFeature():
    return {
      "type": "Feature",
      "geometry": randomGeometry(),
      "properties": random.choice([None, {}, {'foo': 'bar'}])
    }

def randomFeatureCollection():
    length = round(random.random()*100)%3
    return {
      "type": "FeatureCollection",
      "features": [randomFeature() for i in range(int(length))]
    }

def randomCRS():  # TODO
    return {
        "type": "link",
        "properties": randomLink()
    } if random.random() < 0.5 else {
        "type": "name",
        "properties": {
            "name": "urn:ogc:def:crs:OGC:1.3:CRS84"
        }
    }

def randomLink():
    link = { "href": "data.crs" if random.random() < 0.5 else "http://example.com/crs/42" }
    if random.random() < 0.5:
        link["type"] = random.choice(["proj4", "ogcwkt", "esriwkt"])
    return link

def randomBbox():  # TODO
    return [-180.0, -90.0, 180.0, 90.0]

<commit_msg>Improve randomCRS.<commit_after>

import random

def Point(position):
    """ Create a valid GeoJSON Point geometry. """
    return {
       "type": "Point",
       "coordinates": position
    }

def Feature(geometry, properties=None):
    """ Create a valid GeoJSON Feature. """
    return {
        "type": "Feature",
        "geometry": geometry,
        "properties": properties
    }

def FeatureCollection(features=None):
    """ Create a valid GeoJSON FeatureCollection. """
    return {
        "type": "FeatureCollection",
        "features": [] if features is None else features
    }

def GeometryCollection(geometries=None):
    """ Create a valid GeoJSON GeometryCollection. """
    return {
        "type": "GeometryCollection",
        "geometries": [] if geometries is None else geometries
    }

def randomPosition():
    length = (round(random.random()*100)%6)+2
    return [(random.random()-0.5)*100 for i in range(int(length))]

def randomPointCoordinates():
    return randomPosition()

def randomMultiPointCoordinates():
    length = (round(random.random()*100)%6)+1
    return [randomPosition() for i in range(int(length))]

def randomLineStringCoordinates():
    length = (round(random.random()*100)%6)+2
    return [randomPosition() for i in range(int(length))]

def randomLinearRingCoordinates():
    origin = randomPosition()
    return [origin]+randomLineStringCoordinates()+[origin]

def randomMultiLineStringCoordinates():
    length = (round(random.random()*100)%6)+1
    return [randomLineStringCoordinates() for i in range(int(length))]

def randomPolygonCoordinates():  # TODO
    return [randomLinearRingCoordinates()] if random.random() < 0.5 else [
      [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ],
      [ [100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2] ]
    ]

def randomMultiPolygonCoordinates():
    length = (round(random.random()*100)%6)+1
    return [randomPolygonCoordinates() for i in range(int(length))]

def randomGeometry():
    return random.choice([
      randomPoint,
      randomMultiPoint,
      randomLineString,
      randomMultiLineString,
      randomPolygon,
      randomMultiPolygon,
      randomGeometryCollection
    ])()

def randomPoint():
    return {
        "type": "Point",
        "coordinates": randomPointCoordinates()
    }

def randomMultiPoint():
    return {
      "type": "MultiPoint",
      "coordinates": randomMultiPointCoordinates()
    }

def randomLineString():
    return {
      "type": "LineString",
      "coordinates": randomLineStringCoordinates()
    }

def randomMultiLineString():
    return {
      "type": "MultiLineString",
      "coordinates": randomMultiLineStringCoordinates()
    }

def randomPolygon():
    return {
      "type": "Polygon",
      "coordinates": randomPolygonCoordinates()
    }

def randomMultiPolygon():
    return {
      "type": "MultiPolygon",
      "coordinates": randomMultiPolygonCoordinates()
    }

def randomGeometryCollection():
    length = round(random.random()*100)%3
    return {
      "type": "GeometryCollection",
      "geometries": [randomGeometry() for i in range(int(length))]
    }

def randomFeature():
    return {
      "type": "Feature",
      "geometry": randomGeometry(),
      "properties": random.choice([None, {}, {'foo': 'bar'}])
    }

def randomFeatureCollection():
    length = round(random.random()*100)%3
    return {
      "type": "FeatureCollection",
      "features": [randomFeature() for i in range(int(length))]
    }

def randomCRS():  # TODO
    return {
        "type": "link",
        "properties": randomLink()
    } if random.random() < 0.5 else {
        "type": "name",
        "properties": {
            "name": "urn:ogc:def:crs:OGC:1.3:CRS84" if random.random() < 0.5 else "EPSG:4326"
        }
    }

def randomLink():
    link = { "href": "data.crs" if random.random() < 0.5 else "http://example.com/crs/42" }
    if random.random() < 0.5:
        link["type"] = random.choice(["proj4", "ogcwkt", "esriwkt"])
    return link

def randomBbox():  # TODO
    return [-180.0, -90.0, 180.0, 90.0]

<|endoftext|>


<commit_before>"""Write new stories based on inputted text using trigram algo."""
from random import sample
import re

sentence = 'I wish I may I wish I might'

def open_file(filename):
    fp = open(filename)
    clean_para = []
    for line in fp:
        cleanline = re.sub('-', ' ', line)
        clean_line = ''.join(c for c in cleanline if c not in '(),.')
        clean_para.append(clean_line)
    return clean_para

#make_baselist(clean_line)
def make_baselist(sentence):
    """Create baselist from an inputted sentence."""
    baselist = sentence.split()
    return baselist

def make_bigram(baselist):
    """Make bigrams out of an ordinary list."""
    bigrams = []
    for i in range(len(baselist) - 1):
            bigrams.append(baselist[i] + ' ' + baselist[i + 1])
    return bigrams

def make_dict(bigrams):
    """Build dictonary with bigram keys."""
    bigram_dict = {}
    for each in bigrams:
        bigram_dict.setdefault(each, [])
    return bigram_dict

def populate_dict(the_dict, bigram_list, word_list):
    """Populate dictonary values with words from wordlist."""
    for idx, item in enumerate(bigram_list):
        if idx + 1 == len(bigram_list):
            return the_dict
        new_value = word_list[idx + 2]
        the_dict[item].append(new_value)

def start_output(bigram_list):
    """The function takes one random bigram for the start of output."""
    a = sample(bigram_list, 1)
    output = ''.join(a)
    return output

def add_output(the_dict, output, n):
    """The function takes a value from the bigram list to make trigram."""
    final_list = output.split(' ')
    while len(final_list) < n:
        two_words = final_list[-2] + ' ' + final_list[-1]
        if the_dict[two_words]:
            add_word = sample(the_dict[two_words], 1)
        else:
            return ' '.join(final_list)
        final_list += add_word
    return ' '.join(final_list)
<commit_msg>main changes<commit_after>"""Write new stories based on inputted text using trigram algo."""
from random import sample
import re

sentence = 'I wish I may I wish I might'

def open_file(filename):
    """Return list of words free of special characters."""
    fp = open(filename)
    clean_para = []
    for line in fp:
        cleanline = re.sub('-', ' ', line)
        clean_line = ''.join(c for c in cleanline if c not in '(),.')
        clean_para.append(clean_line)
    return clean_para

def make_baselist(sentence):
    """Create baselist from an inputted sentence."""
    baselist = sentence.split()
    return baselist

def make_bigram(baselist):
    """Make bigrams out of an ordinary list."""
    bigrams = []
    for i in range(len(baselist) - 1):
            bigrams.append(baselist[i] + ' ' + baselist[i + 1])
    return bigrams

def make_dict(bigrams):
    """Build dictonary with bigram keys."""
    bigram_dict = {}
    for each in bigrams:
        bigram_dict.setdefault(each, [])
    return bigram_dict

def populate_dict(the_dict, bigram_list, word_list):
    """Populate dictonary values with words from wordlist."""
    for idx, item in enumerate(bigram_list):
        if idx + 1 == len(bigram_list):
            return the_dict
        new_value = word_list[idx + 2]
        the_dict[item].append(new_value)

def start_output(bigram_list):
    """The function takes one random bigram for the start of output."""
    a = sample(bigram_list, 1)
    output = ''.join(a)
    return output

def add_output(the_dict, output, n):
    """The function takes a value from the bigram list to make trigram."""
    final_list = output.split(' ')
    while len(final_list) < n:
        two_words = final_list[-2] + ' ' + final_list[-1]
        if the_dict[two_words]:
            add_word = sample(the_dict[two_words], 1)
        else:
            return ' '.join(final_list)
        final_list += add_word
    return ' '.join(final_list)

def main(filename, n):
    """The function initiates our trigram algorithm."""
    base_list = open_file(filename)
    bigrams = make_bigram(base_list)
    the_dict = make_dict(bigrams)
    new_dict = populate_dict(the_dict, bigrams, base_list)
    output = start_output(bigrams)
    paragraph = add_output(new_dict, output, n)
    if len(paragraph) < n:
        paragraph += start_output(bigrams)
        paragraph += add_output(new_dict, output, n)
    print(paragraph)
<|endoftext|>


<commit_before>import sys
sys.path.insert(0, '.')

activate_this = 'virtualenv/bin/activate_this.py'
execfile(activate_this, dict(__file__=activate_this))

import openmoves
application = openmoves.init(configFile='openmoves.cfg')

assert 'ADMINS' in application.config, 'no admins configured'
admins = application.config['ADMINS']

assert 'SYSTEM_SENDER_ADDRESS' in application.config, 'no system sender address configured'
systemSenderAddress = application.config['SYSTEM_SENDER_ADDRESS']

smtpServer = application.config['SMTP_SERVER']

# http://flask.pocoo.org/docs/errorhandling/
if not application.debug:
    import logging
    from logging.handlers import SMTPHandler
    mail_handler = SMTPHandler(smtpServer, systemSenderAddress, admins, 'openmoves.net application error')
    mail_handler.setLevel(logging.ERROR)
    application.logger.addHandler(mail_handler)
<commit_msg>fixup 3327d2d. #11<commit_after>import sys
sys.path.insert(0, '.')

activate_this = 'virtualenv/bin/activate_this.py'
execfile(activate_this, dict(__file__=activate_this))

import openmoves
application = openmoves.init(config_file='openmoves.cfg')

assert 'ADMINS' in application.config, 'no admins configured'
admins = application.config['ADMINS']

assert 'SYSTEM_SENDER_ADDRESS' in application.config, 'no system sender address configured'
system_sender_address = application.config['SYSTEM_SENDER_ADDRESS']

smtp_server = application.config['SMTP_SERVER']

# http://flask.pocoo.org/docs/errorhandling/
if not application.debug:
    import logging
    from logging.handlers import SMTPHandler
    mail_handler = SMTPHandler(smtp_server, system_sender_address, admins, 'openmoves.net application error')
    mail_handler.setLevel(logging.ERROR)
    application.logger.addHandler(mail_handler)
<|endoftext|>


<commit_before>"""
Core abstractions used in OpenNSA.

Author: Henrik Thostrup Jensen <htj@nordu.net>
Copyright: NORDUnet (2011)
"""

import urlparse

from opennsa import error

STP_PREFIX = 'urn:ogf:network:stp:'
NSA_PREFIX = 'urn:ogf:network:nsa:'

class STP: # Service Termination Point

    def __init__(self, network, endpoint):
        self.network = network
        self.endpoint = endpoint

    def urn(self):
        return STP_PREFIX + self.network + ':' + self.endpoint

    def __eq__(self, other):
        if not isinstance(other, STP):
            return False
        return self.network == other.network and self.endpoint == other.endpoint

    def __str__(self):
        return '<STP %s:%s>' % (self.network, self.endpoint)

class SDP: # service demarcation point
    # This abstraction is only used in the topology module these days
    # It is rather backwards to work with except for pathfinding

    def __init__(self, stp1, stp2):
        self.stp1 = stp1
        self.stp2 = stp2

    def __eq__(self, other):
        if not isinstance(other, SDP):
            return False
        return self.stp1 == other.stp1 and self.stp2 == other.stp2

    def __str__(self):
        return '<SDP %s:%s-%s:%s>' % (self.stp1.network, self.stp1.endpoint, self.stp2.network, self.stp2.endpoint)

class Link: # intra network link

    def __init__(self, stp1, stp2):
        assert stp1.network == stp2.network, 'Refusing to creating STP pair with STPs with different network'
        self.stp1 = stp1
        self.stp2 = stp2

    def __eq__(self, other):
        if not isinstance(other, Link):
            return False
        return self.stp1 == other.stp1 and self.stp2 == other.stp2

    def __str__(self):
        return '<Link %s::%s=%s>' % (self.stp1.network, self.stp1.endpoint, self.stp2.endpoint)

class Path:
    """
    Represent a path from a source and destitionation STP, with the endpoint pairs between them.
    """
    def __init__(self, network_links):
        self.network_links = network_links

    def links(self):
        return self.network_links

    def sourceEndpoint(self):
        return self.network_links[0].stp1

    def destEndpoint(self):
        return self.network_links[-1].stp2

    def __str__(self):
        return ' - '.join( [ str(nl) for nl in self.network_links ] )

class NetworkEndpoint(STP):

    def __init__(self, network, endpoint, nrm_port=None, dest_stp=None, max_capacity=None, available_capacity=None):
        STP.__init__(self, network, endpoint)
        self.nrm_port = nrm_port # this is config as well - at least for now
        self.dest_stp = dest_stp
        self.max_capacity = max_capacity
        self.available_capacity = available_capacity

    def nrmPort(self):
        if self.nrm_port:
            return self.nrm_port
        else:
            return self.endpoint

    def __str__(self):
        return '<NetworkEndpoint %s:%s-%s#%s>' % (self.network, self.endpoint, self.dest_stp, self.nrm_port)

class NetworkServiceAgent:

    def __init__(self, identity, endpoint): #, service_attributes=None):
        assert type(identity) is str, 'NSA identity type must be string'
        assert type(endpoint) is str, 'NSA endpoint type must be string'
        self.identity = identity
        self.endpoint = endpoint

    def getHostPort(self):
        url = urlparse.urlparse(self.address)
        host, port = url.netloc.split(':',2)
        port = int(port)
        return host, port

    def url(self):
        return self.endpoint

    def urn(self):
        return NSA_PREFIX + self.identity

    def __str__(self):
        return '<NetworkServiceAgent %s>' % self.identity

class Network:

    def __init__(self, name, nsa):
        self.name = name
        self.nsa = nsa
        self.endpoints = []

    def addEndpoint(self, endpoint):
        self.endpoints.append(endpoint)

    def getEndpoint(self, endpoint_name):
        for ep in self.endpoints:
            if ep.endpoint == endpoint_name:
                return ep

        raise error.TopologyError('No such endpoint (%s)' % (endpoint_name))

    def __str__(self):
        return '<Network %s,%i>' % (self.name, len(self.endpoints))

class BandwidthParameters:

    def __init__(self, desired=None, minimum=None, maximum=None):
        self.desired = desired
        self.minimum = minimum
        self.maximum = maximum

class ServiceParameters:

    def __init__(self, start_time, end_time, source_stp, dest_stp, stps=None, directionality='Bidirectional', bandwidth=None):

        # should probably make path object sometime..

        # schedule
        self.start_time = start_time
        self.end_time   = end_time
        # path
        self.source_stp = source_stp
        self.dest_stp   = dest_stp
        self.stps       = stps
        assert directionality in ('Unidirectional', 'Bidirectional')
        self.directionality = directionality

        self.bandwidth = bandwidth or BandwidthParameters()

    def subConnectionClone(self, source_stp, dest_stp):
        return ServiceParameters(self.start_time, self.end_time, source_stp, dest_stp, None, self.directionality, self.bandwidth)

    def protoSP(self):
        return { 'start_time' : self.start_time,
                 'end_time'   : self.end_time,
                 'source_stp' : self.source_stp.urn(),
                 'dest_stp'   : self.dest_stp.urn(),
                 'stps'       : self.stps        }

    def __str__(self):
        return '<ServiceParameters %s>' % str(self.protoSP())

<commit_msg>issue warning for nrm port is missing for endpoint (nrm port will be required at some point)<commit_after>"""
Core abstractions used in OpenNSA.

Author: Henrik Thostrup Jensen <htj@nordu.net>
Copyright: NORDUnet (2011)
"""

import urlparse

from twisted.python import log

from opennsa import error

STP_PREFIX = 'urn:ogf:network:stp:'
NSA_PREFIX = 'urn:ogf:network:nsa:'

LOG_SYSTEM = 'opennsa.nsa'

class STP: # Service Termination Point

    def __init__(self, network, endpoint):
        self.network = network
        self.endpoint = endpoint

    def urn(self):
        return STP_PREFIX + self.network + ':' + self.endpoint

    def __eq__(self, other):
        if not isinstance(other, STP):
            return False
        return self.network == other.network and self.endpoint == other.endpoint

    def __str__(self):
        return '<STP %s:%s>' % (self.network, self.endpoint)

class SDP: # service demarcation point
    # This abstraction is only used in the topology module these days
    # It is rather backwards to work with except for pathfinding

    def __init__(self, stp1, stp2):
        self.stp1 = stp1
        self.stp2 = stp2

    def __eq__(self, other):
        if not isinstance(other, SDP):
            return False
        return self.stp1 == other.stp1 and self.stp2 == other.stp2

    def __str__(self):
        return '<SDP %s:%s-%s:%s>' % (self.stp1.network, self.stp1.endpoint, self.stp2.network, self.stp2.endpoint)

class Link: # intra network link

    def __init__(self, stp1, stp2):
        assert stp1.network == stp2.network, 'Refusing to creating STP pair with STPs with different network'
        self.stp1 = stp1
        self.stp2 = stp2

    def __eq__(self, other):
        if not isinstance(other, Link):
            return False
        return self.stp1 == other.stp1 and self.stp2 == other.stp2

    def __str__(self):
        return '<Link %s::%s=%s>' % (self.stp1.network, self.stp1.endpoint, self.stp2.endpoint)

class Path:
    """
    Represent a path from a source and destitionation STP, with the endpoint pairs between them.
    """
    def __init__(self, network_links):
        self.network_links = network_links

    def links(self):
        return self.network_links

    def sourceEndpoint(self):
        return self.network_links[0].stp1

    def destEndpoint(self):
        return self.network_links[-1].stp2

    def __str__(self):
        return ' - '.join( [ str(nl) for nl in self.network_links ] )

class NetworkEndpoint(STP):

    def __init__(self, network, endpoint, nrm_port=None, dest_stp=None, max_capacity=None, available_capacity=None):
        STP.__init__(self, network, endpoint)
        if nrm_port is None:
            log.msg('Warning: NRM Port for %s is undefined' % endpoint)
        self.nrm_port = nrm_port
        self.dest_stp = dest_stp
        self.max_capacity = max_capacity
        self.available_capacity = available_capacity

    def nrmPort(self):
        if self.nrm_port:
            return self.nrm_port
        else:
            return self.endpoint

    def __str__(self):
        return '<NetworkEndpoint %s:%s-%s#%s>' % (self.network, self.endpoint, self.dest_stp, self.nrm_port)

class NetworkServiceAgent:

    def __init__(self, identity, endpoint): #, service_attributes=None):
        assert type(identity) is str, 'NSA identity type must be string'
        assert type(endpoint) is str, 'NSA endpoint type must be string'
        self.identity = identity
        self.endpoint = endpoint

    def getHostPort(self):
        url = urlparse.urlparse(self.address)
        host, port = url.netloc.split(':',2)
        port = int(port)
        return host, port

    def url(self):
        return self.endpoint

    def urn(self):
        return NSA_PREFIX + self.identity

    def __str__(self):
        return '<NetworkServiceAgent %s>' % self.identity

class Network:

    def __init__(self, name, nsa):
        self.name = name
        self.nsa = nsa
        self.endpoints = []

    def addEndpoint(self, endpoint):
        self.endpoints.append(endpoint)

    def getEndpoint(self, endpoint_name):
        for ep in self.endpoints:
            if ep.endpoint == endpoint_name:
                return ep

        raise error.TopologyError('No such endpoint (%s)' % (endpoint_name))

    def __str__(self):
        return '<Network %s,%i>' % (self.name, len(self.endpoints))

class BandwidthParameters:

    def __init__(self, desired=None, minimum=None, maximum=None):
        self.desired = desired
        self.minimum = minimum
        self.maximum = maximum

class ServiceParameters:

    def __init__(self, start_time, end_time, source_stp, dest_stp, stps=None, directionality='Bidirectional', bandwidth=None):

        # should probably make path object sometime..

        # schedule
        self.start_time = start_time
        self.end_time   = end_time
        # path
        self.source_stp = source_stp
        self.dest_stp   = dest_stp
        self.stps       = stps
        assert directionality in ('Unidirectional', 'Bidirectional')
        self.directionality = directionality

        self.bandwidth = bandwidth or BandwidthParameters()

    def subConnectionClone(self, source_stp, dest_stp):
        return ServiceParameters(self.start_time, self.end_time, source_stp, dest_stp, None, self.directionality, self.bandwidth)

    def protoSP(self):
        return { 'start_time' : self.start_time,
                 'end_time'   : self.end_time,
                 'source_stp' : self.source_stp.urn(),
                 'dest_stp'   : self.dest_stp.urn(),
                 'stps'       : self.stps        }

    def __str__(self):
        return '<ServiceParameters %s>' % str(self.protoSP())

<|endoftext|>


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

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

import hashlib
import tempfile

try:
    from PIL import Image
except ImportError:
    raise ImportError('Please install python-imaging')

class VirtKeyboardError(Exception):
    pass

class VirtKeyboard(object):
    def __init__(self, file=None, coords=None, color=None, convert=None):
        # file: virtual keyboard image
        # coords: dictionary <value to return>:<tuple(x1,y1,x2,y2)>
        # color: color of the symbols in the image
        #        depending on the image, it can be a single value or a tuple
        # convert: if not None, convert image to this target type (for example 'RGB')

        if file is not None:
            assert color, 'No color provided !'
            self.load_image(file, color, convert)

        if coords is not None:
            self.load_symbols(coords)

    def load_image(self, file, color, convert=None):
        self.image = Image.open(file)

        if convert is not None:
            self.image = self.image.convert(convert)

        self.bands = self.image.getbands()
        if isinstance(color, int) and not isinstance(self.bands, str) and len(self.bands) != 1:
            raise VirtKeyboardError("Color requires %i component but only 1 is provided"
                                    % len(self.bands))
        if not isinstance(color, int) and len(color) != len(self.bands):
            raise VirtKeyboardError("Color requires %i components but %i are provided"
                                    % (len(self.bands), len(color)))
        self.color = color

        self.width, self.height = self.image.size
        self.pixar = self.image.load()

    def load_symbols(self, coords):
        self.coords = {}
        self.md5 = {}
        for i in coords:
            coord = self.get_symbol_coords(coords[i])
            if coord == (-1, -1, -1, -1):
                continue
            self.coords[i] = coord
            self.md5[i] = self.checksum(self.coords[i])

    def check_color(self, pixel):
        return pixel == self.color

    def get_symbol_coords(self, (x1, y1, x2, y2)):
        newY1 = -1
        newY2 = -1
        for y in range(y1, min(y2 + 1, self.height)):
            empty_line = True
            for x in range(x1, min(x2 + 1, self.width)):
                if self.check_color(self.pixar[x, y]):
                    empty_line = False
                    if newY1 == -1:
                        newY1 = y
                        break
                    else:
                        break
            if newY1 != -1 and not empty_line:
                newY2 = y
        newX1 = -1
        newX2 = -1
        for x in range(x1, min(x2 + 1, self.width)):
            empty_column = True
            for y in range(y1, min(y2 + 1, self.height)):
                if self.check_color(self.pixar[x, y]):
                    empty_column = False
                    if newX1 == -1:
                        newX1 = x
                        break
                    else:
                        break
            if newX1 != -1 and not empty_column:
                newX2 = x
        return (newX1, newY1, newX2, newY2)

    def checksum(self, (x1, y1, x2, y2)):
        s = ''
        for y in range(y1, min(y2 + 1, self.height)):
            for x in range(x1, min(x2 + 1, self.width)):
                if self.check_color(self.pixar[x, y]):
                    s += "."
                else:
                    s += " "
        return hashlib.md5(s).hexdigest()

    def get_symbol_code(self, md5sum):
        for i in self.md5:
            if md5sum == self.md5[i]:
                return i
        raise VirtKeyboardError('Symbol not found')

    def check_symbols(self, symbols, dirname):
        # symbols: dictionary <symbol>:<md5 value>
        for s in symbols:
            try:
                self.get_symbol_code(symbols[s])
            except VirtKeyboardError:
                if dirname is None:
                    dirname = tempfile.mkdtemp(prefix='weboob_session_')
                self.generate_MD5(dirname)
                raise VirtKeyboardError("Symbol '%s' not found; all symbol hashes are available in %s"
                                        % (s, dirname))

    def generate_MD5(self, dir):
        for i in self.coords:
            width = self.coords[i][2] - self.coords[i][0] + 1
            height = self.coords[i][3] - self.coords[i][1] + 1
            img = Image.new(''.join(self.bands), (width, height))
            matrix = img.load()
            for y in range(height):
                for x in range(width):
                    matrix[x, y] = self.pixar[self.coords[i][0] + x, self.coords[i][1] + y]
            img.save(dir + "/" + self.md5[i] + ".png")

class MappedVirtKeyboard(VirtKeyboard):
    def __init__(self, file, document, img_element, color, map_attr="onclick", convert=None):
        map_id = img_element.attrib.get("usemap")[1:]
        map = document.find("//map[@id='" + map_id + "']")
        if map is None:
            map = document.find("//map[@name='" + map_id + "']")

        coords = {}
        for area in map.getiterator("area"):
            code = area.attrib.get(map_attr)
            area_coords = []
            for coord in area.attrib.get("coords").split(','):
                area_coords.append(int(coord))
            coords[code] = tuple(area_coords)

        super(MappedVirtKeyboard, self).__init__(file, coords, color, convert)
<commit_msg>add a margin attribute<commit_after># -*- coding: utf-8 -*-

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

import hashlib
import tempfile

try:
    from PIL import Image
except ImportError:
    raise ImportError('Please install python-imaging')

class VirtKeyboardError(Exception):
    pass

class VirtKeyboard(object):
    """
    Handle a virtual keyboard.

    :attribute margin: Margin used by :meth:`get_symbol_coords̀` to reduce size
        of each "key" of the virtual keyboard. This attribute is always
        converted to a 4-tuple, and has the same semantic as the CSS
        margin property (top, right, bottom, right).
    :type margin: int or float or (2|3|4)-tuple
    """
    margin = None

    def __init__(self, file=None, coords=None, color=None, convert=None):
        # file: virtual keyboard image
        # coords: dictionary <value to return>:<tuple(x1,y1,x2,y2)>
        # color: color of the symbols in the image
        #        depending on the image, it can be a single value or a tuple
        # convert: if not None, convert image to this target type (for example 'RGB')

        if file is not None:
            assert color, 'No color provided !'
            self.load_image(file, color, convert)

        if type(self.margin) in (int, float):
            self.margin = (self.margin,) * 4
        elif self.margin is not None:
            if len(self.margin) == 2:
                self.margin = self.margin + self.margin
            elif len(self.margin) == 3:
                self.margin = self.margin + (self.margin[1],)
            assert len(self.margin) == 4

        if coords is not None:
            self.load_symbols(coords)

    def load_image(self, file, color, convert=None):
        self.image = Image.open(file)

        if convert is not None:
            self.image = self.image.convert(convert)

        self.bands = self.image.getbands()
        if isinstance(color, int) and not isinstance(self.bands, str) and len(self.bands) != 1:
            raise VirtKeyboardError("Color requires %i component but only 1 is provided"
                                    % len(self.bands))
        if not isinstance(color, int) and len(color) != len(self.bands):
            raise VirtKeyboardError("Color requires %i components but %i are provided"
                                    % (len(self.bands), len(color)))
        self.color = color

        self.width, self.height = self.image.size
        self.pixar = self.image.load()

    def load_symbols(self, coords):
        self.coords = {}
        self.md5 = {}
        for i in coords:
            coord = self.get_symbol_coords(coords[i])
            if coord == (-1, -1, -1, -1):
                continue
            self.coords[i] = coord
            self.md5[i] = self.checksum(self.coords[i])

    def check_color(self, pixel):
        return pixel == self.color

    def get_symbol_coords(self, (x1, y1, x2, y2)):
        if self.margin:
            top, right, bottom, left = self.margin
            x1, y1, x2, y2 = x1 + left, y1 + top, x2 - right, y2 - bottom

        newY1 = -1
        newY2 = -1
        for y in range(y1, min(y2 + 1, self.height)):
            empty_line = True
            for x in range(x1, min(x2 + 1, self.width)):
                if self.check_color(self.pixar[x, y]):
                    empty_line = False
                    if newY1 == -1:
                        newY1 = y
                        break
                    else:
                        break
            if newY1 != -1 and not empty_line:
                newY2 = y
        newX1 = -1
        newX2 = -1
        for x in range(x1, min(x2 + 1, self.width)):
            empty_column = True
            for y in range(y1, min(y2 + 1, self.height)):
                if self.check_color(self.pixar[x, y]):
                    empty_column = False
                    if newX1 == -1:
                        newX1 = x
                        break
                    else:
                        break
            if newX1 != -1 and not empty_column:
                newX2 = x
        return (newX1, newY1, newX2, newY2)

    def checksum(self, (x1, y1, x2, y2)):
        s = ''
        for y in range(y1, min(y2 + 1, self.height)):
            for x in range(x1, min(x2 + 1, self.width)):
                if self.check_color(self.pixar[x, y]):
                    s += "."
                else:
                    s += " "
        return hashlib.md5(s).hexdigest()

    def get_symbol_code(self, md5sum):
        for i in self.md5:
            if md5sum == self.md5[i]:
                return i
        raise VirtKeyboardError('Symbol not found')

    def check_symbols(self, symbols, dirname):
        # symbols: dictionary <symbol>:<md5 value>
        for s in symbols:
            try:
                self.get_symbol_code(symbols[s])
            except VirtKeyboardError:
                if dirname is None:
                    dirname = tempfile.mkdtemp(prefix='weboob_session_')
                self.generate_MD5(dirname)
                raise VirtKeyboardError("Symbol '%s' not found; all symbol hashes are available in %s"
                                        % (s, dirname))

    def generate_MD5(self, dir):
        for i in self.coords:
            width = self.coords[i][2] - self.coords[i][0] + 1
            height = self.coords[i][3] - self.coords[i][1] + 1
            img = Image.new(''.join(self.bands), (width, height))
            matrix = img.load()
            for y in range(height):
                for x in range(width):
                    matrix[x, y] = self.pixar[self.coords[i][0] + x, self.coords[i][1] + y]
            img.save(dir + "/" + self.md5[i] + ".png")

class MappedVirtKeyboard(VirtKeyboard):
    def __init__(self, file, document, img_element, color, map_attr="onclick", convert=None):
        map_id = img_element.attrib.get("usemap")[1:]
        map = document.find("//map[@id='" + map_id + "']")
        if map is None:
            map = document.find("//map[@name='" + map_id + "']")

        coords = {}
        for area in map.getiterator("area"):
            code = area.attrib.get(map_attr)
            area_coords = []
            for coord in area.attrib.get("coords").split(','):
                area_coords.append(int(coord))
            coords[code] = tuple(area_coords)

        super(MappedVirtKeyboard, self).__init__(file, coords, color, convert)
<|endoftext|>


<commit_before>"""Nothing to see here . . . """

import os
import re
import numpy as np
import tensorflow as tf

# Special vocabulary symbols.
_PAD = b"_PAD"      # Append to unused space for both encoder/decoder.
_GO  = b"_GO"       # Prepend to each decoder input.
_EOS = b"_EOS"      # Append to outputs only. Stopping signal when decoding.
_UNK = b"_UNK"      # For any symbols not in our vocabulary.
_START_VOCAB = [_PAD, _GO, _EOS, _UNK]

# Enumerations for ease of use by this and other files.
PAD_ID  = 0
GO_ID   = 1
EOS_ID  = 2
UNK_ID  = 3

# Regular expressions used to tokenize.
_WORD_SPLIT = re.compile(b"([.,!?\"':;)(])")
_DIGIT_RE   = re.compile(br"\d")

def basic_tokenizer(sentence):
    """Very basic tokenizer: split the sentence into a list of tokens."""
    words = []
    for space_separated_fragment in sentence.strip().split():
        words.extend(_WORD_SPLIT.split(space_separated_fragment))
    return [w for w in words if w]

def sentence_to_token_ids(sentence, vocabulary, normalize_digits=True):
    """Convert a string to list of integers representing token-ids.

    For example, a sentence "I have a dog" may become tokenized into
    ["I", "have", "a", "dog"] and with vocabulary {"I": 1, "have": 2,
    "a": 4, "dog": 7"} this function will return [1, 2, 4, 7].

    Args:
      sentence: the sentence in bytes format to convert to token-ids.
      vocabulary: a dictionary mapping tokens to integers.
      normalize_digits: Boolean; if true, all digits are replaced by 0s.

    Returns:
      a list of integers, the token-ids for the sentence.
    """
    words = basic_tokenizer(sentence)

    if not normalize_digits:
        return [vocabulary.get(w, UNK_ID) for w in words]

    # Normalize digits by 0 before looking words up in the vocabulary.
    return [vocabulary.get(_DIGIT_RE.sub(b"0", w), UNK_ID) for w in words]

def load_graph(frozen_model_dir):
    """Load frozen tensorflow graph into the default graph.

    Args:
        frozen_model_dir: location of protobuf file containing frozen graph.

    Returns:
        tf.Graph object imported from frozen_model_path.
    """

    # Prase the frozen graph definition into a GraphDef object.
    frozen_file = os.path.join(frozen_model_dir, "frozen_model.pb")
    with tf.gfile.GFile(frozen_file, "rb") as f:
        graph_def = tf.GraphDef()
        graph_def.ParseFromString(f.read())

    # Load the graph def into the default graph and return it.
    with tf.Graph().as_default() as graph:
        tf.import_graph_def(
            graph_def,
            input_map=None,
            return_elements=None,
            op_dict=None,
            producer_op_list=None
        )
    return graph

def unfreeze_bot(frozen_model_path):
    """Restores the frozen graph from file and grabs input/output tensors needed to
    interface with a bot for conversation.

    Args:
        frozen_model_path: location of protobuf file containing frozen graph.

    Returns:
        outputs: tensor that can be run in a session.
    """

    bot_graph   = load_graph(frozen_model_path)
    tensors = {'inputs': bot_graph.get_tensor_by_name('import/input_pipeline/user_input:0'),
               'outputs': bot_graph.get_tensor_by_name('import/outputs:0')}
    return tensors, bot_graph

class FrozenBot:

    def __init__(self, frozen_model_dir, vocab_size):
        print(frozen_model_dir)
        print(type(frozen_model_dir))
        self.tensor_dict, self.graph = unfreeze_bot(frozen_model_dir)
        self.sess = tf.Session(graph=self.graph)

        self.config = {'dataset_params': {
            'data_dir': frozen_model_dir, 'vocab_size': vocab_size}}
        self.word_to_idx, self.idx_to_word = self.get_frozen_vocab()

    def get_frozen_vocab(self):
        """Helper function to get dictionaries for translating between tokens and words."""
        data_dir    = self.config['dataset_params']['data_dir']
        vocab_size  = self.config['dataset_params']['vocab_size']
        vocab_paths = {
            'from_vocab': os.path.join(data_dir, 'vocab{}.from'.format(vocab_size)),
            'to_vocab': os.path.join(data_dir, 'vocab{}.to'.format(vocab_size))}
        word_to_idx, _ = self.get_vocab_dicts(vocabulary_path=vocab_paths['from_vocab'])
        _, idx_to_word = self.get_vocab_dicts(vocabulary_path=vocab_paths['to_vocab'])
        return word_to_idx, idx_to_word

    def as_words(self, sentence):
        return " ".join([tf.compat.as_str(self.idx_to_word[i]) for i in sentence])

    def __call__(self, sentence):
        """Outputs response sentence (string) given input (string)."""
        print('calling')
        # Convert input sentence to token-ids.
        sentence_tokens = sentence_to_token_ids(
            tf.compat.as_bytes(sentence), self.word_to_idx)
        sentence_tokens = np.array([sentence_tokens[::-1]])

        # Get output sentence from the chatbot.
        fetches = self.tensor_dict['outputs']
        feed_dict={self.tensor_dict['inputs']: sentence_tokens}
        response = self.sess.run(fetches=fetches, feed_dict=feed_dict)
        print('resp:', response)
        return self.as_words(response[0][:-1])

    def get_vocab_dicts(self, vocabulary_path):
        """Returns word_to_idx, idx_to_word dictionaries given vocabulary.

        Args:
          vocabulary_path: path to the file containing the vocabulary.

        Returns:
          a pair: the vocabulary (a dictionary mapping string to integers), and
          the reversed vocabulary (a list, which reverses the vocabulary mapping).

        Raises:
          ValueError: if the provided vocabulary_path does not exist.
        """
        if tf.gfile.Exists(vocabulary_path):
            rev_vocab = []
            with tf.gfile.GFile(vocabulary_path, mode="rb") as f:
                rev_vocab.extend(f.readlines())
            rev_vocab = [tf.compat.as_bytes(line.strip()) for line in rev_vocab]
            vocab = dict([(x, y) for (y, x) in enumerate(rev_vocab)])
            return vocab, rev_vocab
        else:
            raise ValueError("Vocabulary file %s not found.", vocabulary_path)

<commit_msg>Remove extra space in bot responses, especially for punctuation marks.<commit_after>"""Nothing to see here . . . """

import os
import re
import numpy as np
import tensorflow as tf

# Special vocabulary symbols.
_PAD = b"_PAD"      # Append to unused space for both encoder/decoder.
_GO  = b"_GO"       # Prepend to each decoder input.
_EOS = b"_EOS"      # Append to outputs only. Stopping signal when decoding.
_UNK = b"_UNK"      # For any symbols not in our vocabulary.
_START_VOCAB = [_PAD, _GO, _EOS, _UNK]

# Enumerations for ease of use by this and other files.
PAD_ID  = 0
GO_ID   = 1
EOS_ID  = 2
UNK_ID  = 3

# Regular expressions used to tokenize.
_WORD_SPLIT = re.compile(b"([.,!?\"':;)(])")
_DIGIT_RE   = re.compile(br"\d")

def basic_tokenizer(sentence):
    """Very basic tokenizer: split the sentence into a list of tokens."""
    words = []
    for space_separated_fragment in sentence.strip().split():
        words.extend(_WORD_SPLIT.split(space_separated_fragment))
    return [w for w in words if w]

def sentence_to_token_ids(sentence, vocabulary, normalize_digits=True):
    """Convert a string to list of integers representing token-ids.

    For example, a sentence "I have a dog" may become tokenized into
    ["I", "have", "a", "dog"] and with vocabulary {"I": 1, "have": 2,
    "a": 4, "dog": 7"} this function will return [1, 2, 4, 7].

    Args:
      sentence: the sentence in bytes format to convert to token-ids.
      vocabulary: a dictionary mapping tokens to integers.
      normalize_digits: Boolean; if true, all digits are replaced by 0s.

    Returns:
      a list of integers, the token-ids for the sentence.
    """
    words = basic_tokenizer(sentence)

    if not normalize_digits:
        return [vocabulary.get(w, UNK_ID) for w in words]

    # Normalize digits by 0 before looking words up in the vocabulary.
    return [vocabulary.get(_DIGIT_RE.sub(b"0", w), UNK_ID) for w in words]

def load_graph(frozen_model_dir):
    """Load frozen tensorflow graph into the default graph.

    Args:
        frozen_model_dir: location of protobuf file containing frozen graph.

    Returns:
        tf.Graph object imported from frozen_model_path.
    """

    # Prase the frozen graph definition into a GraphDef object.
    frozen_file = os.path.join(frozen_model_dir, "frozen_model.pb")
    with tf.gfile.GFile(frozen_file, "rb") as f:
        graph_def = tf.GraphDef()
        graph_def.ParseFromString(f.read())

    # Load the graph def into the default graph and return it.
    with tf.Graph().as_default() as graph:
        tf.import_graph_def(
            graph_def,
            input_map=None,
            return_elements=None,
            op_dict=None,
            producer_op_list=None
        )
    return graph

def unfreeze_bot(frozen_model_path):
    """Restores the frozen graph from file and grabs input/output tensors needed to
    interface with a bot for conversation.

    Args:
        frozen_model_path: location of protobuf file containing frozen graph.

    Returns:
        outputs: tensor that can be run in a session.
    """

    bot_graph   = load_graph(frozen_model_path)
    tensors = {'inputs': bot_graph.get_tensor_by_name('import/input_pipeline/user_input:0'),
               'outputs': bot_graph.get_tensor_by_name('import/outputs:0')}
    return tensors, bot_graph

class FrozenBot:

    def __init__(self, frozen_model_dir, vocab_size):
        print(frozen_model_dir)
        print(type(frozen_model_dir))
        self.tensor_dict, self.graph = unfreeze_bot(frozen_model_dir)
        self.sess = tf.Session(graph=self.graph)

        self.config = {'dataset_params': {
            'data_dir': frozen_model_dir, 'vocab_size': vocab_size}}
        self.word_to_idx, self.idx_to_word = self.get_frozen_vocab()

    def get_frozen_vocab(self):
        """Helper function to get dictionaries for translating between tokens and words."""
        data_dir    = self.config['dataset_params']['data_dir']
        vocab_size  = self.config['dataset_params']['vocab_size']
        vocab_paths = {
            'from_vocab': os.path.join(data_dir, 'vocab{}.from'.format(vocab_size)),
            'to_vocab': os.path.join(data_dir, 'vocab{}.to'.format(vocab_size))}
        word_to_idx, _ = self.get_vocab_dicts(vocabulary_path=vocab_paths['from_vocab'])
        _, idx_to_word = self.get_vocab_dicts(vocabulary_path=vocab_paths['to_vocab'])
        return word_to_idx, idx_to_word

    def as_words(self, sentence):
        words = " ".join([tf.compat.as_str(self.idx_to_word[i]) for i in sentence])
        words = words.replace(' , ', ', ').replace(' .', '.').replace(' !', '!')
        return words[0].upper() + words[1:]

    def __call__(self, sentence):
        """Outputs response sentence (string) given input (string)."""
        # Convert input sentence to token-ids.
        sentence_tokens = sentence_to_token_ids(
            tf.compat.as_bytes(sentence), self.word_to_idx)
        sentence_tokens = np.array([sentence_tokens[::-1]])

        # Get output sentence from the chatbot.
        fetches = self.tensor_dict['outputs']
        feed_dict={self.tensor_dict['inputs']: sentence_tokens}
        response = self.sess.run(fetches=fetches, feed_dict=feed_dict)
        return self.as_words(response[0][:-1])

    def get_vocab_dicts(self, vocabulary_path):
        """Returns word_to_idx, idx_to_word dictionaries given vocabulary.

        Args:
          vocabulary_path: path to the file containing the vocabulary.

        Returns:
          a pair: the vocabulary (a dictionary mapping string to integers), and
          the reversed vocabulary (a list, which reverses the vocabulary mapping).

        Raises:
          ValueError: if the provided vocabulary_path does not exist.
        """
        if tf.gfile.Exists(vocabulary_path):
            rev_vocab = []
            with tf.gfile.GFile(vocabulary_path, mode="rb") as f:
                rev_vocab.extend(f.readlines())
            rev_vocab = [tf.compat.as_bytes(line.strip()) for line in rev_vocab]
            vocab = dict([(x, y) for (y, x) in enumerate(rev_vocab)])
            return vocab, rev_vocab
        else:
            raise ValueError("Vocabulary file %s not found.", vocabulary_path)

<|endoftext|>


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

from cloud.cloud_api_client import APIException, CloudAPIClient
from gateway.daemon_thread import DaemonThread, DaemonThreadWait
from gateway.events import GatewayEvent
from gateway.input_controller import InputController
from gateway.models import Config
from ioc import INJECTED, Inject, Injectable, Singleton

logger = logging.getLogger('openmotics')

@Injectable.named('event_sender')
@Singleton
class EventSender(object):

    @Inject
    def __init__(self, cloud_api_client=INJECTED, input_controller=INJECTED):  # type: (CloudAPIClient, InputController) -> None
        self._queue = deque()  # type: deque
        self._stopped = True
        self._cloud_client = cloud_api_client
        self._input_controller = input_controller

        self._events_queue = deque()  # type: deque
        self._events_thread = DaemonThread(name='EventSender loop',
                                           target=self._send_events_loop,
                                           interval=0.1, delay=0.2)

    def start(self):
        # type: () -> None
        self._events_thread.start()

    def stop(self):
        # type: () -> None
        self._events_thread.stop()

    def enqueue_event(self, event):
        if Config.get('cloud_enabled') is False:
            return
        if self._is_enabled(event):
            event.data['timestamp'] = time.time()
            self._queue.appendleft(event)

    def _is_enabled(self, event):
        if event.type == GatewayEvent.Types.INPUT_CHANGE:
            input_id = event.data['id']
            # TODO: Below entry needs to be cached. But caching needs invalidation, so lets fix this
            #       when we have decent cache invalidation events to subscribe on
            try:
                input_ = self._input_controller.load_input(input_id)
            except DoesNotExist:
                return False
            return input_.event_enabled
        else:
            return True

    def _send_events_loop(self):
        # type: () -> None
        try:
            if not self._batch_send_events():
                raise DaemonThreadWait
        except APIException as ex:
            logger.error('Error sending events to the cloud: {}'.format(str(ex)))

    def _batch_send_events(self):
        events = []
        while len(events) < 25:
            try:
                events.append(self._queue.pop())
            except IndexError:
                break
        if len(events) > 0:
            self._cloud_client.send_events(events)
            return True
        return False
<commit_msg>Cache the `event_enabled` property<commit_after># Copyright (C) 2019 OpenMotics BV
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""
Sends events to the cloud
"""
from __future__ import absolute_import
import logging
import time
from collections import deque
from peewee import DoesNotExist

from cloud.cloud_api_client import APIException, CloudAPIClient
from gateway.daemon_thread import DaemonThread, DaemonThreadWait
from gateway.events import GatewayEvent
from gateway.input_controller import InputController
from gateway.models import Config
from serial_utils import CommunicationTimedOutException
from ioc import INJECTED, Inject, Injectable, Singleton

logger = logging.getLogger('openmotics')

if False:  # MYPY
    from typing import Dict

@Injectable.named('event_sender')
@Singleton
class EventSender(object):

    @Inject
    def __init__(self, cloud_api_client=INJECTED, input_controller=INJECTED):  # type: (CloudAPIClient, InputController) -> None
        self._queue = deque()  # type: deque
        self._stopped = True
        self._cloud_client = cloud_api_client
        self._input_controller = input_controller
        self._event_enabled_cache = {}  # type: Dict[int, bool]
        self._events_queue = deque()  # type: deque
        self._events_thread = DaemonThread(name='EventSender loop',
                                           target=self._send_events_loop,
                                           interval=0.1, delay=0.2)

    def start(self):
        # type: () -> None
        self._events_thread.start()

    def stop(self):
        # type: () -> None
        self._events_thread.stop()

    def enqueue_event(self, event):
        if Config.get('cloud_enabled') is False:
            return
        if event.type == GatewayEvent.Types.CONFIG_CHANGE:
            if event.data.get('type') == 'input':
                self._event_enabled_cache = {}
        if self._should_send_event(event):
            event.data['timestamp'] = time.time()
            self._queue.appendleft(event)

    def _should_send_event(self, event):
        if event.type != GatewayEvent.Types.INPUT_CHANGE:
            return True
        input_id = event.data['id']
        if input_id in self._event_enabled_cache:
            return self._event_enabled_cache[input_id]
        try:
            try:
                input_ = self._input_controller.load_input(input_id)
                should_send = input_.event_enabled
            except DoesNotExist:
                should_send = False
            self._event_enabled_cache[input_id] = should_send
        except CommunicationTimedOutException:
            should_send = False
        return should_send

    def _send_events_loop(self):
        # type: () -> None
        try:
            if not self._batch_send_events():
                raise DaemonThreadWait
        except APIException as ex:
            logger.error('Error sending events to the cloud: {}'.format(str(ex)))

    def _batch_send_events(self):
        events = []
        while len(events) < 25:
            try:
                events.append(self._queue.pop())
            except IndexError:
                break
        if len(events) > 0:
            self._cloud_client.send_events(events)
            return True
        return False
<|endoftext|>


<commit_before>from enum import Enum

from kivy.app import App
from kivy.properties import NumericProperty
from kivy.animation import Animation

from core.hex_lib import hex_angle, index_of_direction

from game import game_instance
from skill import MoveType
from utils import Color
import actions

from ui.hex_widget import HexWidget
from ui.tile import Tile
from ui.action_widgets import ActionBuilder
from ui.shield_widget import ShieldWidget
from ui.contour import Contour
from ui.base_widgets import AngledColoredWidget
from ui.utils import check_root_window

hit_color = Color.firebrick
heal_color = Color.lightgreen
contour_color = Color.forestgreen
contour_color.a = 0
reachable_color = Color.olivedrab
reachable_color.a = 0.5

class Status(Enum):
    Idle = 0
    Moving = 1

class PieceBody(HexWidget):
    pass

class PieceInterBody(AngledColoredWidget):
    pass

class Piece(HexWidget):
    angle = NumericProperty(0)

    def __init__(self, unit, **kwargs):
        super(Piece, self).__init__(q=unit.hex_coords.q, r=unit.hex_coords.r, **kwargs)
        self.unit = unit
        self.color = unit.color
        self.current_skill = None
        self.skill_widget = None
        self.status = Status.Idle
        self.selected = False
        self.reachable_tiles = []

        self._shape_parts = {}
        done_list = []
        for shape_part in self.unit.shape:
            part_hex = self.hex_coords + shape_part
            w = PieceBody(q=part_hex.q, r=part_hex.r, layout=self.hex_layout, color=self.color)
            self._shape_parts.update({w: (w.pos[0] - self.pos[0], w.pos[1] - self.pos[1])})
            self.add_widget(w)

            for shape_part_other in self.unit.shape:
                same_shape_parts = shape_part == shape_part_other
                processed = (shape_part, shape_part_other) in done_list or (shape_part_other, shape_part) in done_list
                if not same_shape_parts and not processed and index_of_direction(shape_part_other - shape_part) != -1:
                    done_list.append((shape_part, shape_part_other))
                    hex_pos = self.hex_layout.hex_to_pixel(part_hex)
                    part_hex_other = self.hex_coords + shape_part_other
                    hex_pos_other = self.hex_layout.hex_to_pixel(part_hex_other)
                    size = (self.hex_layout.size.x, self.hex_layout.margin * 5)
                    pos = (hex_pos.x + (hex_pos_other.x - hex_pos.x) / 2 - size[0] / 2,
                           hex_pos.y + (hex_pos_other.y - hex_pos.y) / 2 - size[1] / 2)
                    angle = shape_part.angle_to_neighbour(shape_part_other - shape_part)
                    w = PieceInterBody(pos=pos, size=size, angle=angle, color=self.color, rotate_from_center=True)
                    self._shape_parts.update({w: (w.pos[0] - self.pos[0], w.pos[1] - self.pos[1])})
                    self.add_widget(w)

        self.contour = Contour(unit.shape, layout=self.hex_layout, color=contour_color, pos=self.pos)
        self.add_widget(self.contour)

        self.do_rotate()
        self._shields = [{} for _ in range(len(unit.shields))]
        self.update_shields()

        # events
        self.unit.on_health_change += self.on_unit_health_change
        self.unit.on_shield_change += self.update_shields
        self.unit.on_skill_move += self.on_unit_skill_move

    def do_rotate(self):
        self.angle = self.hex_coords.angle_to_neighbour(self.unit.orientation)
        if self.skill_widget:
            self.skill_widget.angle = self.angle

#    ######  ##     ## #### ######## ##       ########   ######
#   ##    ## ##     ##  ##  ##       ##       ##     ## ##    ##
#   ##       ##     ##  ##  ##       ##       ##     ## ##
#    ######  #########  ##  ######   ##       ##     ##  ######
#         ## ##     ##  ##  ##       ##       ##     ##       ##
#   ##    ## ##     ##  ##  ##       ##       ##     ## ##    ##
#    ######  ##     ## #### ######## ######## ########   ######
#   ############################################################
    def update_shields(self):
        def del_part(anim, widget):
            self.remove_widget(widget)
            for d in self._shields:
                if widget in d:
                    del d[widget]
                    return

        for shape_part_index, shape_part in enumerate(self.unit.shape):
            for shield_index in range(6):
                linear_index = shape_part_index * 6 + shield_index
                shield_value = self.unit.shields[linear_index]
                old_size = len(self._shields[linear_index])
                diff = shield_value - old_size
                if diff > 0:
                    for i in range(old_size, diff):
                        col = .6 - i * (0.6 / 3.)
                        shape_coord = self.hex_coords + shape_part
                        w = ShieldWidget(q=shape_coord.q, r=shape_coord.r,
                                         layout=self.hex_layout,
                                         color=[col, col, col, 1],
                                         radius=self.radius - (2 + 4) * i, thickness=8 - i * 2,
                                         angle=hex_angle(shield_index))
                        self.add_widget(w)
                        self._shields[linear_index].update({w: (w.pos[0] - self.pos[0], w.pos[1] - self.pos[1], i)})
                elif diff < 0:
                    for shield_part, (_, _, order) in self._shields[linear_index].items():
                        if shield_value <= order < old_size:
                            shield_part.color = hit_color
                            anim = Animation(thickness=shield_part.thickness * 2, a=0, duration=0.5, t='in_out_circ')

                            app = App.get_running_app()
                            app.anim_scheduler.add(anim, shield_part, 0, del_part)

    def on_finished_moving(self, trajectory, callback):
        self.status = Status.Idle
        previous = trajectory[-2] if len(trajectory) > 1 else self.hex_coords
        self.hex_coords = trajectory[-1]
        self.unit.move_to(hex_coords=self.hex_coords, orientation=trajectory[-1] - previous)
        if callback:
            callback(self)

    @check_root_window
    def on_pos(self, *args):
        self.contour.pos = self.pos
        for shape_part, offset in self._shape_parts.items():
            shape_part.pos = (self.pos[0] + offset[0], self.pos[1] + offset[1])

        for shield_data in self._shields:
            for shield_part, (dx, dy, _) in shield_data.items():
                shield_part.pos = (self.pos[0] + dx, self.pos[1] + dy)

    @check_root_window
    def on_color_change(self, r, g, b, a):
        for shape_part, _ in self._shape_parts.items():
            shape_part.color = (r, g, b, a)

    def on_unit_health_change(self, health_change, context):
        duration = 0.2
        anim = None
        if health_change < 0:
            pt = self.hex_layout.hex_to_pixel(self.hex_coords + context.direction)
            target_pos_x = self.x + (pt.x - self.x) / 10
            target_pos_y = self.y + (pt.y - self.y) / 10
            anim = Animation(pos=(target_pos_x, target_pos_y), **hit_color.rgb_dict, duration=duration / 3)
            anim += Animation(pos=(self.x, self.y), r=self.r, g=self.g, b=self.b, duration=duration * 2 / 3)
        else:
            anim = Animation(radius=self.radius * 1.2, **heal_color.rgb_dict, duration=duration / 3.)
            anim += Animation(radius=self.radius, r=self.r, g=self.g, b=self.b, duration=duration * 2 / 3)

        app = App.get_running_app()
        app.anim_scheduler.add(anim, self, context.hit.order)

    def on_unit_skill_move(self, context):
        def on_skill_move_end(hex_coords, orientation):
            self.hex_coords = hex_coords
            self.unit.move_to(hex_coords, orientation)

        pos = self.hex_layout.hex_to_pixel(context.end_coords).tup if context.move_info.move else None

        anim = None
        if context.move_info.move_type == MoveType.none:
            anim = Animation(duration=0)
            if pos:
                anim &= Animation(pos=pos, duration=0.1)
            if context.move_info.orientation:
                if abs(context.target_angle - self.angle) > 180:
                    self.angle -= 360
                anim &= Animation(angle=context.target_angle, duration=0.2)
        elif context.move_info.move_type == MoveType.blink:
            anim = Animation(a=0, duration=0.1)
            if pos:
                anim += Animation(pos=pos, duration=0)
            if context.move_info.orientation:
                if abs(context.target_angle - self.angle) > 180:
                    self.angle -= 360
                anim += Animation(angle=context.target_angle, duration=0)
            anim += Animation(a=1, duration=0.2)
        elif context.move_info.move_type == MoveType.pushed:
            anim = Animation(pos=pos, duration=0.3, t='out_back')

        app = App.get_running_app()
        app.anim_scheduler.add(anim, self, context.move_info.order, lambda *args: on_skill_move_end(context.end_coords, context.end_orientation))

    def move_to(self, hex_coords, tile_pos=None, trajectory=[], on_move_end=None):
        """ override from HexWidget """
        if trajectory:
            self.clean_reachable_tiles()
            duration_per_tile = 0.2
            self.status = Status.Moving
            Animation.cancel_all(self)
            trajectory.remove(self.hex_coords)
            trajectory.reverse()
            anim = Animation(duration=0)
            prev_state = self.hex_coords, self.angle
            for h in trajectory:
                pos = self.hex_layout.hex_to_pixel(h)
                step_anim = Animation(pos=pos.tup, duration=duration_per_tile)
                prev_hex, prev_angle = prev_state
                angle = prev_hex.angle_to_neighbour(h - prev_hex)
                if angle != prev_angle:
                    if abs(prev_angle - angle) > 180:
                        angle += 360
                    step_anim &= Animation(angle=angle, duration=duration_per_tile / 3)
                anim += step_anim
                prev_state = h, angle
            anim.bind(on_complete=lambda *args: self.on_finished_moving(trajectory, on_move_end))
            anim.start(self)
        else:
            super(Piece, self).move_to(hex_coords, tile_pos, trajectory)

    def hex_test(self, hex_coords):
        return self.unit.hex_test(hex_coords)

    def load(self):
        self.update_shields()

#    ######  ##    ## #### ##       ##        ######
#   ##    ## ##   ##   ##  ##       ##       ##    ##
#   ##       ##  ##    ##  ##       ##       ##
#    ######  #####     ##  ##       ##        ######
#         ## ##  ##    ##  ##       ##             ##
#   ##    ## ##   ##   ##  ##       ##       ##    ##
#    ######  ##    ## #### ######## ########  ######
#   #################################################
    def clean_skill(self):
        if self.skill_widget:
            self.parent.remove_widget(self.skill_widget)
            self.skill_widget = None
        self.current_skill = None

    def load_skill(self, rk_skill):
        self.current_skill = rk_skill
        self.skill_widget = ActionBuilder(rk_skill, self.hex_coords, self.hex_layout, pos=self.pos, angle=self.angle)
        self.parent.add_widget(self.skill_widget)

    def display_reachable_tiles(self):
        if not self.reachable_tiles:
            reachable_hexes = game_instance.current_fight.current_map.get_reachable(self.unit)
            for h in reachable_hexes:
                tile = Tile(h.q, h.r,
                            layout=self.hex_layout,
                            color=reachable_color,
                            radius=self.radius - 2,
                            size=(self.radius - 2, self.radius - 2))
                self.parent.add_widget(tile)
                self.reachable_tiles.append(tile)

    def is_in_move_range(self, hex_coords):
        if self.reachable_tiles:
            for tile in self.reachable_tiles:
                if tile.hex_coords == hex_coords:
                    return True
        return False

    def clean_reachable_tiles(self):
        for tile in self.reachable_tiles:
            self.parent.remove_widget(tile)
        self.reachable_tiles = []

    def on_action_change(self, action_type, rk_skill):
        self.clean_skill()
        if action_type == actions.ActionType.Move:
            self.display_reachable_tiles()
        else:
            self.clean_reachable_tiles()
            if rk_skill:
                self.load_skill(rk_skill)

    def on_hovered_in(self):
        if not self.selected:
            self.display_reachable_tiles()

    def on_hovered_out(self):
        if not self.selected:
            self.clean_reachable_tiles()

    def on_touched_down(self):
        self.do_select(True)
        return True

    def do_select(self, select):
        if self.selected != select:
            if select:
                self.display_reachable_tiles()
                self.contour.show()
            else:
                self.clean_skill()
                self.clean_reachable_tiles()
                self.contour.hide()
            self.selected = select
<commit_msg>Fix for python 3.4<commit_after>from enum import Enum

from kivy.app import App
from kivy.properties import NumericProperty
from kivy.animation import Animation

from core.hex_lib import hex_angle, index_of_direction

from game import game_instance
from skill import MoveType
from utils import Color
import actions

from ui.hex_widget import HexWidget
from ui.tile import Tile
from ui.action_widgets import ActionBuilder
from ui.shield_widget import ShieldWidget
from ui.contour import Contour
from ui.base_widgets import AngledColoredWidget
from ui.utils import check_root_window

hit_color = Color.firebrick
heal_color = Color.lightgreen
contour_color = Color.forestgreen
contour_color.a = 0
reachable_color = Color.olivedrab
reachable_color.a = 0.5

class Status(Enum):
    Idle = 0
    Moving = 1

class PieceBody(HexWidget):
    pass

class PieceInterBody(AngledColoredWidget):
    pass

class Piece(HexWidget):
    angle = NumericProperty(0)

    def __init__(self, unit, **kwargs):
        super(Piece, self).__init__(q=unit.hex_coords.q, r=unit.hex_coords.r, **kwargs)
        self.unit = unit
        self.color = unit.color
        self.current_skill = None
        self.skill_widget = None
        self.status = Status.Idle
        self.selected = False
        self.reachable_tiles = []

        self._shape_parts = {}
        done_list = []
        for shape_part in self.unit.shape:
            part_hex = self.hex_coords + shape_part
            w = PieceBody(q=part_hex.q, r=part_hex.r, layout=self.hex_layout, color=self.color)
            self._shape_parts.update({w: (w.pos[0] - self.pos[0], w.pos[1] - self.pos[1])})
            self.add_widget(w)

            for shape_part_other in self.unit.shape:
                same_shape_parts = shape_part == shape_part_other
                processed = (shape_part, shape_part_other) in done_list or (shape_part_other, shape_part) in done_list
                if not same_shape_parts and not processed and index_of_direction(shape_part_other - shape_part) != -1:
                    done_list.append((shape_part, shape_part_other))
                    hex_pos = self.hex_layout.hex_to_pixel(part_hex)
                    part_hex_other = self.hex_coords + shape_part_other
                    hex_pos_other = self.hex_layout.hex_to_pixel(part_hex_other)
                    size = (self.hex_layout.size.x, self.hex_layout.margin * 5)
                    pos = (hex_pos.x + (hex_pos_other.x - hex_pos.x) / 2 - size[0] / 2,
                           hex_pos.y + (hex_pos_other.y - hex_pos.y) / 2 - size[1] / 2)
                    angle = shape_part.angle_to_neighbour(shape_part_other - shape_part)
                    w = PieceInterBody(pos=pos, size=size, angle=angle, color=self.color, rotate_from_center=True)
                    self._shape_parts.update({w: (w.pos[0] - self.pos[0], w.pos[1] - self.pos[1])})
                    self.add_widget(w)

        self.contour = Contour(unit.shape, layout=self.hex_layout, color=contour_color, pos=self.pos)
        self.add_widget(self.contour)

        self.do_rotate()
        self._shields = [{} for _ in range(len(unit.shields))]
        self.update_shields()

        # events
        self.unit.on_health_change += self.on_unit_health_change
        self.unit.on_shield_change += self.update_shields
        self.unit.on_skill_move += self.on_unit_skill_move

    def do_rotate(self):
        self.angle = self.hex_coords.angle_to_neighbour(self.unit.orientation)
        if self.skill_widget:
            self.skill_widget.angle = self.angle

#    ######  ##     ## #### ######## ##       ########   ######
#   ##    ## ##     ##  ##  ##       ##       ##     ## ##    ##
#   ##       ##     ##  ##  ##       ##       ##     ## ##
#    ######  #########  ##  ######   ##       ##     ##  ######
#         ## ##     ##  ##  ##       ##       ##     ##       ##
#   ##    ## ##     ##  ##  ##       ##       ##     ## ##    ##
#    ######  ##     ## #### ######## ######## ########   ######
#   ############################################################
    def update_shields(self):
        def del_part(anim, widget):
            self.remove_widget(widget)
            for d in self._shields:
                if widget in d:
                    del d[widget]
                    return

        for shape_part_index, shape_part in enumerate(self.unit.shape):
            for shield_index in range(6):
                linear_index = shape_part_index * 6 + shield_index
                shield_value = self.unit.shields[linear_index]
                old_size = len(self._shields[linear_index])
                diff = shield_value - old_size
                if diff > 0:
                    for i in range(old_size, diff):
                        col = .6 - i * (0.6 / 3.)
                        shape_coord = self.hex_coords + shape_part
                        w = ShieldWidget(q=shape_coord.q, r=shape_coord.r,
                                         layout=self.hex_layout,
                                         color=[col, col, col, 1],
                                         radius=self.radius - (2 + 4) * i, thickness=8 - i * 2,
                                         angle=hex_angle(shield_index))
                        self.add_widget(w)
                        self._shields[linear_index].update({w: (w.pos[0] - self.pos[0], w.pos[1] - self.pos[1], i)})
                elif diff < 0:
                    for shield_part, (_, _, order) in self._shields[linear_index].items():
                        if shield_value <= order < old_size:
                            shield_part.color = hit_color
                            anim = Animation(thickness=shield_part.thickness * 2, a=0, duration=0.5, t='in_out_circ')

                            app = App.get_running_app()
                            app.anim_scheduler.add(anim, shield_part, 0, del_part)

    def on_finished_moving(self, trajectory, callback):
        self.status = Status.Idle
        previous = trajectory[-2] if len(trajectory) > 1 else self.hex_coords
        self.hex_coords = trajectory[-1]
        self.unit.move_to(hex_coords=self.hex_coords, orientation=trajectory[-1] - previous)
        if callback:
            callback(self)

    @check_root_window
    def on_pos(self, *args):
        self.contour.pos = self.pos
        for shape_part, offset in self._shape_parts.items():
            shape_part.pos = (self.pos[0] + offset[0], self.pos[1] + offset[1])

        for shield_data in self._shields:
            for shield_part, (dx, dy, _) in shield_data.items():
                shield_part.pos = (self.pos[0] + dx, self.pos[1] + dy)

    @check_root_window
    def on_color_change(self, r, g, b, a):
        for shape_part, _ in self._shape_parts.items():
            shape_part.color = (r, g, b, a)

    def on_unit_health_change(self, health_change, context):
        duration = 0.2
        anim = None
        if health_change < 0:
            pt = self.hex_layout.hex_to_pixel(self.hex_coords + context.direction)
            target_pos_x = self.x + (pt.x - self.x) / 10
            target_pos_y = self.y + (pt.y - self.y) / 10
            anim = Animation(pos=(target_pos_x, target_pos_y), duration=duration / 3, **hit_color.rgb_dict)
            anim += Animation(pos=(self.x, self.y), r=self.r, g=self.g, b=self.b, duration=duration * 2 / 3)
        else:
            anim = Animation(radius=self.radius * 1.2, duration=duration / 3., **heal_color.rgb_dict)
            anim += Animation(radius=self.radius, r=self.r, g=self.g, b=self.b, duration=duration * 2 / 3)

        app = App.get_running_app()
        app.anim_scheduler.add(anim, self, context.hit.order)

    def on_unit_skill_move(self, context):
        def on_skill_move_end(hex_coords, orientation):
            self.hex_coords = hex_coords
            self.unit.move_to(hex_coords, orientation)

        pos = self.hex_layout.hex_to_pixel(context.end_coords).tup if context.move_info.move else None

        anim = None
        if context.move_info.move_type == MoveType.none:
            anim = Animation(duration=0)
            if pos:
                anim &= Animation(pos=pos, duration=0.1)
            if context.move_info.orientation:
                if abs(context.target_angle - self.angle) > 180:
                    self.angle -= 360
                anim &= Animation(angle=context.target_angle, duration=0.2)
        elif context.move_info.move_type == MoveType.blink:
            anim = Animation(a=0, duration=0.1)
            if pos:
                anim += Animation(pos=pos, duration=0)
            if context.move_info.orientation:
                if abs(context.target_angle - self.angle) > 180:
                    self.angle -= 360
                anim += Animation(angle=context.target_angle, duration=0)
            anim += Animation(a=1, duration=0.2)
        elif context.move_info.move_type == MoveType.pushed:
            anim = Animation(pos=pos, duration=0.3, t='out_back')

        app = App.get_running_app()
        app.anim_scheduler.add(anim, self, context.move_info.order, lambda *args: on_skill_move_end(context.end_coords, context.end_orientation))

    def move_to(self, hex_coords, tile_pos=None, trajectory=[], on_move_end=None):
        """ override from HexWidget """
        if trajectory:
            self.clean_reachable_tiles()
            duration_per_tile = 0.2
            self.status = Status.Moving
            Animation.cancel_all(self)
            trajectory.remove(self.hex_coords)
            trajectory.reverse()
            anim = Animation(duration=0)
            prev_state = self.hex_coords, self.angle
            for h in trajectory:
                pos = self.hex_layout.hex_to_pixel(h)
                step_anim = Animation(pos=pos.tup, duration=duration_per_tile)
                prev_hex, prev_angle = prev_state
                angle = prev_hex.angle_to_neighbour(h - prev_hex)
                if angle != prev_angle:
                    if abs(prev_angle - angle) > 180:
                        angle += 360
                    step_anim &= Animation(angle=angle, duration=duration_per_tile / 3)
                anim += step_anim
                prev_state = h, angle
            anim.bind(on_complete=lambda *args: self.on_finished_moving(trajectory, on_move_end))
            anim.start(self)
        else:
            super(Piece, self).move_to(hex_coords, tile_pos, trajectory)

    def hex_test(self, hex_coords):
        return self.unit.hex_test(hex_coords)

    def load(self):
        self.update_shields()

#    ######  ##    ## #### ##       ##        ######
#   ##    ## ##   ##   ##  ##       ##       ##    ##
#   ##       ##  ##    ##  ##       ##       ##
#    ######  #####     ##  ##       ##        ######
#         ## ##  ##    ##  ##       ##             ##
#   ##    ## ##   ##   ##  ##       ##       ##    ##
#    ######  ##    ## #### ######## ########  ######
#   #################################################
    def clean_skill(self):
        if self.skill_widget:
            self.parent.remove_widget(self.skill_widget)
            self.skill_widget = None
        self.current_skill = None

    def load_skill(self, rk_skill):
        self.current_skill = rk_skill
        self.skill_widget = ActionBuilder(rk_skill, self.hex_coords, self.hex_layout, pos=self.pos, angle=self.angle)
        self.parent.add_widget(self.skill_widget)

    def display_reachable_tiles(self):
        if not self.reachable_tiles:
            reachable_hexes = game_instance.current_fight.current_map.get_reachable(self.unit)
            for h in reachable_hexes:
                tile = Tile(h.q, h.r,
                            layout=self.hex_layout,
                            color=reachable_color,
                            radius=self.radius - 2,
                            size=(self.radius - 2, self.radius - 2))
                self.parent.add_widget(tile)
                self.reachable_tiles.append(tile)

    def is_in_move_range(self, hex_coords):
        if self.reachable_tiles:
            for tile in self.reachable_tiles:
                if tile.hex_coords == hex_coords:
                    return True
        return False

    def clean_reachable_tiles(self):
        for tile in self.reachable_tiles:
            self.parent.remove_widget(tile)
        self.reachable_tiles = []

    def on_action_change(self, action_type, rk_skill):
        self.clean_skill()
        if action_type == actions.ActionType.Move:
            self.display_reachable_tiles()
        else:
            self.clean_reachable_tiles()
            if rk_skill:
                self.load_skill(rk_skill)

    def on_hovered_in(self):
        if not self.selected:
            self.display_reachable_tiles()

    def on_hovered_out(self):
        if not self.selected:
            self.clean_reachable_tiles()

    def on_touched_down(self):
        self.do_select(True)
        return True

    def do_select(self, select):
        if self.selected != select:
            if select:
                self.display_reachable_tiles()
                self.contour.show()
            else:
                self.clean_skill()
                self.clean_reachable_tiles()
                self.contour.hide()
            self.selected = select
<|endoftext|>