<commit_before>import os
from datetime import datetime
from django.core.mail import send_mail
from openbudget.settings.base import TEMP_FILES_DIR, ADMINS, EMAIL_HOST_USER
from openbudget.apps.transport.models import String
from openbudget.apps.transport.incoming.parsers import get_parser, get_parser_key

class BaseImporter(object):
    """Gets data out of files and into the database.

    This class is abstract and does not implement the `get_data` method.

    This class can handle any of the supported datasets for importing.

    At this stage, that means Budget Templates (template and related
    node objects), and Budgets/Actuals (Budget or Actual, and related
    items).

    The importer supports a lower level import by parsing the
    file name for meta data - useful while testing, so developers do
    not have to work with an interactive importer. Otherwise, \
    it should be used with an interactive wizard so the content \
    editor can add metadata via a form as part of the import process.

    """

    def __init__(self, sourcefile=None, post_data=None, ignore_unknown_headers=False,
                 ignore_invalid_rows=False, dataset_meta_in_filename=False):

        self.sourcefile = sourcefile
        self.post_data = post_data
        self.ignore_unknown_headers = ignore_unknown_headers
        self.ignore_invalid_rows = ignore_invalid_rows
        self.dataset_meta_in_filename = dataset_meta_in_filename

        if sourcefile:
            self.extract()

    def extract(self):
        """Create a valid dataset from data in the sourcefile.

        We create a dataset object.

        We clean up the headers.

        We email ourselves if the source file cannot be converted \
        to a datset, and we save that sourcefile in a tempoary \
        location, as well as emailing it, for analysis.

        """
        self._extract_meta()

        data_stream = self.sourcefile.read()
        self.data = self.get_data(data_stream)

        return self

    def validate(self):
        """
        Runs validation on the extracted data using the parser's
        validation.
        """
        return self.parser.validate(self.data)

    def save(self):
        """
        Delegates to the parser's save method.
        """
        return self.parser.save()

    def deferred(self):
        """
        Gets a deferred object from the parser, adding to it
        the parser's class key.

        Returns the deferred object which can be later serialized
        and sent to queue, for later resolving it.
        """
        deferred = self.parser.deferred()
        deferred['class'] = get_parser_key(self.parser.__class__)

        return deferred

    def resolve(self, deferred):
        """
        Takes a deferred importer object which sets the appropriate
        parser and delegates to it's resolve method.
        """
        # get the parser class key
        klass = deferred['class']

        if not klass:
            raise Exception('Deferred object missing class key: %s' % klass)

        # get the parser class and resolve the deferred object
        self.parser = get_parser(klass).resolve(deferred)
        # return self for fluency's sake
        return self

    def get_data(self, stream):
        """
        Takes a data stream read from the source file, extracts a
        dataset from it and stores it in `self.data`.
        """
        raise NotImplementedError()

    def normalize_headers(self, headers):
        """Clean the headers of the dataset.

        We replace the existing headers with new ones that \
        have been cleaned and normalized.

        To clean, we strip white space and common joining \
        symbols, and we convert all to lowercase.

        To normalize, we match the header to strings in a \
        string scope map, and convert to the string in the \
        map when our key is either the string or in the scope \
        list.

        """
        symbols = {
            ord('_'): None,
            ord('-'): None,
            ord('"'): None,
            ord(' '): None,
            ord("'"): None,
        }
        scopes_map = self._get_header_scopes()
        normalized_headers = []

        for index, header in enumerate(headers):

            tmp = unicode(header).translate(symbols).lower()

            for k, v in scopes_map.iteritems():

                if tmp == k or tmp in v:
                    normalized_headers[index] = k

        return normalized_headers

    def import_error(self):
        """
        Handle import exceptions by sending an email to admins
        with the file attached.
        """
        #TODO: need to attach the file to the sent email
        dt = datetime.now().isoformat()

        this_file = TEMP_FILES_DIR + \
            '/failed_import_{timestamp}_{filename}'.format(
                timestamp=dt,
                filename=unicode(self.sourcefile)
            )

        with open(this_file, 'wb+') as tmp_file:
            for chunk in self.sourcefile.chunks():
                tmp_file.write(chunk)

        # email ourselves that we have a file to check
        subject = 'Open Budget: Failed File Import'
        message = 'The file is attached.'
        sender = EMAIL_HOST_USER
        recipients = [ADMINS]

        send_mail(subject, message, sender, recipients)

    def _extract_meta(self):
        """Get's the meta data for the dataset. \
        The meta data determines the parser class to be used for \
        parsing and saving the data, and the data for creating the \
        container object.

        Each file that is imported has rows of data, where each row \
        is, ultimately, some object. The objects contained in the \
        file also need additional data in order to be contextualized \
        in the datastore.

        For example, if the sourcefile is full of entries that are \
        nodes in a template, we still need to know, for example the \
        name of the template, the entity it belongs to, and so on.

        When data is imported via an interactive wizard, this \
        "metadata" can be filled out in a form by the person doing \
        the import.

        Alternatively, the BaseImporter class also supports parsing \
        the filename of the sourcefile to extract the required \
        metadata. For this option, dataset_meta_in_filename must be \
        True. Importing like this is handy during development, \
        but you'll need to know that your dataset is valid in \
        advance, as there will be no interactive wizard to fix data.

        """
        if self.dataset_meta_in_filename:
            parser = self._get_parser_from_filename()
        else:
            parser = self._get_parser_from_post()

        self.parser = parser

        return self

    def _get_header_scopes(self):
        """
        Gets the available strings and scopes which are used
        for normalizing the headers.
        """

        scopes_map = {}

        strings = String.objects.filter(parent__isnull=True)

        for string in strings:
            scopes_map[string.string] = [scope.string for scope in string.scope_set.all()]

        return scopes_map

    def _get_parser_from_filename(self):
        """Extract necessary info on the dataset from the filename.

        FILENAME FORMAT:
        |PARSER|_|CONTAINEROBJECT-ATTRS|.extension

        Arguments for object attributes are keywords.
        For object attributes, each attribute is separated by a \
        semi-colon. Multiple values for an attribute (i.e: m2m), \
        are comma separated.

        EXAMPLE - BUDGET TEMPLATE:
        budgettemplate_name=israel-municipality;divisions=4,5,6;period_start=2001-01-10.csv

        EXAMPLE - BUDGET OR ACTUAL:
        budget_entity=1,period_start=2001-01-01;period_end=2001-12-31.csv

        """

        # an empty dict to populate with data for our container object
        container_object_dict = {}

        # get our data string from the filename
        keys, ext = os.path.splitext(unicode(self.sourcefile))

        # first, split the parser key from the container_object keys
        parser_key, attributes_str = keys.split('_', 1)

        # get the appropriate parser class
        parser = get_parser(parser_key)

        # now get the keyword arguments for the container object
        container_object_kwargs = attributes_str.split(';')

        # and split these keyword arguments into keys and values
        for kwarg in container_object_kwargs:
            attr_key, attr_val = kwarg.split('=')

            # and make sure each attribute is valid for the container model
            try:
                getattr(parser.container_model, attr_key)
            except AttributeError as e:
                raise e

            # if the value has commas, it is an m2m related field
            if ',' in attr_val:
                attr_val = tuple(attr_val.split(','))

            container_object_dict[attr_key] = attr_val

        # return instantiated parser
        return parser(container_object_dict)

    def _get_parser_from_post(self):
        """Extract necessary info on the dataset from the request's POST data.

        For now relies on the same format of the above file name meta extractor, \
        except it looks for the parser type under the key `type` and for the rest \
        under the key `attributes`.
        """
        #TODO: refactor the meta extraction from string parsing to proper data in POST
        container_object_dict = {}
        parser_key = self.post_data.get('type', 'budget')
        attributes_str = self.post_data.get('attributes', None)

        # get the appropriate parser class
        parser = get_parser(parser_key)

        if attributes_str:
            # parse the attributes
            # split the string to pairs
            attributes = attributes_str.split(';')
            for attr in attributes:
                # split each pair to key-value
                attr_key, attr_val = attr.split('=')

                # check that this key belongs to our parser's container model
                try:
                    getattr(parser.container_model, attr_key)
                except AttributeError as e:
                    try:
                        # if it's not an attribute of the container model's class
                        # it might be an attribute of its instance (because of use of mixins)
                        getattr(parser.container_model(), attr_key)
                    except AttributeError as e:
                        raise e

                # if the value has commas, it is an m2m related field
                if ',' in attr_val:
                    attr_val = tuple(attr_val.split(','))

                container_object_dict[attr_key] = attr_val

            # return instantiated parser
            return parser(container_object_dict)

        else:
            raise Exception('No attributes given in meta data.')
<commit_msg>Fixed import_error method, so that the errored files are correcly attached to the email message.<commit_after>import os
from datetime import datetime
from django.core.mail import EmailMessage
from django.utils.translation import ugettext_lazy as _
from openbudget.settings.base import TEMP_FILES_DIR, ADMINS, EMAIL_HOST_USER
from openbudget.apps.transport.models import String
from openbudget.apps.transport.incoming.parsers import get_parser, get_parser_key

class BaseImporter(object):
    """Gets data out of files and into the database.

    This class is abstract and does not implement the `get_data` method.

    This class can handle any of the supported datasets for importing.

    At this stage, that means Budget Templates (template and related
    node objects), and Budgets/Actuals (Budget or Actual, and related
    items).

    The importer supports a lower level import by parsing the
    file name for meta data - useful while testing, so developers do
    not have to work with an interactive importer. Otherwise, \
    it should be used with an interactive wizard so the content \
    editor can add metadata via a form as part of the import process.

    """

    def __init__(self, sourcefile=None, post_data=None, ignore_unknown_headers=False,
                 ignore_invalid_rows=False, dataset_meta_in_filename=False):

        self.sourcefile = sourcefile
        self.post_data = post_data
        self.ignore_unknown_headers = ignore_unknown_headers
        self.ignore_invalid_rows = ignore_invalid_rows
        self.dataset_meta_in_filename = dataset_meta_in_filename

        if sourcefile:
            self.extract()

    def extract(self):
        """Create a valid dataset from data in the sourcefile.

        We create a dataset object.

        We clean up the headers.

        We email ourselves if the source file cannot be converted \
        to a datset, and we save that sourcefile in a tempoary \
        location, as well as emailing it, for analysis.

        """
        self._extract_meta()

        data_stream = self.sourcefile.read()
        self.data = self.get_data(data_stream)

        return self

    def validate(self):
        """
        Runs validation on the extracted data using the parser's
        validation.
        """
        return self.parser.validate(self.data)

    def save(self):
        """
        Delegates to the parser's save method.
        """
        return self.parser.save()

    def deferred(self):
        """
        Gets a deferred object from the parser, adding to it
        the parser's class key.

        Returns the deferred object which can be later serialized
        and sent to queue, for later resolving it.
        """
        deferred = self.parser.deferred()
        deferred['class'] = get_parser_key(self.parser.__class__)

        return deferred

    def resolve(self, deferred):
        """
        Takes a deferred importer object which sets the appropriate
        parser and delegates to it's resolve method.
        """
        # get the parser class key
        klass = deferred['class']

        if not klass:
            raise Exception('Deferred object missing class key: %s' % klass)

        # get the parser class and resolve the deferred object
        self.parser = get_parser(klass).resolve(deferred)
        # return self for fluency's sake
        return self

    def get_data(self, stream):
        """
        Takes a data stream read from the source file, extracts a
        dataset from it and stores it in `self.data`.
        """
        raise NotImplementedError()

    def normalize_headers(self, headers):
        """Clean the headers of the dataset.

        We replace the existing headers with new ones that \
        have been cleaned and normalized.

        To clean, we strip white space and common joining \
        symbols, and we convert all to lowercase.

        To normalize, we match the header to strings in a \
        string scope map, and convert to the string in the \
        map when our key is either the string or in the scope \
        list.

        """
        symbols = {
            ord('_'): None,
            ord('-'): None,
            ord('"'): None,
            ord(' '): None,
            ord("'"): None,
        }
        scopes_map = self._get_header_scopes()
        normalized_headers = []

        for index, header in enumerate(headers):

            tmp = unicode(header).translate(symbols).lower()

            for k, v in scopes_map.iteritems():

                if tmp == k or tmp in v:
                    normalized_headers[index] = k

        return normalized_headers

    def import_error(self):
        """If a file is not validly formed, we can't open it.

        In this case, we send a copy of the file by email to the site admins.

        We want to site admins to be able to see the file, and understand what \
        was invalid - perhaps it is a problem that can be solved in code - \
        file import is part science, part art.
        """
        dt = datetime.now().isoformat()

        this_file = TEMP_FILES_DIR + \
            '/failed_import_{timestamp}_{filename}'.format(
                timestamp=dt,
                filename=unicode(self.sourcefile)
            )

        with open(this_file, 'wb+') as tmp_file:
            for chunk in self.sourcefile.chunks():
                tmp_file.write(chunk)

        subject = _('Open Budget: Failed File Import')
        message = _('The file is attached.')
        sender = EMAIL_HOST_USER
        recipients = [ADMINS]
        attachment = this_file
        mail = EmailMessage(subject, message, sender, recipients)
        mail.attach_file(attachment)
        mail.send()

    def _extract_meta(self):
        """Get's the meta data for the dataset. \
        The meta data determines the parser class to be used for \
        parsing and saving the data, and the data for creating the \
        container object.

        Each file that is imported has rows of data, where each row \
        is, ultimately, some object. The objects contained in the \
        file also need additional data in order to be contextualized \
        in the datastore.

        For example, if the sourcefile is full of entries that are \
        nodes in a template, we still need to know, for example the \
        name of the template, the entity it belongs to, and so on.

        When data is imported via an interactive wizard, this \
        "metadata" can be filled out in a form by the person doing \
        the import.

        Alternatively, the BaseImporter class also supports parsing \
        the filename of the sourcefile to extract the required \
        metadata. For this option, dataset_meta_in_filename must be \
        True. Importing like this is handy during development, \
        but you'll need to know that your dataset is valid in \
        advance, as there will be no interactive wizard to fix data.

        """
        if self.dataset_meta_in_filename:
            parser = self._get_parser_from_filename()
        else:
            parser = self._get_parser_from_post()

        self.parser = parser

        return self

    def _get_header_scopes(self):
        """
        Gets the available strings and scopes which are used
        for normalizing the headers.
        """

        scopes_map = {}

        strings = String.objects.filter(parent__isnull=True)

        for string in strings:
            scopes_map[string.string] = [scope.string for scope in string.scope_set.all()]

        return scopes_map

    def _get_parser_from_filename(self):
        """Extract necessary info on the dataset from the filename.

        FILENAME FORMAT:
        |PARSER|_|CONTAINEROBJECT-ATTRS|.extension

        Arguments for object attributes are keywords.
        For object attributes, each attribute is separated by a \
        semi-colon. Multiple values for an attribute (i.e: m2m), \
        are comma separated.

        EXAMPLE - BUDGET TEMPLATE:
        budgettemplate_name=israel-municipality;divisions=4,5,6;period_start=2001-01-10.csv

        EXAMPLE - BUDGET OR ACTUAL:
        budget_entity=1,period_start=2001-01-01;period_end=2001-12-31.csv

        """

        # an empty dict to populate with data for our container object
        container_object_dict = {}

        # get our data string from the filename
        keys, ext = os.path.splitext(unicode(self.sourcefile))

        # first, split the parser key from the container_object keys
        parser_key, attributes_str = keys.split('_', 1)

        # get the appropriate parser class
        parser = get_parser(parser_key)

        # now get the keyword arguments for the container object
        container_object_kwargs = attributes_str.split(';')

        # and split these keyword arguments into keys and values
        for kwarg in container_object_kwargs:
            attr_key, attr_val = kwarg.split('=')

            # and make sure each attribute is valid for the container model
            try:
                getattr(parser.container_model, attr_key)
            except AttributeError as e:
                raise e

            # if the value has commas, it is an m2m related field
            if ',' in attr_val:
                attr_val = tuple(attr_val.split(','))

            container_object_dict[attr_key] = attr_val

        # return instantiated parser
        return parser(container_object_dict)

    def _get_parser_from_post(self):
        """Extract necessary info on the dataset from the request's POST data.

        For now relies on the same format of the above file name meta extractor, \
        except it looks for the parser type under the key `type` and for the rest \
        under the key `attributes`.
        """
        #TODO: refactor the meta extraction from string parsing to proper data in POST
        container_object_dict = {}
        parser_key = self.post_data.get('type', 'budget')
        attributes_str = self.post_data.get('attributes', None)

        # get the appropriate parser class
        parser = get_parser(parser_key)

        if attributes_str:
            # parse the attributes
            # split the string to pairs
            attributes = attributes_str.split(';')
            for attr in attributes:
                # split each pair to key-value
                attr_key, attr_val = attr.split('=')

                # check that this key belongs to our parser's container model
                try:
                    getattr(parser.container_model, attr_key)
                except AttributeError as e:
                    try:
                        # if it's not an attribute of the container model's class
                        # it might be an attribute of its instance (because of use of mixins)
                        getattr(parser.container_model(), attr_key)
                    except AttributeError as e:
                        raise e

                # if the value has commas, it is an m2m related field
                if ',' in attr_val:
                    attr_val = tuple(attr_val.split(','))

                container_object_dict[attr_key] = attr_val

            # return instantiated parser
            return parser(container_object_dict)

        else:
            raise Exception('No attributes given in meta data.')
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    Author: Guewen Baconnier
#    Copyright 2013 Camptocamp SA
#
#    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/>.
#
##############################################################################

"""
Producers of events.

Fire the common events:

-  ``on_record_create`` when a record is created
-  ``on_record_write`` when something is written on a record
-  ``on_record_unlink``  when a record is deleted

"""

from openerp import api
from openerp.osv import orm
from .session import ConnectorSession
from .event import (on_record_create,
                    on_record_write,
                    on_record_unlink)

create_original = orm.BaseModel.create

@api.model
@api.returns('self', lambda value: value.id)
def create(self, vals):
    record_id = create_original(self, vals)
    if self.pool.get('connector.installed') is not None:
        session = ConnectorSession(self.env.cr, self.env.uid, context=self.env.context)
        on_record_create.fire(session, self._name, record_id.id, vals)
    return record_id
orm.AbstractModel.create = create

write_original = orm.BaseModel.write

@api.multi
def write(self, vals):
    result = write_original(self, vals)
    if self.pool.get('connector.installed') is not None:
        session = ConnectorSession(self.env.cr, self.env.uid, context=self.env.context)
        if on_record_write.has_consumer_for(session, self._name):
            for record_id in self._ids:
                on_record_write.fire(session, self._name,
                                     record_id, vals)
    return result
orm.AbstractModel.write = write

unlink_original = orm.BaseModel.unlink

def unlink(self, cr, uid, ids, context=None):
    if self.pool.get('connector.installed') is not None:
        if not hasattr(ids, '__iter__'):
            ids = [ids]
        session = ConnectorSession(cr, uid, context=context)
        if on_record_unlink.has_consumer_for(session, self._name):
            for record_id in ids:
                on_record_unlink.fire(session, self._name, record_id)
    return unlink_original(self, cr, uid, ids, context=context)
orm.AbstractModel.unlink = unlink
<commit_msg>[FIX] Tests not working with travis due to 'ImportError: cannot import name api'. Try to fix the tests by avoiding the direct import<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    Author: Guewen Baconnier
#    Copyright 2013 Camptocamp SA
#
#    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/>.
#
##############################################################################

"""
Producers of events.

Fire the common events:

-  ``on_record_create`` when a record is created
-  ``on_record_write`` when something is written on a record
-  ``on_record_unlink``  when a record is deleted

"""

import openerp
from openerp.osv import orm
from .session import ConnectorSession
from .event import (on_record_create,
                    on_record_write,
                    on_record_unlink)

create_original = orm.BaseModel.create

@openerp.api.model
@openerp.api.returns('self', lambda value: value.id)
def create(self, vals):
    record_id = create_original(self, vals)
    if self.pool.get('connector.installed') is not None:
        session = ConnectorSession(self.env.cr, self.env.uid, context=self.env.context)
        on_record_create.fire(session, self._name, record_id.id, vals)
    return record_id
orm.AbstractModel.create = create

write_original = orm.BaseModel.write

@openerp.api.multi
def write(self, vals):
    result = write_original(self, vals)
    if self.pool.get('connector.installed') is not None:
        session = ConnectorSession(self.env.cr, self.env.uid, context=self.env.context)
        if on_record_write.has_consumer_for(session, self._name):
            for record_id in self._ids:
                on_record_write.fire(session, self._name,
                                     record_id, vals)
    return result
orm.AbstractModel.write = write

unlink_original = orm.BaseModel.unlink

def unlink(self, cr, uid, ids, context=None):
    if self.pool.get('connector.installed') is not None:
        if not hasattr(ids, '__iter__'):
            ids = [ids]
        session = ConnectorSession(cr, uid, context=context)
        if on_record_unlink.has_consumer_for(session, self._name):
            for record_id in ids:
                on_record_unlink.fire(session, self._name, record_id)
    return unlink_original(self, cr, uid, ids, context=context)
orm.AbstractModel.unlink = unlink
<|endoftext|>


<commit_before>"""
View which can render and send email from a contact form.

"""

from django.core.urlresolvers import reverse
from django.views.generic.edit import FormView

from .forms import ContactForm

class ContactFormView(FormView):
    form_class = ContactForm
    recipient_list = None
    template_name = 'contact_form/contact_form.html'

    def form_valid(self, form):
        form.save()
        return super(ContactFormView, self).form_valid(form)

    def get_form_kwargs(self):
        # ContactForm instances require instantiation with an
        # HttpRequest.
        kwargs = super(ContactFormView, self).get_form_kwargs()
        kwargs.update({'request': self.request})

        # We may also have been given a recipient list when
        # instantiated.
        if self.recipient_list is not None:
            kwargs.update({'recipient_list': self.recipient_list})
        return kwargs

    def get_success_url(self):
        # This is in a method instead of the success_url attribute
        # because doing it as an attribute would involve a
        # module-level call to reverse(), creating a circular
        # dependency between the URLConf (which imports this module)
        # and this module (which would need to access the URLConf to
        # make the reverse() call).
        return reverse('contact_form_sent')
<commit_msg>Work around Django ticket #25548 in ContactFormView.<commit_after>"""
View which can render and send email from a contact form.

"""

from django.core.urlresolvers import reverse
from django.views.generic.edit import FormView

from .forms import ContactForm

class ContactFormView(FormView):
    form_class = ContactForm
    recipient_list = None
    template_name = 'contact_form/contact_form.html'

    def form_valid(self, form):
        form.save()
        return super(ContactFormView, self).form_valid(form)

    def form_invalid(self, form):
        # tl;dr -- this method is implemented to work around Django
        # ticket #25548, which is present in the Django 1.9 release
        # (but not in Django 1.8).
        #
        # The longer explanation is that in Django 1.9,
        # FormMixin.form_invalid() does not pass the form instance to
        # get_context_data(). This causes get_context_data() to
        # construct a new form instance with the same data in order to
        # put it into the template context, and then any access to
        # that form's ``errors`` or ``cleaned_data`` runs that form
        # instance's validation. The end result is that validation
        # gets run twice on an invalid form submission, which is
        # undesirable for performance reasons.
        #
        # Manually implementing this method, and passing the form
        # instance to get_context_data(), solves this issue (which
        # will be fixed, at the very least, in Django 1.10, and may
        # also be backported into the Django 1.9 release series).
        return self.render_to_response(self.get_context_data(form=form))

    def get_form_kwargs(self):
        # ContactForm instances require instantiation with an
        # HttpRequest.
        kwargs = super(ContactFormView, self).get_form_kwargs()
        kwargs.update({'request': self.request})

        # We may also have been given a recipient list when
        # instantiated.
        if self.recipient_list is not None:
            kwargs.update({'recipient_list': self.recipient_list})
        return kwargs

    def get_success_url(self):
        # This is in a method instead of the success_url attribute
        # because doing it as an attribute would involve a
        # module-level call to reverse(), creating a circular
        # dependency between the URLConf (which imports this module)
        # and this module (which would need to access the URLConf to
        # make the reverse() call).
        return reverse('contact_form_sent')
<|endoftext|>


<commit_before>###
# Imports
###

from __future__ import unicode_literals
from slackclient import SlackClient

import yaml

###
# Classes
###

class Command:
    def __init__(self, name, function, num_args=0):
        self.name = name
        self.function = function
        self.num_args = num_args

class Player:
    def __init__(self, id, name):
        self.id = id
        self.name = name
        self.im_id = get_im_id_for_user_id(self.id)
        self.current_word = None

class Game:
    def __init__(self, players):
        self.players = players
        self.current_round = 1
        self.words = {player.id: [] for player in players}

    def get_partner(self, player):
        if self.players[0].id == player.id:
            return self.players[1]
        return self.players[0]

###
# Global Variables
###

config = yaml.load(file('stony.conf', 'r'))
slack_client = SlackClient(config['SLACK_TOKEN'])

outputs = []

# A map from user id to Game.
user_id_to_game = {}

# A map from user id to Player.
user_id_to_player = {}

###
# Error Handling Functions
###

def handle_missing_params(channel, command):
    message = 'I need more parameters for the command *\'' + command + '\'*.'
    send_message(channel, message)

def handle_unknown_command(channel, command):
    message = 'I do not understand the command *\'' + command + '\'*.'
    send_message(channel, message)

def handle_invalid_username(channel, username):
    message = 'I can\'t find the user *\'' + username + '\'*.'
    send_message(channel, message)

###
# Bot Utility Functions
###

def send_message(channel, message):
    outputs.append([channel, '>>>' + message])

def get_im_id_for_user_id(user_id):
    api_call = slack_client.api_call('im.open', user=user_id)
    if api_call.get('ok'):
        return api_call.get('channel').get('id')
    return None

def get_id_for_username(username):
    api_call = slack_client.api_call('users.list')
    if api_call.get('ok'):
        users = api_call.get('members')
        for user in users:
            if 'name' in user and user.get('name') == username:
                return user.get('id')
    return None

def get_username_for_id(user_id):
    api_call = slack_client.api_call('users.info', user=user_id)
    if api_call.get('ok'):
        return api_call.get('user').get('name')
    return None

###
# Bot Helper Functions
###

def get_player_for_user_id(user_id):
    player = user_id_to_player.get(user_id)
    if player is None:
        username = get_username_for_id(user_id)
        player = Player(user_id, username)
        user_id_to_player[user_id] = player
    return player

###
# Game Functions
###

def start_game(channel, player, new_partner_name):
    if player.name == new_partner_name:
        message = 'Sorry!  This game can\'t be played solo.'
        send_message(channel, message)
        return

    existing_game = user_id_to_game.get(player.id)
    if existing_game != None:
        existing_partner = existing_game.get_partner(player)
        message = 'You\'re already in a game with *' + existing_partner.name + '*.'
        send_message(channel, message)
        return

    new_partner_id = get_id_for_username(new_partner_name)
    new_partner_existing_game = user_id_to_game.get(new_partner_id)
    if new_partner_existing_game != None:
        message = 'Oops!  ' + new_partner_name + ' is already in a game.'
        send_message(channel, message)
        return

    new_partner = get_player_for_user_id(new_partner_id)
    new_game = Game([player, new_partner])
    user_id_to_game[player.id] = new_game
    message = 'You\'re now in a game of _One, Two, Three_ with *' + new_partner_name + '*.\n'
    message += 'Please enter a starting word using `123 word [your_word]`.'
    send_message(channel, message)

    user_id_to_game[new_partner.id] = new_game
    player.current_word = None
    message = 'You\'re now in a game of _One, Two, Three_ with *' + player.name + '*.\n'
    new_partner.current_word = None
    message += 'Please enter a starting word using `123 word [your_word]`.'
    send_message(new_partner.im_id, message)

def register_word(channel, player, word):
    existing_game = user_id_to_game.get(player.id)
    if existing_game == None:
        message = 'You\'re not currently in a game of _One, Two, Three_.'
        send_message(channel, message)
        return

    if player.current_word != None:
        message = 'You\'ve already registered the word *\'' + player.current_word + '\'*.'
        send_message(channel, message)
        return

    player.current_word = word.lower()
    existing_game.words[player.id].append(word)
    message = 'Your word, *\'' + player.current_word + '\'*, is now registered.  Please wait for ' + existing_game.get_partner(player).name + '.'
    send_message(channel, message)

    for existing_player in existing_game.players:
        if existing_player.current_word == None:
            return

    start_next_round(channel, existing_game)

def start_next_round(channel, game):
    if game.players[0].current_word == game.players[1].current_word:
        for player in game.players:
            partner = game.get_partner(player)
            message = 'Congratulations!  You and ' + partner.name + ' both guessed *\'' + player.current_word + '\'* after ' + str(game.current_round) + ' round' + ('' if game.current_round == 1 else 's') + '.  Nicely done!'
            send_message(player.im_id, message)
            user_id_to_game[player.id] = None
        return

    game.current_round += 1
    for player in game.players:
        partner = game.get_partner(player)
        message = 'The words are in: ' + partner.name + ' guessed *\'' + partner.current_word + '\'*.\n'
        message += 'Please enter a new word for pair *[' + player.current_word + ', ' + partner.current_word + ']* using `123 word [your_word]`.'
        send_message(player.im_id, message)

    for player in game.players:
        player.current_word = None

def quit_game(channel, player):
    existing_game = user_id_to_game.get(player.id)
    if existing_game == None:
        message = 'You\'re not currently in a game of _One, Two, Three_.'
        send_message(channel, message)
        return

    for existing_player in existing_game.players:
        user_id_to_game[existing_player.id] = None
        message = ('You have ' if player.id == existing_player.id else player.name + ' has ') + 'quit the game.'
        send_message(existing_player.im_id, message)

###
# Available Commands
###

AVAILABLE_COMMANDS = [
  Command('play', start_game, num_args=1),
  Command('word', register_word, num_args=1),
  Command('quit', quit_game, num_args=0),
]

###
# Bot Main Functions
###

def process_message(data):
    message_text = data['text']

    # We only care about messages starting with '123'.
    if not message_text.startswith('123'):
        return

    # Get the sender's Player object, creating it if necessary.
    message_sender_id = data['user']
    player = get_player_for_user_id(message_sender_id)

    # Ensure this is the player's IM channel.
    channel = data['channel']
    if channel != player.im_id:
        return

    # Retrieve the command.
    message_tokens = message_text.split()
    command = message_tokens[1]
    args = message_tokens[2:]

    cmd = None
    for c in AVAILABLE_COMMANDS:
        if c.name == command:
            cmd = c

    if not cmd:
        handle_unknown_command(channel, command)
        return

    # Ensure we received the required number of arguments.
    if len(args) != cmd.num_args:
        handle_missing_params(channel, command)
        return

    # Execute the command!
    if cmd.num_args == 0:
        cmd.function(channel, player)
    else:
        cmd.function(channel, player, *args)
<commit_msg>Add result reporting<commit_after>###
# Imports
###

from __future__ import unicode_literals
from slackclient import SlackClient

import yaml

###
# Classes
###

class Command:
    def __init__(self, name, function, num_args=0):
        self.name = name
        self.function = function
        self.num_args = num_args

class Player:
    def __init__(self, id, name):
        self.id = id
        self.name = name
        self.im_id = get_im_id_for_user_id(self.id)
        self.current_word = None

class Game:
    def __init__(self, players):
        self.players = players
        self.current_round = 1
        self.words = {player.id: [] for player in players}

    def get_partner(self, player):
        if self.players[0].id == player.id:
            return self.players[1]
        return self.players[0]

###
# Global Variables
###

config = yaml.load(file('stony.conf', 'r'))
slack_client = SlackClient(config['SLACK_TOKEN'])

outputs = []

# A map from user id to Game.
user_id_to_game = {}

# A map from user id to Player.
user_id_to_player = {}

###
# Error Handling Functions
###

def handle_missing_params(channel, command):
    message = 'I need more parameters for the command *\'' + command + '\'*.'
    send_message(channel, message)

def handle_unknown_command(channel, command):
    message = 'I do not understand the command *\'' + command + '\'*.'
    send_message(channel, message)

def handle_invalid_username(channel, username):
    message = 'I can\'t find the user *\'' + username + '\'*.'
    send_message(channel, message)

###
# Bot Utility Functions
###

def send_message(channel, message):
    outputs.append([channel, '>>>' + message])

def get_im_id_for_user_id(user_id):
    api_call = slack_client.api_call('im.open', user=user_id)
    if api_call.get('ok'):
        return api_call.get('channel').get('id')
    return None

def get_id_for_username(username):
    api_call = slack_client.api_call('users.list')
    if api_call.get('ok'):
        users = api_call.get('members')
        for user in users:
            if 'name' in user and user.get('name') == username:
                return user.get('id')
    return None

def get_username_for_id(user_id):
    api_call = slack_client.api_call('users.info', user=user_id)
    if api_call.get('ok'):
        return api_call.get('user').get('name')
    return None

def get_id_for_channel_name(channel_name):
    api_call = slack_client.api_call('channels.list')
    if api_call.get('ok'):
        channels = api_call.get('channels')
        for channel in channels:
            if 'name' in channel and channel.get('name') == channel_name:
                return channel.get('id')
    return None

###
# Bot Helper Functions
###

def get_player_for_user_id(user_id):
    player = user_id_to_player.get(user_id)
    if player is None:
        username = get_username_for_id(user_id)
        player = Player(user_id, username)
        user_id_to_player[user_id] = player
    return player

###
# Game Functions
###

def start_game(channel, player, new_partner_name):
    if player.name == new_partner_name:
        message = 'Sorry!  This game can\'t be played solo.'
        send_message(channel, message)
        return

    existing_game = user_id_to_game.get(player.id)
    if existing_game != None:
        existing_partner = existing_game.get_partner(player)
        message = 'You\'re already in a game with *' + existing_partner.name + '*.'
        send_message(channel, message)
        return

    new_partner_id = get_id_for_username(new_partner_name)
    new_partner_existing_game = user_id_to_game.get(new_partner_id)
    if new_partner_existing_game != None:
        message = 'Oops!  ' + new_partner_name + ' is already in a game.'
        send_message(channel, message)
        return

    player.current_word = None
    new_partner = get_player_for_user_id(new_partner_id)
    new_partner.current_word = None
    new_game = Game([player, new_partner])
    user_id_to_game[player.id] = new_game
    message = 'You\'re now in a game of _One, Two, Three_ with *' + new_partner_name + '*.\n'
    message += 'Please enter a starting word using `123 word [your_word]`.'
    send_message(channel, message)

    user_id_to_game[new_partner.id] = new_game
    message = 'You\'re now in a game of _One, Two, Three_ with *' + player.name + '*.\n'
    message += 'Please enter a starting word using `123 word [your_word]`.'
    send_message(new_partner.im_id, message)

def register_word(channel, player, word):
    existing_game = user_id_to_game.get(player.id)
    if existing_game == None:
        message = 'You\'re not currently in a game of _One, Two, Three_.'
        send_message(channel, message)
        return

    if player.current_word != None:
        message = 'You\'ve already registered the word *\'' + player.current_word + '\'*.'
        send_message(channel, message)
        return

    player.current_word = word.lower()
    existing_game.words[player.id].append(word)
    message = 'Your word, *\'' + player.current_word + '\'*, is now registered.  Please wait for ' + existing_game.get_partner(player).name + '.'
    send_message(channel, message)

    for existing_player in existing_game.players:
        if existing_player.current_word == None:
            return

    start_next_round(channel, existing_game)

def start_next_round(channel, game):
    if game.players[0].current_word == game.players[1].current_word:
        for player in game.players:
            partner = game.get_partner(player)
            message = 'Congratulations!  You and ' + partner.name + ' both guessed *\'' + player.current_word + '\'* after ' + str(game.current_round) + ' round' + ('' if game.current_round == 1 else 's') + '.  Nicely done!'
            send_message(player.im_id, message)
            user_id_to_game[player.id] = None
        report_results(channel, game)
        return

    game.current_round += 1
    for player in game.players:
        partner = game.get_partner(player)
        message = 'The words are in: ' + partner.name + ' guessed *\'' + partner.current_word + '\'*.\n'
        message += 'Please enter a new word for pair *[' + player.current_word + ', ' + partner.current_word + ']* using `123 word [your_word]`.'
        send_message(player.im_id, message)

    for player in game.players:
        player.current_word = None

def report_results(channel, game):
    message = 'This just in!  ' + game.players[0].name + ' and ' + game.players[1].name + ' just completed a game in *' + game.current_round + ' round' + ('' if game.current_round == 1 else 's') + '.*\n'
    message += 'Here\'s the word path:\n'
    message += '*'
    for index in xrange(0, len(game.words[game.players[0]])):
        message += '[' + game.words[game.players[0]] + ', ' + game.words[game.players[1]] + '], '
    message = message[0:-2]
    out_channel = get_id_for_channel_name('one_two_three')
    send_message(out_channel, message)

def quit_game(channel, player):
    existing_game = user_id_to_game.get(player.id)
    if existing_game == None:
        message = 'You\'re not currently in a game of _One, Two, Three_.'
        send_message(channel, message)
        return

    for existing_player in existing_game.players:
        user_id_to_game[existing_player.id] = None
        message = ('You have ' if player.id == existing_player.id else player.name + ' has ') + 'quit the game.'
        send_message(existing_player.im_id, message)

###
# Available Commands
###

AVAILABLE_COMMANDS = [
  Command('play', start_game, num_args=1),
  Command('word', register_word, num_args=1),
  Command('quit', quit_game, num_args=0),
]

###
# Bot Main Functions
###

def process_message(data):
    message_text = data['text']

    # We only care about messages starting with '123'.
    if not message_text.startswith('123'):
        return

    # Get the sender's Player object, creating it if necessary.
    message_sender_id = data['user']
    player = get_player_for_user_id(message_sender_id)

    # Ensure this is the player's IM channel.
    channel = data['channel']
    if channel != player.im_id:
        return

    # Retrieve the command.
    message_tokens = message_text.split()
    command = message_tokens[1]
    args = message_tokens[2:]

    cmd = None
    for c in AVAILABLE_COMMANDS:
        if c.name == command:
            cmd = c

    if not cmd:
        handle_unknown_command(channel, command)
        return

    # Ensure we received the required number of arguments.
    if len(args) != cmd.num_args:
        handle_missing_params(channel, command)
        return

    # Execute the command!
    if cmd.num_args == 0:
        cmd.function(channel, player)
    else:
        cmd.function(channel, player, *args)
<|endoftext|>


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

__all__ = ('WindowsBalloonTip', 'balloon_tip')

import time
import ctypes
from plyer.platforms.win.libs import win_api_defs
from plyer.compat import PY2
from threading import RLock

WS_OVERLAPPED = 0x00000000
WS_SYSMENU = 0x00080000
WM_DESTROY = 2
CW_USEDEFAULT = 8

LR_LOADFROMFILE = 16
LR_DEFAULTSIZE = 0x0040
IDI_APPLICATION = 32512
IMAGE_ICON = 1

NOTIFYICON_VERSION_4 = 4
NIM_ADD = 0
NIM_MODIFY = 1
NIM_DELETE = 2
NIM_SETVERSION = 4
NIF_MESSAGE = 1
NIF_ICON = 2
NIF_TIP = 4
NIF_INFO = 0x10
NIIF_USER = 4
NIIF_LARGE_ICON = 0x20

class WindowsBalloonTip(object):

    _class_atom = 0
    _wnd_class_ex = None
    _hwnd = None
    _hicon = None
    _balloon_icon = None
    _notify_data = None
    _count = 0
    _lock = RLock()

    @staticmethod
    def _get_unique_id():
        WindowsBalloonTip._lock.acquire()
        val = WindowsBalloonTip._count
        WindowsBalloonTip._count += 1
        WindowsBalloonTip._lock.release()
        return val

    def __init__(self, title, message, app_name, app_icon='', timeout=10):
        ''' app_icon if given is a icon file.
        '''

        wnd_class_ex = win_api_defs.get_WNDCLASSEXW()
        class_name = 'PlyerTaskbar' + str(WindowsBalloonTip._get_unique_id())
        if PY2:
            class_name = class_name.decode('utf8')
        wnd_class_ex.lpszClassName = class_name
        # keep ref to it as long as window is alive
        wnd_class_ex.lpfnWndProc =\
            win_api_defs.WindowProc(win_api_defs.DefWindowProcW)
        wnd_class_ex.hInstance = win_api_defs.GetModuleHandleW(None)
        if wnd_class_ex.hInstance is None:
            raise Exception('Could not get windows module instance.')
        class_atom = win_api_defs.RegisterClassExW(wnd_class_ex)
        if class_atom == 0:
            raise Exception('Could not register the PlyerTaskbar class.')
        self._class_atom = class_atom
        self._wnd_class_ex = wnd_class_ex

        # create window
        self._hwnd = win_api_defs.CreateWindowExW(0, class_atom,
            '', WS_OVERLAPPED, 0, 0, CW_USEDEFAULT,
            CW_USEDEFAULT, None, None, wnd_class_ex.hInstance, None)
        if self._hwnd is None:
            raise Exception('Could not get create window.')
        win_api_defs.UpdateWindow(self._hwnd)

        # load icon
        if app_icon:
            icon_flags = LR_LOADFROMFILE | LR_DEFAULTSIZE
            hicon = win_api_defs.LoadImageW(None, app_icon, IMAGE_ICON, 0, 0,
                                            icon_flags)
            if hicon is None:
                raise Exception('Could not load icon {}'.
                                format(icon_path_name))
            self._balloon_icon = self._hicon = hicon
        else:
            self._hicon = win_api_defs.LoadIconW(None,
                ctypes.cast(IDI_APPLICATION, win_api_defs.LPCWSTR))
        self.notify(title, message, app_name)
        if timeout:
            time.sleep(timeout)

    def __del__(self):
        self.remove_notify()
        if self._hicon is not None:
            win_api_defs.DestroyIcon(self._hicon)
        if self._wnd_class_ex is not None:
            win_api_defs.UnregisterClassW(self._class_atom,
                                          self._wnd_class_ex.hInstance)
        if self._hwnd is not None:
            win_api_defs.DestroyWindow(self._hwnd)

    def notify(self, title, message, app_name):
        ''' Displays a balloon in the systray. Can be called multiple times
        with different parameter values.
        '''
        self.remove_notify()
        # add icon and messages to window
        hicon = self._hicon
        flags = NIF_TIP | NIF_INFO
        icon_flag = 0
        if hicon is not None:
            flags |= NIF_ICON
            # if icon is default app's one, don't display it in message
            if self._balloon_icon is not None:
                icon_flag = NIIF_USER | NIIF_LARGE_ICON
        notify_data = win_api_defs.get_NOTIFYICONDATAW(0, self._hwnd,
            id(self), flags, 0, hicon, app_name, 0, 0, message,
            NOTIFYICON_VERSION_4, title, icon_flag, win_api_defs.GUID(),
            self._balloon_icon)

        self._notify_data = notify_data
        if not win_api_defs.Shell_NotifyIconW(NIM_ADD, notify_data):
            raise Exception('Shell_NotifyIconW failed.')
        if not win_api_defs.Shell_NotifyIconW(NIM_SETVERSION,
                                              notify_data):
            raise Exception('Shell_NotifyIconW failed.')

    def remove_notify(self):
        '''Removes the notify balloon, if displayed.
        '''
        if self._notify_data is not None:
            win_api_defs.Shell_NotifyIconW(NIM_DELETE, self._notify_data)
            self._notify_data = None

def balloon_tip(**kwargs):
    WindowsBalloonTip(**kwargs)
<commit_msg>Fix notification ticker error + pep8<commit_after># -- coding: utf-8 --

__all__ = ('WindowsBalloonTip', 'balloon_tip')

import time
import ctypes
from plyer.platforms.win.libs import win_api_defs
from plyer.compat import PY2
from threading import RLock

WS_OVERLAPPED = 0x00000000
WS_SYSMENU = 0x00080000
WM_DESTROY = 2
CW_USEDEFAULT = 8

LR_LOADFROMFILE = 16
LR_DEFAULTSIZE = 0x0040
IDI_APPLICATION = 32512
IMAGE_ICON = 1

NOTIFYICON_VERSION_4 = 4
NIM_ADD = 0
NIM_MODIFY = 1
NIM_DELETE = 2
NIM_SETVERSION = 4
NIF_MESSAGE = 1
NIF_ICON = 2
NIF_TIP = 4
NIF_INFO = 0x10
NIIF_USER = 4
NIIF_LARGE_ICON = 0x20

class WindowsBalloonTip(object):

    _class_atom = 0
    _wnd_class_ex = None
    _hwnd = None
    _hicon = None
    _balloon_icon = None
    _notify_data = None
    _count = 0
    _lock = RLock()

    @staticmethod
    def _get_unique_id():
        WindowsBalloonTip._lock.acquire()
        val = WindowsBalloonTip._count
        WindowsBalloonTip._count += 1
        WindowsBalloonTip._lock.release()
        return val

    def __init__(self, title, message, app_name, app_icon='',
                 timeout=10, **kwargs):
        ''' app_icon if given is a icon file.
        '''

        wnd_class_ex = win_api_defs.get_WNDCLASSEXW()
        class_name = 'PlyerTaskbar' + str(WindowsBalloonTip._get_unique_id())
        if PY2:
            class_name = class_name.decode('utf8')
        wnd_class_ex.lpszClassName = class_name
        # keep ref to it as long as window is alive
        wnd_class_ex.lpfnWndProc =\
            win_api_defs.WindowProc(win_api_defs.DefWindowProcW)
        wnd_class_ex.hInstance = win_api_defs.GetModuleHandleW(None)
        if wnd_class_ex.hInstance is None:
            raise Exception('Could not get windows module instance.')
        class_atom = win_api_defs.RegisterClassExW(wnd_class_ex)
        if class_atom == 0:
            raise Exception('Could not register the PlyerTaskbar class.')
        self._class_atom = class_atom
        self._wnd_class_ex = wnd_class_ex

        # create window
        self._hwnd = win_api_defs.CreateWindowExW(
            0, class_atom,
            '', WS_OVERLAPPED, 0, 0, CW_USEDEFAULT,
            CW_USEDEFAULT, None, None, wnd_class_ex.hInstance, None
        )
        if self._hwnd is None:
            raise Exception('Could not get create window.')
        win_api_defs.UpdateWindow(self._hwnd)

        # load icon
        if app_icon:
            icon_flags = LR_LOADFROMFILE | LR_DEFAULTSIZE
            hicon = win_api_defs.LoadImageW(None, app_icon, IMAGE_ICON, 0, 0,
                                            icon_flags)
            if hicon is None:
                raise Exception('Could not load icon {}'.
                                format(icon_path_name))
            self._balloon_icon = self._hicon = hicon
        else:
            self._hicon = win_api_defs.LoadIconW(
                None,
                ctypes.cast(IDI_APPLICATION, win_api_defs.LPCWSTR)
            )
        self.notify(title, message, app_name)
        if timeout:
            time.sleep(timeout)

    def __del__(self):
        self.remove_notify()
        if self._hicon is not None:
            win_api_defs.DestroyIcon(self._hicon)
        if self._wnd_class_ex is not None:
            win_api_defs.UnregisterClassW(self._class_atom,
                                          self._wnd_class_ex.hInstance)
        if self._hwnd is not None:
            win_api_defs.DestroyWindow(self._hwnd)

    def notify(self, title, message, app_name):
        ''' Displays a balloon in the systray. Can be called multiple times
        with different parameter values.
        '''
        self.remove_notify()
        # add icon and messages to window
        hicon = self._hicon
        flags = NIF_TIP | NIF_INFO
        icon_flag = 0
        if hicon is not None:
            flags |= NIF_ICON
            # if icon is default app's one, don't display it in message
            if self._balloon_icon is not None:
                icon_flag = NIIF_USER | NIIF_LARGE_ICON
        notify_data = win_api_defs.get_NOTIFYICONDATAW(
            0, self._hwnd,
            id(self), flags, 0, hicon, app_name, 0, 0, message,
            NOTIFYICON_VERSION_4, title, icon_flag, win_api_defs.GUID(),
            self._balloon_icon
        )

        self._notify_data = notify_data
        if not win_api_defs.Shell_NotifyIconW(NIM_ADD, notify_data):
            raise Exception('Shell_NotifyIconW failed.')
        if not win_api_defs.Shell_NotifyIconW(NIM_SETVERSION,
                                              notify_data):
            raise Exception('Shell_NotifyIconW failed.')

    def remove_notify(self):
        '''Removes the notify balloon, if displayed.
        '''
        if self._notify_data is not None:
            win_api_defs.Shell_NotifyIconW(NIM_DELETE, self._notify_data)
            self._notify_data = None

def balloon_tip(**kwargs):
    WindowsBalloonTip(**kwargs)
<|endoftext|>


<commit_before>from boilerpipe.extract import Extractor
from joblib import Memory
import numpy as np
import requests

def entry_content(entry):
    contents = [entry.description, entry.content[0].value,  entry.summary]
    return contents[np.argmin(map(len, contents))]

class FailedExtraction(Exception):
    pass

# see http://tomazkovacic.com/blog/2011/06/09/evaluating-text-extraction-algorithms/
def _scrape(url=None, html=None):
    assert (url != html)
    return Extractor(
        extractor='DefaultExtractor',
        html=html) if html is not None else _scrape(
            html=requests.get(url).content)

_memory = Memory(cachedir="content-cache", verbose=1, bytes_limit=10**9)
@_memory.cache(ignore=["entry"])
def url2html(url, entry=None):
    try:
        html = _scrape(url=url).getHTML()
        assert(html)
    except:
        html = '
{title}
\n'.format(title=entry.title) + entry_content(entry)
        assert(html)
    return html

@_memory.cache(ignore=["entry"])
def url2text(url, entry=None):
    try:
        text = _scrape(url=url).getText()
        if len(text) < 40:
            raise FailedExtraction
    except:
        text = (entry.title or '') + "." + (_scrape(html=entry_content(entry)).getText() or '')
        assert(text)
    return text

def entry2text(entry):
    return url2text(entry.link, entry)

def entry2html(entry):
    return url2html(entry.link, entry)
<commit_msg>better name and cover all corner cases ever seen<commit_after>from boilerpipe.extract import Extractor
from joblib import Memory
import numpy as np
import requests

def _get_entry_content(entry):
    contents = [
        entry.get("description", ""),
        entry.get("content", [{}])[0].get("value", ""),
        entry.get("summary", "")
    ]
    return contents[np.argmax(map(len, contents))]

class FailedExtraction(Exception):
    pass

# see http://tomazkovacic.com/blog/2011/06/09/evaluating-text-extraction-algorithms/
def _scrape(url=None, html=None):
    assert (url != html)
    return Extractor(
        extractor='DefaultExtractor',
        html=html) if html is not None else _scrape(
            html=requests.get(url).content)

_memory = Memory(cachedir="content-cache", verbose=1, bytes_limit=10**9)
@_memory.cache(ignore=["entry"])
def url2html(url, entry=None):
    try:
        html = _scrape(url=url).getHTML()
        assert(html)
    except:
        html = '
{title}
\n'.format(title=entry.title) + entry_content(entry)
        assert(html)
    return html

@_memory.cache(ignore=["entry"])
def url2text(url, entry=None):
    try:
        text = _scrape(url=url).getText()
        if len(text) < 40:
            raise FailedExtraction
    except:
        text = (entry.title or '') + "." + (_scrape(html=entry_content(entry)).getText() or '')
        assert(text)
    return text

def entry2text(entry):
    return url2text(entry.link, entry)

def entry2html(entry):
    return url2html(entry.link, entry)
<|endoftext|>


<commit_before>import RPi.GPIO as gpio
import time
#curses is used to capture the keyboard input
import curses
import pygame
from random import randint

#TODO: re-enable pylinter and set it up properly
#TODO: set up a finally that cleans up the GPIOs always instead of just after a keyboardbreak (ctr-c)
class Propulsion(object):
  def __init__(self):
    self.stdscr = curses.initscr()
    curses.endwin()
    #Disable warnings for the GPIOs being in use
    gpio.setwarnings(False)
    #Set the pinmode to BCM
    gpio.setmode(gpio.BCM)
    gpio.setup(18, gpio.OUT)
    gpio.setup(13, gpio.OUT)
    gpio.setup(17, gpio.OUT)
    gpio.setup(22, gpio.OUT)
    gpio.setup(23, gpio.OUT)
    gpio.setup(24, gpio.OUT)

    #Set pulse modulation to 50hz for pin 18 and store that initialization in a variable
    self.pwm1 = gpio.PWM(18, 50)
    self.pwm2 = gpio.PWM(13, 50)
    #Start the pwm at 0% duty cycle
    self.pwm1.start(0)
    self.pwm2.start(0)
    #The normal speed for forwards and backwards momentum
    self.cruisingSpeed = 60
    self.speedRight = 60
    self.speedLeft = 60
    #Initialize the state of the propulsion
    self.state = "awake"
    # The higher the steerforce, the more extreme the steering effect will be (1/2, 1/3 * power of other wheel)
    self.steerForce = 4
    self.quickTurn = True
    #self.laugh()

  def laugh(self):
    pygame.mixer.init()
    pygame.mixer.music.load("laugh.mp3")
    pygame.mixer.music.play()
    while pygame.mixer.music.get_busy() == True:
        continue

  def forward(self):
    print("inching forward with speed "+ str(self.cruisingSpeed))
    # Reset the speed of both wheels to cruising speed to disable left and right modes
    #TODO: put the following 2 lines in a function so the code is more DRY
    self.speedRight = self.speedLeft = self.cruisingSpeed
    self.updateCycle()
    self.state = "forward"
    self.turnWheel("right", "forward")
    self.turnWheel("left", "forward")

  def reverse(self):
    print("awkwardly backing away with speed "+ str(self.cruisingSpeed))
    self.speedRight = self.speedLeft = self.cruisingSpeed
    self.updateCycle()
    self.state = "reverse"
    self.turnWheel("right", "reverse")
    self.turnWheel("left", "reverse")

  def left(self):
    #When driving forward, slow down the left wheel to turn left
    #As of right now, the state has no 'forward left' so it will just output left
    if self.state == "forward" and self.state != "left":
        print("forward left")
        #TODO: keep separate state for forwardleft and right because this sin't dry
        #HEre the wheelspeeds are reset because if you turn forward right after forward left, the wheelspeeds would both be
        # divided by steerforce
        self.speedRight = self.speedLeft = self.cruisingSpeed
        self.speedLeft /= self.steerForce
        self.updateCycle()
    # The next mode is for when the bot stands still
    elif self.state != "forward" and self.state != "reverse":
        print("to the left from " + self.state)
        self.speedRight = self.speedLeft = self.cruisingSpeed
        self.updateCycle()
        self.state = "left"
        # This is a nifty trick to control quickturning. If quickturn is true, the left wheel turns backward,
        # the right wheel forward; if quickturn is false, the left wheel stops (false, false) the right wheel turns forward.
        self.turnWheel("left", "reverse") if self.quickTurn else self.turnWheel("left", "stop")
        self.turnWheel("right", "forward")

  def right(self):
    print("to the right ")
    if self.state == "forward" and self.state != "right":
        print("forward right")
        #Todo, move speed to the turnWheel function as well, makes for easier code when turning when reversing
        #Maybe its best to turn wheels into an object and have the rest of the script only rack if the bot is moving forwards or backwards
        self.speedRight = self.speedLeft = self.cruisingSpeed
        self.speedRight /= self.steerForce
        self.updateCycle()
    # The next mode is for when the bot stands still
    elif self.state != "forward" and self.state != "reverse":
        print("to the right from " + self.state)
        #reset the speed of both wheels before turning.
        self.speedRight = self.speedLeft = self.cruisingSpeed
        self.updateCycle()
        self.state = "right"
        self.turnWheel("right", "reverse") if self.quickTurn else self.turnWheel("right", "stop")
        self.turnWheel("left", "forward")

  def goDuckYour(self):
    '''This function selects a random sequence and executes it.
    Each sequence contains 1 or more instructions like "left" or "forward. Each instruction is coupled to a function
    each function sets the GPIOs up. After each instruction the sequence will wait for a number of seconds.
    The coding in this function may look a bit ugly that's what you get with custom sequences...'''
    print("Loose yourself (autonomous mode)")
    testMoves = [self.left, self.right, self.reverse]
    waggleMoves = [self.left, self.right]
    sequence2 = ["enableQuickTurn"]
    waggleMode = True

    def test():
        ''''This mode is for testing out fun sequences. Just pop em in testmoves and watch her go.
        If you find a nice combo, save it an array, give it a name in the modemapping object and gooo'''
        print("Executing testmoves")
        for instruction in testMoves:
            instruction()
            time.sleep(5)

    def waggle():
        '''Waggle works like this: left,right,left,random quickturn, repeat patter with %chance through recursion'''
        print("Executing waggle")
        self.enableQuickTurn(False)
        for i in range(3):
            waggleMoves[0]()
            time.sleep(.5)
            waggleMoves[1]()
            time.sleep(.5)
        self.enableQuickTurn(True)
        waggleMoves[randint(0,1)]()
        time.sleep(.4)
        if (randint(0,9) >= 4):
            waggle()
    #TODO: find a way to interrupt sleep so this process can be stopped by the user
    #This dict holds the dirrent modes for autonomous movement
    modeMapping = {
        "1" : test,
        "2" : waggle,
        "3" : "spin"
    }
    userInput = self.stdscr.getch()
    option = curses.keyname(userInput)
    curses.endwin()
    modeMapping[option]()

    self.stop()

  def start(self):
    try:
      while True:
        curses.cbreak()
        userInput = self.stdscr.getch()
        option = curses.keyname(userInput)
        curses.endwin()
        print("input is: " + str(option))
        #we could convert this to a dictionary mapping but that wouldnt work for the more complex options
        if option == "w":
            self.forward()
        elif option == "s":
            self.reverse()
        elif option == "a":
            self.left()
        elif option == "d":
            self.right()
        elif option == "b":
            self.stop()
        elif option == "0":
            self.goDuckYour()
        #Todo check if both speeds are within bounds
        elif option=="k" and self.cruisingSpeed <= 90:
          self.cruisingSpeed += 10
          self.speedRight *= 1.1
          self.speedLeft *= 1.1
          self.updateCycle()
        elif option=="m" and self.cruisingSpeed >= 40:
          self.cruisingSpeed -= 10
          self.speedRight *= .9
          self.speedLeft *= .9
          self.updateCycle()
        #build in a bit of a delay to not overwork the processor too much
        time.sleep(.1)
    except KeyboardInterrupt:
      self.quit()

  def stop(self):
    print("Stop! Hammertime")
    self.state = "still"
    self.turnWheel("left", "stop")
    self.turnWheel("right", "stop")

  def turnWheel(self, wheel, direction):
    if wheel == "left":
        if direction == "forward":
            gpio.output(23, True)
            gpio.output(24, False)
        elif direction == "reverse":
            gpio.output(23, False)
            gpio.output(24, True)
        elif direction == "stop":
            gpio.output(23, False)
            gpio.output(24, False)
    if wheel == "right":
        if direction == "forward":
            gpio.output(17, True)
            gpio.output(22, False)
        elif direction == "reverse":
            gpio.output(17, False)
            gpio.output(22, True)
        elif direction == "stop":
            gpio.output(17, False)
            gpio.output(22, False)

  def enableQuickTurn(self, value):
    self.quickTurn = value

  def updateCycle(self):
    self.pwm1.ChangeDutyCycle(self.speedRight)
    self.pwm2.ChangeDutyCycle(self.speedLeft)
    # if wheel == "left":
    #     self.pwm2.ChangeDutyCycle(speed)
    # elif wheel == "right":
    #     self.pwm1.ChangeDutyCycle(speed)

  def quit(self):
    print("quitting program")
    self.pwm1.ChangeDutyCycle(0)
    self.pwm2.ChangeDutyCycle(0)

    gpio.cleanup()
    curses.endwin()
propulsion = Propulsion()
#propulsion.init()
propulsion.start()

<commit_msg>Changed the way speed changes happen for the tires. There's still a small bug in there when you feed the function bigger changes like -30 speed, but we'll get to that later. 🌝<commit_after>import RPi.GPIO as gpio
import time
#curses is used to capture the keyboard input
import curses
import pygame
from random import randint

#TODO: re-enable pylinter and set it up properly
#TODO: set up a finally that cleans up the GPIOs always instead of just after a keyboardbreak (ctr-c)
class Propulsion(object):
  def __init__(self):
    self.stdscr = curses.initscr()
    curses.endwin()
    #Disable warnings for the GPIOs being in use
    gpio.setwarnings(False)
    #Set the pinmode to BCM
    gpio.setmode(gpio.BCM)
    gpio.setup(18, gpio.OUT)
    gpio.setup(13, gpio.OUT)
    gpio.setup(17, gpio.OUT)
    gpio.setup(22, gpio.OUT)
    gpio.setup(23, gpio.OUT)
    gpio.setup(24, gpio.OUT)

    #Set pulse modulation to 50hz for pin 18 and store that initialization in a variable
    self.pwm1 = gpio.PWM(18, 50)
    self.pwm2 = gpio.PWM(13, 50)
    #Start the pwm at 0% duty cycle
    self.pwm1.start(0)
    self.pwm2.start(0)
    #The normal speed for forwards and backwards momentum
    self.cruisingSpeed = 60
    self.speedRight = 60
    self.speedLeft = 60
    #Initialize the state of the propulsion
    self.state = "awake"
    # The higher the steerforce, the more extreme the steering effect will be (1/2, 1/3 * power of other wheel)
    self.steerForce = 4
    self.quickTurn = True
    #self.laugh()

  def laugh(self):
    pygame.mixer.init()
    pygame.mixer.music.load("laugh.mp3")
    pygame.mixer.music.play()
    while pygame.mixer.music.get_busy() == True:
        continue

  def forward(self):
    print("inching forward with speed "+ str(self.cruisingSpeed))
    # Reset the speed of both wheels to cruising speed to disable left and right modes
    #TODO: put the following 2 lines in a function so the code is more DRY
    self.speedRight = self.speedLeft = self.cruisingSpeed
    self.updateCycle()
    self.state = "forward"
    self.turnWheel("right", "forward")
    self.turnWheel("left", "forward")

  def reverse(self):
    print("awkwardly backing away with speed "+ str(self.cruisingSpeed))
    self.speedRight = self.speedLeft = self.cruisingSpeed
    self.updateCycle()
    self.state = "reverse"
    self.turnWheel("right", "reverse")
    self.turnWheel("left", "reverse")

  def left(self):
    #When driving forward, slow down the left wheel to turn left
    #As of right now, the state has no 'forward left' so it will just output left
    if self.state == "forward" and self.state != "left":
        print("forward left")
        #TODO: keep separate state for forwardleft and right because this sin't dry
        #HEre the wheelspeeds are reset because if you turn forward right after forward left, the wheelspeeds would both be
        # divided by steerforce
        self.speedRight = self.speedLeft = self.cruisingSpeed
        self.speedLeft /= self.steerForce
        self.updateCycle()
    # The next mode is for when the bot stands still
    elif self.state != "forward" and self.state != "reverse":
        print("to the left from " + self.state)
        self.speedRight = self.speedLeft = self.cruisingSpeed
        self.updateCycle()
        self.state = "left"
        # This is a nifty trick to control quickturning. If quickturn is true, the left wheel turns backward,
        # the right wheel forward; if quickturn is false, the left wheel stops (false, false) the right wheel turns forward.
        self.turnWheel("left", "reverse") if self.quickTurn else self.turnWheel("left", "stop")
        self.turnWheel("right", "forward")

  def right(self):
    print("to the right ")
    if self.state == "forward" and self.state != "right":
        print("forward right")
        #Todo, move speed to the turnWheel function as well, makes for easier code when turning when reversing
        #Maybe its best to turn wheels into an object and have the rest of the script only rack if the bot is moving forwards or backwards
        self.speedRight = self.speedLeft = self.cruisingSpeed
        self.speedRight /= self.steerForce
        self.updateCycle()
    # The next mode is for when the bot stands still
    elif self.state != "forward" and self.state != "reverse":
        print("to the right from " + self.state)
        #reset the speed of both wheels before turning.
        self.speedRight = self.speedLeft = self.cruisingSpeed
        self.updateCycle()
        self.state = "right"
        self.turnWheel("right", "reverse") if self.quickTurn else self.turnWheel("right", "stop")
        self.turnWheel("left", "forward")

  def goDuckYour(self):
    '''This function selects a random sequence and executes it.
    Each sequence contains 1 or more instructions like "left" or "forward. Each instruction is coupled to a function
    each function sets the GPIOs up. After each instruction the sequence will wait for a number of seconds.
    The coding in this function may look a bit ugly that's what you get with custom sequences...'''
    print("Loose yourself (autonomous mode)")
    testMoves = [self.left, self.right, self.reverse]
    waggleMoves = [self.left, self.right]
    sequence2 = ["enableQuickTurn"]
    waggleMode = True

    def test():
        ''''This mode is for testing out fun sequences. Just pop em in testmoves and watch her go.
        If you find a nice combo, save it an array, give it a name in the modemapping object and gooo'''
        print("Executing testmoves")
        for instruction in testMoves:
            instruction()
            time.sleep(3)

    def spin():
        ''''Time to go crazy'''
        print("WUBBA LUBBA DUB DUUUUB")
        #TODO: change this after I fix the math for changeSpeed so it accepts an absolute number
        self.changeSpeed(-10)
        self.left()
        time.sleep(.5)
        while (self.cruisingSpeed <= 90):
            self.changeSpeed(10)
            self.left()
            time.sleep(.5)
        self.right()
        time.sleep(2)

    def waggle():
        '''Waggle works like this: left,right,left,random quickturn, repeat patter with %chance through recursion'''
        print("Executing waggle")
        self.enableQuickTurn(False)
        for i in range(3):
            waggleMoves[0]()
            time.sleep(.3)
            waggleMoves[1]()
            time.sleep(.3)
        self.enableQuickTurn(True)
        waggleMoves[randint(0,1)]()
        time.sleep(1)
        if (randint(0,9) >= 4):
            waggle()
    #TODO: find a way to interrupt sleep so this process can be stopped by the user
    #This dict holds the dirrent modes for autonomous movement
    modeMapping = {
        "1" : test,
        "2" : waggle,
        "3" : spin
    }
    userInput = self.stdscr.getch()
    option = curses.keyname(userInput)
    curses.endwin()
    modeMapping[option]()
    self.stop()

  def start(self):
    try:
      while True:
        curses.cbreak()
        userInput = self.stdscr.getch()
        option = curses.keyname(userInput)
        curses.endwin()
        print("input is: " + str(option))
        #we could convert this to a dictionary mapping but that wouldnt work for the more complex options
        if option == "w":
            self.forward()
        elif option == "s":
            self.reverse()
        elif option == "a":
            self.left()
        elif option == "d":
            self.right()
        elif option == "b":
            self.stop()
        elif option == "0":
            self.goDuckYour()
        elif option=="k":
          self.changeSpeed(self.cruisingSpeed + 10)
        elif option=="m":
          self.changeSpeed(self.cruisingSpeed - 10)
        #build in a bit of a delay to not overwork the processor too much
        time.sleep(.02)
    except KeyboardInterrupt:
      self.quit()

  def changeSpeed(self, value):
    #TODO: Im pretty sure this function can work with absolute values being passed, as in
    # We want the speed to be 90 so we pass in 90. I started doing the math below and then realized Im
    # Too drunk/tired to finish it. Ah well, let future Laurens worry about it
    # Also it might be better to have a function that sets both the wheel direction and the speed. Then,
    # The wheels can be objects with direction and speed as properties, yay OOP
    # if (value >= 40 and value <= 90):
    #     self.cruisingSpeed = value
    #     self.speedRight *=
    print("changeSpeed called with: " + str(value) + " cruisingspeed: " + str(self.cruisingSpeed))
    if ( (self.cruisingSpeed + value) <= 100 and (self.cruisingSpeed + value) >= 30 ):
        self.cruisingSpeed += value
        self.speedRight *= (1 + value / 100)
        self.speedLeft *= (1 + value / 100)
        if (self.speedRight > 100):
            print("right over limit: " + str(self.speedRight))
            self.speedRight = 100
    self.updateCycle()

  def stop(self):
    print("Stop! Hammertime")
    self.state = "still"
    self.turnWheel("left", "stop")
    self.turnWheel("right", "stop")

  def turnWheel(self, wheel, direction):
    if wheel == "left":
        if direction == "forward":
            gpio.output(23, True)
            gpio.output(24, False)
        elif direction == "reverse":
            gpio.output(23, False)
            gpio.output(24, True)
        elif direction == "stop":
            gpio.output(23, False)
            gpio.output(24, False)
    if wheel == "right":
        if direction == "forward":
            gpio.output(17, True)
            gpio.output(22, False)
        elif direction == "reverse":
            gpio.output(17, False)
            gpio.output(22, True)
        elif direction == "stop":
            gpio.output(17, False)
            gpio.output(22, False)

  def enableQuickTurn(self, value):
    self.quickTurn = value

  def updateCycle(self):
    self.pwm1.ChangeDutyCycle(self.speedRight)
    self.pwm2.ChangeDutyCycle(self.speedLeft)

  def quit(self):
    print("quitting program")
    self.pwm1.ChangeDutyCycle(0)
    self.pwm2.ChangeDutyCycle(0)
    gpio.cleanup()
    curses.endwin()

propulsion = Propulsion()
propulsion.start()
<|endoftext|>


<commit_before># Copyright (c) 2015 Davide Gessa
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.

from pycoin import networks
from colorlog import ColoredFormatter
import logging
import os
import platform
import sys

def app_data_path (appauthor, appname, roaming=True):
	if sys.platform.startswith('java'):
		os_name = platform.java_ver()[3][0]
		if os_name.startswith('Windows'):
			system = 'win32'
		elif os_name.startswith('Mac'):
			system = 'darwin'
		else:
			system = 'linux2'
	else:
		system = sys.platform

	if system == "win32":
		if appauthor is None:
			appauthor = appname
		const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA"
		path = os.path.normpath(_get_win_folder(const))
		if appname:
			if appauthor is not False:
				path = os.path.join(path, appauthor, appname)
			else:
				path = os.path.join(path, appname)
	elif system == 'darwin':
		path = os.path.expanduser('~/Library/Application Support/')
		if appname:
			path = os.path.join(path, appname)
	else:
		path = os.getenv('XDG_DATA_HOME', os.path.expanduser("~/"))
		if appname:
			path = os.path.join(path, '.'+appname)
	return path

VERBOSE = 5
APP_VERSION = '0.6.9.4'
APP_NAME = 'contractvm'
APP_AUTHOR = 'Davide Gessa'
DATA_DIR = app_data_path (appauthor=APP_AUTHOR, appname=APP_NAME)
TEMP_DIR_RELATIVE = '/temp/'
TEMP_DIR = DATA_DIR + TEMP_DIR_RELATIVE
DAPPS_DIR_RELATIVE = '/dapps/'
DAPPS_DIR = DATA_DIR + DAPPS_DIR_RELATIVE

BACKEND_PROTOCOLS = ['rpc', 'chainsoapi', 'node']

CHAINS = {
		'XTN' : {
			'code': 'XTN',
			'base_fee': 60000,
			'genesis_block': "0000000033ab95c1231f6dede34aad172068250354beccfad156072c6d37e093",
			'genesis_height': 625697,
			'name': networks.full_network_name_for_netcode ('XTN'),
			'seeds': [ ]
		},
		'BTC' : {
			'code': 'BTC',
			'base_fee': 40000,
			'genesis_block': "000000000000000002f214ea3bc2c195ed11f9195ab07229151befab03ada10b",
			'genesis_height': 385720,
			'name': networks.full_network_name_for_netcode ('BTC')
		},
		'XLT' : {
			'code': 'XLT',
			'base_fee': 450000,
			'genesis_block': "22f9d7316645dc02cdd05c32db902ae4aca582c7f138b2b7cecbc58d269e58a6",
			'genesis_height': 741198,
			'name': networks.full_network_name_for_netcode ('XLT')
		},
		'LTC' : {
			'code': 'LTC',
			'base_fee': 100000,
			'genesis_block': "",
			'genesis_height': 329203,
			'name': networks.full_network_name_for_netcode ('LTC')
		},
		'DOGE': {
			'code': 'DOGE',
			'base_fee': 100000000,
			'genesis_block': "7a0d505875129fcf5f88b6bad6f083214d341130dde3053019d38a23258b4f1e",
			'genesis_height': 981606,
			'name': networks.full_network_name_for_netcode ('DOGE')
		}
	}

CONF = {
	'chain': 'XTN',
	'regtest': False,
	'discard-old-blocks': False,
	'maxpeers': 25,
	'dapps': {
		'list': [],
		'enabled': []
	},
	'backend': {
		'protocol': ['node'],
	},
	'api': {
		'enabled': True,
		'threads': 1,
		'port': 8181
	},
	'dht': {
		'seeds': [ '51.254.215.160:80' ],
		'port': 5051
	}
}

formatter = ColoredFormatter(
	'%(log_color)s[%(asctime)-8s] %(module)s: %(message_log_color)s%(message)s',
	datefmt=None,
	reset=True,
	log_colors = {
		'DEBUG':	'blue',
		'PLUGINFO': 'purple',
		'INFO':	 'green',
		'WARNING':  'yellow',
		'ERROR':	'red',
		'CRITICAL': 'red',
	},
	secondary_log_colors={
		'message': {
			'DEBUG':	'purple',
			'PLUGINFO': 'blue',
			'INFO':	 'yellow',
			'WARNING':  'green',
			'ERROR':	'yellow',
			'CRITICAL': 'red',
		}
	},
	style = '%'
)

stream = logging.StreamHandler ()
stream.setFormatter (formatter)

logger = logging.getLogger (APP_NAME)
logger.addHandler (stream)

logging.addLevelName (15, "PLUGINFO")
logging.Logger.pluginfo = lambda self, message, *args, **kws: self._log(15, message, args, **kws) if self.isEnabledFor(15) else None
<commit_msg>chain reset<commit_after># Copyright (c) 2015 Davide Gessa
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.

from pycoin import networks
from colorlog import ColoredFormatter
import logging
import os
import platform
import sys

def app_data_path (appauthor, appname, roaming=True):
	if sys.platform.startswith('java'):
		os_name = platform.java_ver()[3][0]
		if os_name.startswith('Windows'):
			system = 'win32'
		elif os_name.startswith('Mac'):
			system = 'darwin'
		else:
			system = 'linux2'
	else:
		system = sys.platform

	if system == "win32":
		if appauthor is None:
			appauthor = appname
		const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA"
		path = os.path.normpath(_get_win_folder(const))
		if appname:
			if appauthor is not False:
				path = os.path.join(path, appauthor, appname)
			else:
				path = os.path.join(path, appname)
	elif system == 'darwin':
		path = os.path.expanduser('~/Library/Application Support/')
		if appname:
			path = os.path.join(path, appname)
	else:
		path = os.getenv('XDG_DATA_HOME', os.path.expanduser("~/"))
		if appname:
			path = os.path.join(path, '.'+appname)
	return path

VERBOSE = 5
APP_VERSION = '0.6.9.5'
APP_NAME = 'contractvm'
APP_AUTHOR = 'Davide Gessa'
DATA_DIR = app_data_path (appauthor=APP_AUTHOR, appname=APP_NAME)
TEMP_DIR_RELATIVE = '/temp/'
TEMP_DIR = DATA_DIR + TEMP_DIR_RELATIVE
DAPPS_DIR_RELATIVE = '/dapps/'
DAPPS_DIR = DATA_DIR + DAPPS_DIR_RELATIVE

BACKEND_PROTOCOLS = ['rpc', 'chainsoapi', 'node']

CHAINS = {
		'XTN' : {
			'code': 'XTN',
			'base_fee': 60000,
			'genesis_block': "0000000033ab95c1231f6dede34aad172068250354beccfad156072c6d37e093",
			'genesis_height': 625698,
			'name': networks.full_network_name_for_netcode ('XTN'),
			'seeds': [ ]
		},
		'BTC' : {
			'code': 'BTC',
			'base_fee': 40000,
			'genesis_block': "000000000000000002f214ea3bc2c195ed11f9195ab07229151befab03ada10b",
			'genesis_height': 385720,
			'name': networks.full_network_name_for_netcode ('BTC')
		},
		'XLT' : {
			'code': 'XLT',
			'base_fee': 450000,
			'genesis_block': "22f9d7316645dc02cdd05c32db902ae4aca582c7f138b2b7cecbc58d269e58a6",
			'genesis_height': 741198,
			'name': networks.full_network_name_for_netcode ('XLT')
		},
		'LTC' : {
			'code': 'LTC',
			'base_fee': 100000,
			'genesis_block': "",
			'genesis_height': 329203,
			'name': networks.full_network_name_for_netcode ('LTC')
		},
		'DOGE': {
			'code': 'DOGE',
			'base_fee': 100000000,
			'genesis_block': "7a0d505875129fcf5f88b6bad6f083214d341130dde3053019d38a23258b4f1e",
			'genesis_height': 981606,
			'name': networks.full_network_name_for_netcode ('DOGE')
		}
	}

CONF = {
	'chain': 'XTN',
	'regtest': False,
	'discard-old-blocks': False,
	'maxpeers': 25,
	'dapps': {
		'list': [],
		'enabled': []
	},
	'backend': {
		'protocol': ['node'],
	},
	'api': {
		'enabled': True,
		'threads': 1,
		'port': 8181
	},
	'dht': {
		'seeds': [ '51.254.215.160:80' ],
		'port': 5051
	}
}

formatter = ColoredFormatter(
	'%(log_color)s[%(asctime)-8s] %(module)s: %(message_log_color)s%(message)s',
	datefmt=None,
	reset=True,
	log_colors = {
		'DEBUG':	'blue',
		'PLUGINFO': 'purple',
		'INFO':	 'green',
		'WARNING':  'yellow',
		'ERROR':	'red',
		'CRITICAL': 'red',
	},
	secondary_log_colors={
		'message': {
			'DEBUG':	'purple',
			'PLUGINFO': 'blue',
			'INFO':	 'yellow',
			'WARNING':  'green',
			'ERROR':	'yellow',
			'CRITICAL': 'red',
		}
	},
	style = '%'
)

stream = logging.StreamHandler ()
stream.setFormatter (formatter)

logger = logging.getLogger (APP_NAME)
logger.addHandler (stream)

logging.addLevelName (15, "PLUGINFO")
logging.Logger.pluginfo = lambda self, message, *args, **kws: self._log(15, message, args, **kws) if self.isEnabledFor(15) else None
<|endoftext|>


<commit_before># (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.

# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

__version__ = '2.7.0.a1'
__author__ = 'Ansible, Inc.'
__codename__ = 'In the Light'
<commit_msg>Add post modifier to version<commit_after># (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.

# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

__version__ = '2.7.0.a1.post0'
__author__ = 'Ansible, Inc.'
__codename__ = 'In the Light'
<|endoftext|>