<commit_before># -*- coding: utf-8 -*-
#
# Copyright 2012 James Thornton (http://jamesthornton.com)
# BSD License (see LICENSE for details)
#
"""
Base classes for modeling domain objects that wrap vertices and edges.

"""
import six   # Python 3
import inspect
import types
from collections import OrderedDict, Callable

from bulbs.property import Property
from bulbs.element import Element, Vertex, VertexProxy, Edge, EdgeProxy, coerce_vertices, build_data
from bulbs.utils import initialize_element, get_one_result, get_logger, extract
import bulbs.utils as utils

# Model Modes
DEFAULT = 1
STRICT = 2

log = get_logger(__name__)

class Bundle(OrderedDict):

    def as_tuple(self):
        return tuple(self.values())

class ModelMeta(type):
    """Metaclass used to set database Property definitions on Models"""

    def __init__(cls, name, base, namespace):
        # store the Property definitions on the class as a dictionary
        # mapping the Property key to the Property instance
        cls._properties = cls._get_initial_properties()
        cls._register_properties(namespace)

    def _get_initial_properties(cls):
        # Get Properties defined in the parent and inherit them.
        # Or if the Model doesn't have a parent Model, set it to an empty dict
        properties = {}
        parent_properties = getattr(cls, '_properties', None)
        if parent_properties:
            properties = parent_properties.copy()
        return properties

    def _register_properties(cls, namespace):
        # loop through the class namespace looking for database Property instances
        # e.g. age = Integer()
        for key in namespace: # Python 3
            value = namespace[key]
            assert key not in cls._properties, "Can't redefine Property '%s'" % key
            if isinstance(value, Property):
                property_instance = value  # for clarity
                cls._properties[key] = property_instance
                cls._set_property_name(key,property_instance)
                cls._initialize_property(key,property_instance)
                # not doing this b/c some Properties are calculated at savetime
                #delattr(cls, key)

    def _set_property_name(cls, key, property_instance):
        """Set the Property name; use the attribute name unless explicitly set via kwd param."""
        if property_instance.name is None:
            property_instance.name = key

    def _initialize_property(cls, key, property_instance):
        """Set the Model class attribute based on the Property definition."""
        if property_instance.fget:
            # this is a calculated property (should it persist?) -- TODO: make this configurable
            # wrapped fset and fdel in str() to make the default None work with getattr
            fget = getattr(cls, property_instance.fget)
            fset = getattr(cls, str(property_instance.fset), None)
            fdel = getattr(cls, str(property_instance.fdel), None)
            property_value = property(fget, fset, fdel)
        else:
            property_value = None
        setattr(cls, key, property_value)

class Model(six.with_metaclass(ModelMeta, object)):  # Python 3

    _mode = DEFAULT

    def __setattr__(self, key, value):
        if key in self._properties:
            # we want Model Properties to be set be set as actual attributes
            # because they can be real Python propertes or calculated values,
            # which are calcualted/set upon each save().
            value = self._coerce_property_value(key, value)
            object.__setattr__(self, key, value)
        else:
            Element.__setattr__(self, key, value)

    def _coerce_property_value(self, key, value):
        if value is not None:
            property_instance = self._properties[key]
            value = property_instance.coerce(key, value)
        return value

    def _set_property_defaults(self):
        for key in self._properties:
            default_value = self._get_property_default(key)
            Model.__setattr__(self, key, default_value)

    def _get_property_default(self, key):
        # The value entered could be a scalar or a function name
        # TODO: make this work for model methods?
        # defer the call until all properties are set? Or only for calculated properties?
        property_instance = self._properties[key]
        default_value = property_instance.default
        if isinstance(default_value, Callable):
            default_value = default_value()
        return default_value

    def _set_keyword_attributes(self, _data, kwds):
        # may have passed in keys that are not defined as Properties
        data = build_data(_data, kwds)
        for key in data: # Python 3
            value = data[key]  #
            # Notice that __setattr__ is overloaded
            # Must explicitly use Model's setattr because of multiple inheritence
            Model.__setattr__(self, key, value)

    def _set_property_data(self):
        """
        Sets Property data when an element is being initialized, after it is
        retrieved from the DB -- we set it to None if it won't set.
        """
        type_system = self._client.type_system
        for key in self._properties: # Python 3
            property_instance = self._properties[key]
            name = property_instance.name
            value = self._data.get(key, None)
            # what about fset and fget values?
            value = property_instance.convert_to_python(type_system, key, value)
            # TODO: Maybe need to wrap this in try/catch too
            object.__setattr__(self, key, value)

    def _get_property_data(self):
        """Returns validated Property data, ready to be saved in the DB."""
        data = self._get_initial_data()
        type_var = self._client.config.type_var
        type_system = self._client.type_system
        if hasattr(self, type_var):
            # add element_type to the database properties to be saved;
            # but don't worry about "label", it's always saved on the edge
            data[type_var] = getattr(self, type_var)
        for key in self._properties:  # Python 3
            property_instance = self._properties[key]
            value = self._get_property_value(key)
            property_instance.validate(key, value)
            #name = property_instance.name
            value = property_instance.convert_to_db(type_system, value)
            data[key] = value
        return data

    def _get_property_value(self, key):
        value = getattr(self, key)
        if isinstance(value, Callable):
            return value()
        return value

    def _get_initial_data(self):
        """Returns empty dict if mode is set to strict, else return the existing _data."""
        data = {} if self._mode == STRICT else self._data.copy()
        return data

    def get_index(self, index_name):
        """Returns an Index in the Registery or None."""
        try:
            index = self._client.registry.get_index(index_name)
        except KeyError:
            index = None
        return index

    def get_index_keys(self):
        # Defaults to None (index all keys)
        return None

    def get_bundle(self, _data=None, **kwds):
        # It's just on save that you don't set Property defaults.
        # You can here because they will be overridden by set_keyword_attributes.
        self._set_property_defaults()
        self._set_keyword_attributes(_data, kwds)
        data = self._get_property_data()
        index_name = self.get_index_name(self._client.config)
        keys = self.get_index_keys()
        pairs = [('data', data), ('index_name', index_name), ('keys', keys)]
        return Bundle(pairs)

    def get_property_keys(self):
        return self._properties.keys()

    def map(self):
        """
        Returns the Model's property data.

        :rtype: dict

        """
        # Overloading map() here so calculated props are returned properly.
        # Calculated props shouldn't be stored, but their components should be.
        data = dict()
        # Iterating over self._properties instead of _data like in Element
        # in case new props have been set but not saved
        for key in self._properties:
            data[key] = getattr(self, key)
        return data

class Node(Vertex,Model):
    """
    Node is a Vertex model. It's an abstract base class used to create classes
    that model domain objects. It's not meant to be used directly.

    To use this, create a subclass specific to the type of data you are storing.

    Example model declaration::

        from bulbs.model import Node
        from bulbs.property import String, Integer

        class Person(Node):
            element_type = "person"

            name = String(nullable=False)
            age = Integer()

    Example usage::

        >>> from person import Person
        >>> from bulbs.neo4jserver import Graph
        >>> g = Graph()

        # Add a "people" proxy to the Graph object for the Person model:
        >>> g.add_proxy("people", Person)

        # Use it to create a Person node, which also saves it in the database:
        >>> james = g.people.create(name="James Thornton")
        >>> james.eid
        3
        >>> james.name
        'James Thornton'

        # Get the node (again) from the database by its element ID:
        >>> james = g.people.get(james.eid)

        # Update the node and save it in the database:
        >>> james.age = 34
        >>> james.save()

        # Lookup people using the Person model's primary index:
        >>> nodes = g.people.index.lookup(name="James Thornton")

    """
    def __getattr__(self,name):
        """
        Returns the value of the database property for the given name.

        :param name: The name of the data property.
        :type name: str

        :raises: AttributeError

        :rtype: str, int, long, float, list, dict, or None

        """
        try:
            return self._data[name]
        except:
            raise AttributeError(name)

    @classmethod
    def get_element_type(cls, config):
        element_type = getattr(cls, config.type_var)
        return element_type

    @classmethod
    def get_element_key(cls, config):
        return cls.get_element_type(config)

    @classmethod
    def get_index_name(cls, config):
        return cls.get_element_type(config)

    @classmethod
    def get_proxy_class(cls):
        return NodeProxy

    def _initialize(self, result):
        # this is called by the initialize_element util;
        # putting it here to ensure method resolution order.
        # initialize all non-DB properties here
        Vertex._initialize(self,result)
        self._initialized = False
        self._set_property_data()
        self._initialized = True

    def save(self):
        """Saves/updates the element's data in the database."""
        data = self._get_property_data()
        index_name = self.get_index_name(self._client.config)
        keys = self.get_index_keys()
        return self._client.update_indexed_vertex(self._id, data, index_name, keys)

    #:
    #: Override the _create and _update methods to cusomize behavior.
    #:

    def _create(self, _data, kwds):
        # bundle is an OrderedDict containing data, index_name, and keys
        data, index_name, keys = self.get_bundle(_data, **kwds).as_tuple()
        result = self._client.create_indexed_vertex(data, index_name, keys).one()
        self._initialize(result)

    def _update(self, _id, _data, kwds):
        data, index_name, keys = self.get_bundle(_data, **kwds).as_tuple()
        result = self._client.update_indexed_vertex(_id, data, index_name, keys).one()
        self._initialize(result)

class Relationship(Edge,Model):
    """
    An abstract base class used to create classes that model domain objects. It is
    not meant to be used directly

    To use this, create a subclass specific to the type of data you are
    storing.

    Example usage for an edge between a blog entry node and its creating user::

        class Knows(Relationship):
            label = "knows"

            timestamp = Float(default="current_timestamp", nullable=False)

            def current_timestamp(self):
                return time.time()

    Example usage::

          >>> from person import Person, Knows
          >>> from bulbs.neo4jserver import Graph
          >>> g = Graph()

          # Add proxy interfaces to the Graph object for each custom Model:
          >>> g.add_proxy("people", Person)
          >>> g.add_proxy("knows", Knows)

          # Create two Person nodes, which are automatically saved in the database:
          >>> james = g.people.create(name="James")
          >>> julie = g.people.create(name="Julie")

          # Create a "knows" relationship between James and Julie:
          >>> knows = g.knows.create(james,julie)
          >>> knows.timestamp

          # Get the people James knows (the outgoing vertices labeled "knows")
          >>> friends = james.outV('knows')

    """
    @classmethod
    def get_label(cls, config):
        label = getattr(cls, config.label_var)
        return label

    @classmethod
    def get_element_key(cls, config):
        return cls.get_label(config)

    @classmethod
    def get_index_name(cls, config):
        return cls.get_label(config)

    @classmethod
    def get_proxy_class(cls):
        return RelationshipProxy

    def _initialize(self,result):
        # this is called by initialize_element;
        # putting it here to ensure method resolution order
        # initialize all non-DB properties here
        Edge._initialize(self,result)
        self._initialized = False
        self._set_property_data()
        self._initialized = True

    def save(self):
        """Saves/updates the element's data in the database."""
        data = self._get_property_data()
        return self._client.update_edge(self._id, data)

    #
    # Override the _create and _update methods to customize behavior.
    #

    def _create(self, outV, inV, _data, kwds):
        label = self.get_label(self._client.config)
        outV, inV = coerce_vertices(outV, inV)
        data, index_name, keys = self.get_bundle(_data, **kwds).as_tuple()
        result = self._client.create_edge(outV, label, inV, data).one()
        self._initialize(result)

    def _update(self, _id, _data, kwds):
        data, index_name, keys = self.get_bundle(_data, **kwds).as_tuple()
        result = self._client.update_edge(_id, data).one()
        self._initialize(result)

class NodeProxy(VertexProxy):

    # make these have the same signature as VertexProxy

    def create(self, _data=None, **kwds):
        node = self.element_class(self.client)
        node._create(_data, kwds)
        return node

    def update(self, _id, _data=None, **kwds):
        node = self.element_class(self.client)
        node._update(_id, _data, kwds)
        return node

    def get_all(self):
        """Returns all the elements for the model type."""
        config = self.client.config
        type_var = config.type_var
        element_type = self.element_class.get_element_type(config)
        return self.index.lookup(type_var,element_type)

    def get_property_keys(self):
        return self.element_class._properties.keys()

class RelationshipProxy(EdgeProxy):

    def create(self, outV, inV, _data=None, **kwds):
        relationship = self.element_class(self.client)
        relationship._create(outV, inV, _data, kwds)
        return relationship

    def update(self, _id, _data=None, **kwds):
        relationship = self.element_class(self.client)
        relationship._update(_id, _data, kwds)
        return relationship

    def get_all(self):
        """Returns all the relationships for the label."""
        # TODO: find a blueprints method that returns all edges for a given label
        # because you many not want to index edges
        config = self.client.config
        label_var = config.label_var
        label = self.element_class.get_label(config)
        return self.index.lookup(label_var,label)

    def get_property_keys(self):
        return self.element_class._properties.keys()

<commit_msg>a few more Model tweaks<commit_after># -*- coding: utf-8 -*-
#
# Copyright 2012 James Thornton (http://jamesthornton.com)
# BSD License (see LICENSE for details)
#
"""
Base classes for modeling domain objects that wrap vertices and edges.

"""
import six   # Python 3
import inspect
import types
from collections import OrderedDict, Callable

from bulbs.property import Property
from bulbs.element import Element, Vertex, VertexProxy, Edge, EdgeProxy, coerce_vertices, build_data
from bulbs.utils import initialize_element, get_one_result, get_logger, extract
import bulbs.utils as utils

# Model Modes
DEFAULT = 1
STRICT = 2

log = get_logger(__name__)

class Bundle(OrderedDict):

    def as_tuple(self):
        return tuple(self.values())

class ModelMeta(type):
    """Metaclass used to set database Property definitions on Models"""

    def __init__(cls, name, base, namespace):
        # store the Property definitions on the class as a dictionary
        # mapping the Property key to the Property instance
        cls._properties = cls._get_initial_properties()
        cls._register_properties(namespace)

    def _get_initial_properties(cls):
        # Get Properties defined in the parent and inherit them.
        # Or if the Model doesn't have a parent Model, set it to an empty dict
        properties = {}
        parent_properties = getattr(cls, '_properties', None)
        if parent_properties:
            properties = parent_properties.copy()
        return properties

    def _register_properties(cls, namespace):
        # loop through the class namespace looking for database Property instances
        # e.g. age = Integer()
        for key in namespace: # Python 3
            value = namespace[key]
            assert key not in cls._properties, "Can't redefine Property '%s'" % key
            if isinstance(value, Property):
                property_instance = value  # for clarity
                cls._properties[key] = property_instance
                cls._set_property_name(key,property_instance)
                cls._initialize_property(key,property_instance)
                # not doing this b/c some Properties are calculated at savetime
                #delattr(cls, key)

    def _set_property_name(cls, key, property_instance):
        """Set the Property name; use the attribute name unless explicitly set via kwd param."""
        if property_instance.name is None:
            property_instance.name = key

    def _initialize_property(cls, key, property_instance):
        """Set the Model class attribute based on the Property definition."""
        if property_instance.fget:
            # this is a calculated property (should it persist?) -- TODO: make this configurable
            # wrapped fset and fdel in str() to make the default None work with getattr
            fget = getattr(cls, property_instance.fget)
            fset = getattr(cls, str(property_instance.fset), None)
            fdel = getattr(cls, str(property_instance.fdel), None)
            property_value = property(fget, fset, fdel)
        else:
            property_value = None
        setattr(cls, key, property_value)

class Model(six.with_metaclass(ModelMeta, object)):  # Python 3

    _mode = DEFAULT

    def __setattr__(self, key, value):
        if key in self._properties:
            # we want Model Properties to be set be set as actual attributes
            # because they can be real Python propertes or calculated values,
            # which are calcualted/set upon each save().
            value = self._coerce_property_value(key, value)
            object.__setattr__(self, key, value)
        else:
            Element.__setattr__(self, key, value)

    def _coerce_property_value(self, key, value):
        if value is not None:
            property_instance = self._properties[key]
            value = property_instance.coerce(key, value)
        return value

    def _set_property_defaults(self):
        for key in self._properties:
            default_value = self._get_property_default(key)
            Model.__setattr__(self, key, default_value)

    def _get_property_default(self, key):
        # The value entered could be a scalar or a function name
        # TODO: make this work for model methods?
        # defer the call until all properties are set? Or only for calculated properties?
        property_instance = self._properties[key]
        default_value = property_instance.default
        if isinstance(default_value, Callable):
            default_value = default_value()
        return default_value

    def _set_keyword_attributes(self, _data, kwds):
        # may have passed in keys that are not defined as Properties
        data = build_data(_data, kwds)
        for key in data: # Python 3
            value = data[key]  #
            # Notice that __setattr__ is overloaded
            # Must explicitly use Model's setattr because of multiple inheritence
            Model.__setattr__(self, key, value)

    def _set_property_data(self):
        """
        Sets Property data when an element is being initialized, after it is
        retrieved from the DB -- we set it to None if it won't set.
        """
        type_system = self._client.type_system
        for key in self._properties: # Python 3
            property_instance = self._properties[key]
            name = property_instance.name
            value = self._data.get(key, None)
            # what about fset and fget values?
            value = property_instance.convert_to_python(type_system, key, value)
            # TODO: Maybe need to wrap this in try/catch too
            object.__setattr__(self, key, value)

    def _get_property_data(self):
        """Returns validated Property data, ready to be saved in the DB."""
        data = self._get_initial_data()
        type_var = self._client.config.type_var
        type_system = self._client.type_system
        if hasattr(self, type_var):
            # add element_type to the database properties to be saved;
            # but don't worry about "label", it's always saved on the edge
            data[type_var] = getattr(self, type_var)
        for key in self._properties:  # Python 3
            property_instance = self._properties[key]
            value = self._get_property_value(key)
            property_instance.validate(key, value)
            #name = property_instance.name
            value = property_instance.convert_to_db(type_system, value)
            data[key] = value
        return data

    def _get_property_value(self, key):
        value = getattr(self, key)
        if isinstance(value, Callable):
            return value()
        return value

    def _get_initial_data(self):
        """Returns empty dict if mode is set to strict, else return the existing _data."""
        data = {} if self._mode == STRICT else self._data.copy()
        return data

    def get_index(self, index_name):
        """Returns an Index in the Registery or None."""
        try:
            index = self._client.registry.get_index(index_name)
        except KeyError:
            index = None
        return index

    def get_index_keys(self):
        # Defaults to None (index all keys)
        return None

    def get_bundle(self, _data=None, **kwds):
        # It's just on save that you don't set Property defaults.
        # You can here because they will be overridden by set_keyword_attributes.
        self._set_property_defaults()
        self._set_keyword_attributes(_data, kwds)
        # Bundle is an OrderedDict with a custom as_tuple() method, so order matters
        bundle = Bundle()
        bundle['data'] = self._get_property_data()
        bundle['index_name'] = self.get_index_name(self._client.config)
        bundle['keys'] = self.get_index_keys()
        return bundle

    def get_property_keys(self):
        return self._properties.keys()

    def map(self):
        """
        Returns the Model's property data.

        :rtype: dict

        """
        # Overloading map() here so calculated props are returned properly.
        # Calculated props shouldn't be stored, but their components should be.
        data = dict()
        # Iterating over self._properties instead of _data like in Element
        # in case new props have been set but not saved
        for key in self._properties:
            data[key] = getattr(self, key)
        return data

class Node(Vertex,Model):
    """
    Node is a Vertex model. It's an abstract base class used to create classes
    that model domain objects. It's not meant to be used directly.

    To use this, create a subclass specific to the type of data you are storing.

    Example model declaration::

        from bulbs.model import Node
        from bulbs.property import String, Integer

        class Person(Node):
            element_type = "person"

            name = String(nullable=False)
            age = Integer()

    Example usage::

        >>> from person import Person
        >>> from bulbs.neo4jserver import Graph
        >>> g = Graph()

        # Add a "people" proxy to the Graph object for the Person model:
        >>> g.add_proxy("people", Person)

        # Use it to create a Person node, which also saves it in the database:
        >>> james = g.people.create(name="James Thornton")
        >>> james.eid
        3
        >>> james.name
        'James Thornton'

        # Get the node (again) from the database by its element ID:
        >>> james = g.people.get(james.eid)

        # Update the node and save it in the database:
        >>> james.age = 34
        >>> james.save()

        # Lookup people using the Person model's primary index:
        >>> nodes = g.people.index.lookup(name="James Thornton")

    """
    def __getattr__(self,name):
        """
        Returns the value of the database property for the given name.

        :param name: The name of the data property.
        :type name: str

        :raises: AttributeError

        :rtype: str, int, long, float, list, dict, or None

        """
        try:
            return self._data[name]
        except:
            raise AttributeError(name)

    @classmethod
    def get_element_type(cls, config):
        element_type = getattr(cls, config.type_var)
        return element_type

    @classmethod
    def get_element_key(cls, config):
        return cls.get_element_type(config)

    @classmethod
    def get_index_name(cls, config):
        return cls.get_element_type(config)

    @classmethod
    def get_proxy_class(cls):
        return NodeProxy

    def save(self):
        """Saves/updates the element's data in the database."""
        data = self._get_property_data()
        index_name = self.get_index_name(self._client.config)
        keys = self.get_index_keys()
        self._client.update_indexed_vertex(self._id, data, index_name, keys)

    #:
    #: Override the _create and _update methods to cusomize behavior.
    #:

    def _create(self, _data, kwds):
        # bundle is an OrderedDict containing data, index_name, and keys
        data, index_name, keys = self.get_bundle(_data, **kwds).as_tuple()
        result = self._client.create_indexed_vertex(data, index_name, keys).one()
        self._initialize(result)

    def _update(self, _id, _data, kwds):
        data, index_name, keys = self.get_bundle(_data, **kwds).as_tuple()
        result = self._client.update_indexed_vertex(_id, data, index_name, keys).one()
        self._initialize(result)

    def _initialize(self, result):
        # this is called by the initialize_element util;
        # putting it here to ensure method resolution order.
        # initialize all non-DB properties here
        Vertex._initialize(self,result)
        self._initialized = False
        self._set_property_data()
        self._initialized = True

class Relationship(Edge,Model):
    """
    An abstract base class used to create classes that model domain objects. It is
    not meant to be used directly

    To use this, create a subclass specific to the type of data you are
    storing.

    Example usage for an edge between a blog entry node and its creating user::

        class Knows(Relationship):
            label = "knows"

            timestamp = Float(default="current_timestamp", nullable=False)

            def current_timestamp(self):
                return time.time()

    Example usage::

          >>> from person import Person, Knows
          >>> from bulbs.neo4jserver import Graph
          >>> g = Graph()

          # Add proxy interfaces to the Graph object for each custom Model:
          >>> g.add_proxy("people", Person)
          >>> g.add_proxy("knows", Knows)

          # Create two Person nodes, which are automatically saved in the database:
          >>> james = g.people.create(name="James")
          >>> julie = g.people.create(name="Julie")

          # Create a "knows" relationship between James and Julie:
          >>> knows = g.knows.create(james,julie)
          >>> knows.timestamp

          # Get the people James knows (the outgoing vertices labeled "knows")
          >>> friends = james.outV('knows')

    """
    @classmethod
    def get_label(cls, config):
        label = getattr(cls, config.label_var)
        return label

    @classmethod
    def get_element_key(cls, config):
        return cls.get_label(config)

    @classmethod
    def get_index_name(cls, config):
        return cls.get_label(config)

    @classmethod
    def get_proxy_class(cls):
        return RelationshipProxy

    def save(self):
        """Saves/updates the element's data in the database."""
        data = self._get_property_data()
        self._client.update_edge(self._id, data)

    #
    # Override the _create and _update methods to customize behavior.
    #

    def _create(self, outV, inV, _data, kwds):
        label = self.get_label(self._client.config)
        outV, inV = coerce_vertices(outV, inV)
        data, index_name, keys = self.get_bundle(_data, **kwds).as_tuple()
        result = self._client.create_edge(outV, label, inV, data).one()
        self._initialize(result)

    def _update(self, _id, _data, kwds):
        data, index_name, keys = self.get_bundle(_data, **kwds).as_tuple()
        result = self._client.update_edge(_id, data).one()
        self._initialize(result)

    def _initialize(self,result):
        # this is called by initialize_element;
        # putting it here to ensure method resolution order
        # initialize all non-DB properties here
        Edge._initialize(self,result)
        self._initialized = False
        self._set_property_data()
        self._initialized = True

class NodeProxy(VertexProxy):

    # make these have the same signature as VertexProxy

    def create(self, _data=None, **kwds):
        node = self.element_class(self.client)
        node._create(_data, kwds)
        return node

    def update(self, _id, _data=None, **kwds):
        node = self.element_class(self.client)
        node._update(_id, _data, kwds)
        return node

    def get_all(self):
        """Returns all the elements for the model type."""
        config = self.client.config
        type_var = config.type_var
        element_type = self.element_class.get_element_type(config)
        return self.index.lookup(type_var,element_type)

    def get_property_keys(self):
        return self.element_class._properties.keys()

class RelationshipProxy(EdgeProxy):

    def create(self, outV, inV, _data=None, **kwds):
        relationship = self.element_class(self.client)
        relationship._create(outV, inV, _data, kwds)
        return relationship

    def update(self, _id, _data=None, **kwds):
        relationship = self.element_class(self.client)
        relationship._update(_id, _data, kwds)
        return relationship

    def get_all(self):
        """Returns all the relationships for the label."""
        # TODO: find a blueprints method that returns all edges for a given label
        # because you many not want to index edges
        config = self.client.config
        label_var = config.label_var
        label = self.element_class.get_label(config)
        return self.index.lookup(label_var,label)

    def get_property_keys(self):
        return self.element_class._properties.keys()

<|endoftext|>


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

AUTHOR = u'Python Users Group Nepal'
SITENAME = u'Python Users Group Nepal'
SITETITLE = AUTHOR
TAGLINE = u'#PyNepal'
SITEURL = ''
FAVICON_URL = 'https://www.python.org/static/favicon.ico'
DISPLAY_PAGES_ON_MENU = False

PATH = 'content'

TIMEZONE = 'Asia/Kathmandu'

DEFAULT_LANG = u'en'

# Feed generation is usually not desired when developing
FEED_ALL_ATOM = None
CATEGORY_FEED_ATOM = None
TRANSLATION_FEED_ATOM = None

# Blogroll
LINKS = (('Python', 'http://python.org/'),)

# Social widget
SOCIAL = (('group', 'https://www.meetup.com/PythonNepal/'),
          ('facebook', 'https://www.facebook.com/groups/pythonnepal/'),
          ('youtube', 'https://www.youtube.com/channel/UC7EWmhPyAIHDsXY93C34eXA'),
          ('rss', 'feeds/all.atom.xml'),)

DEFAULT_PAGINATION = False

# Uncomment following line if you want document-relative URLs when developing
# RELATIVE_URLS = True

THEME = "pure-single"
COVER_IMG_URL = "https://upload.wikimedia.org/wikipedia/commons/4/40/Nepal_Patan_Mangal.jpg"

STATIC_PATHS = ["static", "extra"]

# Extra metadata dictionaries keyed by relative path
EXTRA_PATH_METADATA = {
    'extra/CNAME': {'path': 'CNAME'}
}

MENUITEMS = [
    ("Companies", "http://0.0.0.0:8000/pages/pythoninnepal.html"),
    ("Developers", "http://0.0.0.0:8000/pages/developers.html"),
    ("Resources", "http://0.0.0.0:8000/pages/resources.html"),
    ("Meetups", "http://0.0.0.0:8000/pages/meetups.html"),
    ("Videos", "http://0.0.0.0:8000/pages/videos.html")
]

#
# Use the article's filename instead of the article's title for the
# URL. This way conflict due to similar titles can be avoided
#
SLUGIFY_SOURCE = "basename"

CUSTOM_CSS = "static/css/custom.css"
<commit_msg>Edit and updated as https in every url<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*- #
from __future__ import unicode_literals

AUTHOR = u'Python Users Group Nepal'
SITENAME = u'Python Users Group Nepal'
SITETITLE = AUTHOR
TAGLINE = u'#PyNepal'
SITEURL = ''
FAVICON_URL = 'https://www.python.org/static/favicon.ico'
DISPLAY_PAGES_ON_MENU = False

PATH = 'content'

TIMEZONE = 'Asia/Kathmandu'

DEFAULT_LANG = u'en'

# Feed generation is usually not desired when developing
FEED_ALL_ATOM = None
CATEGORY_FEED_ATOM = None
TRANSLATION_FEED_ATOM = None

# Blogroll
LINKS = (('Python', 'http://python.org/'),)

# Social widget
SOCIAL = (('group', 'https://www.meetup.com/PythonNepal/'),
          ('facebook', 'https://www.facebook.com/groups/pythonnepal/'),
          ('youtube', 'https://www.youtube.com/channel/UC7EWmhPyAIHDsXY93C34eXA'),
          ('rss', 'feeds/all.atom.xml'),)

DEFAULT_PAGINATION = False

# Uncomment following line if you want document-relative URLs when developing
# RELATIVE_URLS = True

THEME = "pure-single"
COVER_IMG_URL = "https://upload.wikimedia.org/wikipedia/commons/4/40/Nepal_Patan_Mangal.jpg"

STATIC_PATHS = ["static", "extra"]

# Extra metadata dictionaries keyed by relative path
EXTRA_PATH_METADATA = {
    'extra/CNAME': {'path': 'CNAME'}
}

MENUITEMS = [
    ("Companies", "https://0.0.0.0:8000/pages/pythoninnepal.html"),
    ("Developers", "https://0.0.0.0:8000/pages/developers.html"),
    ("Resources", "https://0.0.0.0:8000/pages/resources.html"),
    ("Meetups", "https://0.0.0.0:8000/pages/meetups.html"),
    ("Videos", "https://0.0.0.0:8000/pages/videos.html")
]

#
# Use the article's filename instead of the article's title for the
# URL. This way conflict due to similar titles can be avoided
#
SLUGIFY_SOURCE = "basename"

CUSTOM_CSS = "static/css/custom.css"
<|endoftext|>


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

import sys
sys.path.append('/usr/lib/bup')

import os
from subprocess import PIPE, Popen, call
import contextlib
import json

# Unix, Windows and old Macintosh end-of-line
newlines = ['\n', '\r\n', '\r']
def unbuffered(proc, stream='stdout'):
	stream = getattr(proc, stream)
	with contextlib.closing(stream):
		while True:
			out = []
			last = stream.read(1)
			# Don't loop forever
			if last == '' and proc.poll() is not None:
				break
			while last not in newlines:
				# Don't loop forever
				if last == '' and proc.poll() is not None:
					break
				out.append(last)
				last = stream.read(1)
			out = ''.join(out)
			yield out

class BupWorker:
	def __init__(self, bup_dir=None):
		self.dir = None

		# Save default dir now, otherwise BUP_DIR will be overwritten in the future
		self.default_dir = os.environ.get('BUP_DIR', os.path.expanduser('~/.bup'))

		# Set bup exe
		os.environ['BUP_MAIN_EXE'] = os.environ.get('BUP_MAIN_EXE', 'bup')

		if bup_dir is not None:
			self.set_dir(bup_dir)

	def get_default_dir(self):
		return self.default_dir

	def set_dir(self, bup_dir):
		self.dir = bup_dir
		os.environ['BUP_DIR'] = bup_dir

	def get_dir(self):
		return self.dir

	def init(self, callbacks={}):
		return self.run(['init'], callbacks)

	def index(self, dirpath, opts={}, callbacks={}):
		args = ['index', '-u', dirpath]
		if 'exclude_paths' in opts:
			for excluded in opts['exclude_paths']:
				args.extend(('--exclude', excluded))
		if 'exclude_rxs' in opts:
			for excluded in opts['exclude_rxs']:
				args.extend(('--exclude-rx', excluded))
		if 'one_file_system' in opts and opts['one_file_system']:
			args.append('--one-file-system')

		return self.run(args, callbacks)

	def save(self, dirpath, opts={}, callbacks={}):
		args = ['save', '-n', opts['name'], dirpath]
		return self.run(args, callbacks)

	def fuse(self, mount_path, callbacks={}):
		self.run(['fuse', mount_path], callbacks)

	def restore(self, from_path, to_path, callbacks={}):
		self.run(['restore', '-C', to_path, from_path], callbacks)

	def run(self, args, callbacks={}):
		env = {'BUP_FORCE_TTY': '2'}
		if self.dir is not None:
			env['BUP_DIR'] = self.dir

		# Start subprocess

		# patched_cmd = os.path.dirname(__file__)+'/cmd/'+args[0]+'-cmd.py'
		# if os.path.isfile(patched_cmd):
		# 	args[0] = patched_cmd
		# 	args.insert(0, sys.executable)
		#
		# 	if 'onprogress' in callbacks:
		# 		args += ['--format', 'json']
		# 		def onstderr(line):
		# 			progress = None
		# 			try:
		# 				progress = json.loads(line)
		# 			except ValueError, e:
		# 				if 'onstatus' in callbacks:
		# 					callbacks['onstatus'](line)
		# 				else:
		# 					print(line)
		# 				return
		# 			callbacks['onprogress'](progress)
		# 		callbacks['stderr'] = onstderr

		args.insert(0, os.environ['BUP_MAIN_EXE'])

		if 'onstatus' in callbacks:
			callbacks['stderr'] = callbacks['onstatus']

		proc = Popen(args, env=env, stdout=None, stderr=PIPE, universal_newlines=True)

		if "stderr" in callbacks:
			for line in unbuffered(proc, 'stderr'):
				callbacks["stderr"](line)
		elif "stdout" in callbacks:
			for line in unbuffered(proc, 'stdout'):
				callbacks["stdout"](line)

		if "onclose" in callbacks:
			callbacks["onclose"](proc.poll())
<commit_msg>Adds more variables to PATH when executing bup, fixes #24<commit_after>#!/usr/bin/env python2

import sys
sys.path.append('/usr/lib/bup')

import os
from subprocess import PIPE, Popen, call
import contextlib
import json

# Unix, Windows and old Macintosh end-of-line
newlines = ['\n', '\r\n', '\r']
def unbuffered(proc, stream='stdout'):
	stream = getattr(proc, stream)
	with contextlib.closing(stream):
		while True:
			out = []
			last = stream.read(1)
			# Don't loop forever
			if last == '' and proc.poll() is not None:
				break
			while last not in newlines:
				# Don't loop forever
				if last == '' and proc.poll() is not None:
					break
				out.append(last)
				last = stream.read(1)
			out = ''.join(out)
			yield out

class BupWorker:
	def __init__(self, bup_dir=None):
		self.dir = None

		# Save default dir now, otherwise BUP_DIR will be overwritten in the future
		self.default_dir = os.environ.get('BUP_DIR', os.path.expanduser('~/.bup'))

		# Set bup exe
		os.environ['BUP_MAIN_EXE'] = os.environ.get('BUP_MAIN_EXE', 'bup')

		if bup_dir is not None:
			self.set_dir(bup_dir)

	def get_default_dir(self):
		return self.default_dir

	def set_dir(self, bup_dir):
		self.dir = bup_dir
		os.environ['BUP_DIR'] = bup_dir

	def get_dir(self):
		return self.dir

	def init(self, callbacks={}):
		return self.run(['init'], callbacks)

	def index(self, dirpath, opts={}, callbacks={}):
		args = ['index', '-u', dirpath]
		if 'exclude_paths' in opts:
			for excluded in opts['exclude_paths']:
				args.extend(('--exclude', excluded))
		if 'exclude_rxs' in opts:
			for excluded in opts['exclude_rxs']:
				args.extend(('--exclude-rx', excluded))
		if 'one_file_system' in opts and opts['one_file_system']:
			args.append('--one-file-system')

		return self.run(args, callbacks)

	def save(self, dirpath, opts={}, callbacks={}):
		args = ['save', '-n', opts['name'], dirpath]
		return self.run(args, callbacks)

	def fuse(self, mount_path, callbacks={}):
		self.run(['fuse', mount_path], callbacks)

	def restore(self, from_path, to_path, callbacks={}):
		self.run(['restore', '-C', to_path, from_path], callbacks)

	def run(self, args, callbacks={}):
		env = {
			'BUP_FORCE_TTY': '2',
			'BUP_MAIN_EXE': os.environ['BUP_MAIN_EXE'],
			'PATH': os.environ['PATH']
		}
		if self.dir is not None:
			env['BUP_DIR'] = self.dir

		args.insert(0, os.environ['BUP_MAIN_EXE'])

		if 'onstatus' in callbacks:
			callbacks['stderr'] = callbacks['onstatus']

		proc = Popen(args, env=env, stdout=None, stderr=PIPE, universal_newlines=True)

		if "stderr" in callbacks:
			for line in unbuffered(proc, 'stderr'):
				callbacks["stderr"](line)
		elif "stdout" in callbacks:
			for line in unbuffered(proc, 'stdout'):
				callbacks["stdout"](line)

		if "onclose" in callbacks:
			callbacks["onclose"](proc.poll())
<|endoftext|>


<commit_before>from cendr import app, autoconvert, ds, db, cache
from cendr import json_serial
from flask import render_template, request, url_for, redirect, make_response, Response, abort
from cendr.models import strain
from collections import OrderedDict
import json
import os
import yaml
import stripe
try:
    from google.appengine.api import mail
except:
    pass # Importing this not always important...
from cendr.emails import order_submission
from gcloud.datastore.entity import Entity
from datetime import datetime
import pytz
from dateutil.relativedelta import relativedelta
#
# Global Strain Map
#

@app.route('/strain/global-strain-map/')
@cache.memoize(50)
def map_page():
    title = "Global Strain Map"
    bcs = OrderedDict([("Strain", url_for("strain_listing_page")), ("Global-Strain-Map", "")])
    strain_list_dicts = []
    strain_listing = list(strain.select().filter(strain.reference_strain == True)
        .filter(strain.latitude.is_null() == False).execute())
    strain_listing = json.dumps([x.__dict__["_data"] for x in strain_listing], default=json_serial)
    return render_template('map.html', **locals())

#
# Strain Metadata
#

@app.route('/strain/metadata.tsv')
@cache.memoize(50)
def strain_metadata():
    strain_listing = list(strain.select().filter(
        strain.isotype != None).tuples().execute())
    def generate():
        yield '\t'.join(strain._meta.sorted_field_names[1:21]) + "\n"
        for row in strain_listing:
            row = list(row)
            for k, f in enumerate(row):
                if type(f) == unicode:
                    row[k] = f.encode('ascii', 'ignore')
            yield '\t'.join(map(str, row[1:21])) + "\n"
    return Response(generate(), mimetype="text/csv")

#
# Isotype View
#

@app.route('/strain/<isotype_name>/')
@cache.memoize(50)
def isotype_page(isotype_name):
    page_title = isotype_name
    page_type = "isotype"
    obj = isotype_name
    rec = list(strain.filter(strain.isotype == isotype_name)
                .order_by(strain.latitude).dicts().execute())
    ref_strain = [x for x in rec if x["reference_strain"] == True][0]
    strain_json_output = json.dumps([x for x in rec if x["latitude"] != None],  default=json_serial)
    return render_template('strain.html', **locals())

#
# Strain Catalog
#

@app.route('/strain/')
@cache.memoize(50)
def strain_listing_page():
    bcs = OrderedDict([("Strain", None)])
    title = "Strain Catalog"

    if 'warning' in request.args:
        warning = request.args["warning"]

    strain_listing = strain.select(strain.strain,
                                   strain.reference_strain,
                                   strain.isotype,
                                   strain.previous_names,
                                   strain.set_1,
                                   strain.set_2,
                                   strain.set_3,
                                   strain.set_4,
                                   strain.set_divergent).filter(strain.isotype != None).order_by(strain.isotype).execute()
    return render_template('strain_catalog.html', **locals())

#
# Strain Submission
#

@app.route('/strain/submit/')
def strain_submission_page():
    bcs = OrderedDict([("Strain", url_for("strain_listing_page")), ("Strain Submission", "")])
    title = "Strain Submission"
    return render_template('strain_submission.html', **locals())

#
# Protocols
#

@app.route("/strain/protocols/")
@cache.cached(timeout=50)
def protocols():
    title = "Protocols"
    bcs = OrderedDict([("Strain", url_for("strain_listing_page")), ("Protocols", "")])
    protocols = yaml.load(open("cendr/static/content/data/protocols.yaml", 'r'))
    return render_template('protocols.html', **locals())

#
# Strain Ordering Pages
#

def calculate_total(item_list):
    item_price_list = {}
    for i in item_list:
        if i == "set_divergent":
            item_price_list[i] = 10000
        elif i.startswith("set"):
            item_price_list[i] = 40000
        else:
            item_price_list[i] = 1000
    return item_price_list

@app.route('/order', methods=['GET','POST'])
def order_page():
    bcs = OrderedDict([("Strain", "/strain/"), ("Order", "")])
    title = "Order"
    strain_listing = list(set(request.form.getlist('item')))
    if (len(strain_listing) == 0):
        return redirect(url_for("strain_listing_page"))
    items = request.form.getlist("item")
    # Retreive SKU's for prices
    items = calculate_total(items)
    total = sum(items.values())
    field_list = ['name', 'phone', 'email', 'shipping-account', 'address']
    print(request.form)
    if 'shipping-service' in request.form:
        # Check that all pieces are filled out.
        missing_fields = []
        for i in field_list:
            if i in request.form:
                if not request.form[i]:
                    missing_fields.append(i)
                    warning = "Missing Some Fields"
        if len(missing_fields) == 0:
            o = ds.get(ds.key("cendr-order", "count"))
            o["order-number"] += 1
            order = Entity(ds.key('cendr-order'))
            for k in field_list:
                order[k] = request.form[k]
            order["items"] = [u"{k}:{v}".format(k=k, v=v) for k,v in items.items()]
            order["total"] = total
            order['submitted'] = datetime.now(pytz.timezone("America/Chicago"))
            order['order-number'] = o['order-number']
            order['shipping-service'] = request.form['shipping-service']
            with ds.transaction():
                ds.put(o)
                ds.put(order)
            order_hash = order.key.id
            mail.send_mail(sender="CeNDR <andersen-lab@appspot.gserviceaccount.com>",
               to=order["email"],
               subject="CeNDR Order #" + str(order["order-number"]),
               body=order_submission.format(order_hash=order_hash))
            return redirect(url_for("order_confirmation", order_hash=order_hash), code=302)

    return render_template('order.html', **locals())

@app.route("/order/<order_hash>/")
def order_confirmation(order_hash):
    order = ds.get(ds.key("cendr-order", int(order_hash)))
    order["items"] = {x.split(":")[0]:int(x.split(":")[1]) for x in order['items']}
    if order is None:
        abort(404)
    page_title = "Order Number: " + str(order['order-number'])
    return render_template('order_confirm.html', **locals())

<commit_msg>don't cache strain dataset<commit_after>from cendr import app, autoconvert, ds, db, cache
from cendr import json_serial
from flask import render_template, request, url_for, redirect, make_response, Response, abort
from cendr.models import strain
from collections import OrderedDict
import json
import os
import yaml
import stripe
try:
    from google.appengine.api import mail
except:
    pass # Importing this not always important...
from cendr.emails import order_submission
from gcloud.datastore.entity import Entity
from datetime import datetime
import pytz
from dateutil.relativedelta import relativedelta
#
# Global Strain Map
#

@app.route('/strain/global-strain-map/')
@cache.memoize(50)
def map_page():
    title = "Global Strain Map"
    bcs = OrderedDict([("Strain", url_for("strain_listing_page")), ("Global-Strain-Map", "")])
    strain_list_dicts = []
    strain_listing = list(strain.select().filter(strain.reference_strain == True)
        .filter(strain.latitude.is_null() == False).execute())
    strain_listing = json.dumps([x.__dict__["_data"] for x in strain_listing], default=json_serial)
    return render_template('map.html', **locals())

#
# Strain Data
#

@app.route('/strain/strain_data.tsv')
def strain_metadata():
    strain_listing = list(strain.select().filter(
        strain.isotype != None).tuples().execute())
    def generate():
        yield '\t'.join(strain._meta.sorted_field_names[1:21]) + "\n"
        for row in strain_listing:
            row = list(row)
            for k, f in enumerate(row):
                if type(f) == unicode:
                    row[k] = f.encode('ascii', 'ignore')
            yield '\t'.join(map(str, row[1:21])) + "\n"
    return Response(generate(), mimetype="text/tab-separated-values")

#
# Isotype View
#

@app.route('/strain/<isotype_name>/')
@cache.memoize(50)
def isotype_page(isotype_name):
    page_title = isotype_name
    page_type = "isotype"
    obj = isotype_name
    rec = list(strain.filter(strain.isotype == isotype_name)
                .order_by(strain.latitude).dicts().execute())
    ref_strain = [x for x in rec if x["reference_strain"] == True][0]
    strain_json_output = json.dumps([x for x in rec if x["latitude"] != None],  default=json_serial)
    return render_template('strain.html', **locals())

#
# Strain Catalog
#

@app.route('/strain/')
@cache.memoize(50)
def strain_listing_page():
    bcs = OrderedDict([("Strain", None)])
    title = "Strain Catalog"

    if 'warning' in request.args:
        warning = request.args["warning"]

    strain_listing = strain.select(strain.strain,
                                   strain.reference_strain,
                                   strain.isotype,
                                   strain.previous_names,
                                   strain.set_1,
                                   strain.set_2,
                                   strain.set_3,
                                   strain.set_4,
                                   strain.set_divergent).filter(strain.isotype != None).order_by(strain.isotype).execute()
    return render_template('strain_catalog.html', **locals())

#
# Strain Submission
#

@app.route('/strain/submit/')
def strain_submission_page():
    bcs = OrderedDict([("Strain", url_for("strain_listing_page")), ("Strain Submission", "")])
    title = "Strain Submission"
    return render_template('strain_submission.html', **locals())

#
# Protocols
#

@app.route("/strain/protocols/")
@cache.cached(timeout=50)
def protocols():
    title = "Protocols"
    bcs = OrderedDict([("Strain", url_for("strain_listing_page")), ("Protocols", "")])
    protocols = yaml.load(open("cendr/static/content/data/protocols.yaml", 'r'))
    return render_template('protocols.html', **locals())

#
# Strain Ordering Pages
#

def calculate_total(item_list):
    item_price_list = {}
    for i in item_list:
        if i == "set_divergent":
            item_price_list[i] = 10000
        elif i.startswith("set"):
            item_price_list[i] = 40000
        else:
            item_price_list[i] = 1000
    return item_price_list

@app.route('/order', methods=['GET','POST'])
def order_page():
    bcs = OrderedDict([("Strain", "/strain/"), ("Order", "")])
    title = "Order"
    strain_listing = list(set(request.form.getlist('item')))
    if (len(strain_listing) == 0):
        return redirect(url_for("strain_listing_page"))
    items = request.form.getlist("item")
    # Retreive SKU's for prices
    items = calculate_total(items)
    total = sum(items.values())
    field_list = ['name', 'phone', 'email', 'shipping-account', 'address']
    print(request.form)
    if 'shipping-service' in request.form:
        # Check that all pieces are filled out.
        missing_fields = []
        for i in field_list:
            if i in request.form:
                if not request.form[i]:
                    missing_fields.append(i)
                    warning = "Missing Some Fields"
        if len(missing_fields) == 0:
            o = ds.get(ds.key("cendr-order", "count"))
            o["order-number"] += 1
            order = Entity(ds.key('cendr-order'))
            for k in field_list:
                order[k] = request.form[k]
            order["items"] = [u"{k}:{v}".format(k=k, v=v) for k,v in items.items()]
            order["total"] = total
            order['submitted'] = datetime.now(pytz.timezone("America/Chicago"))
            order['order-number'] = o['order-number']
            order['shipping-service'] = request.form['shipping-service']
            with ds.transaction():
                ds.put(o)
                ds.put(order)
            order_hash = order.key.id
            mail.send_mail(sender="CeNDR <andersen-lab@appspot.gserviceaccount.com>",
               to=order["email"],
               subject="CeNDR Order #" + str(order["order-number"]),
               body=order_submission.format(order_hash=order_hash))
            return redirect(url_for("order_confirmation", order_hash=order_hash), code=302)

    return render_template('order.html', **locals())

@app.route("/order/<order_hash>/")
def order_confirmation(order_hash):
    order = ds.get(ds.key("cendr-order", int(order_hash)))
    order["items"] = {x.split(":")[0]:int(x.split(":")[1]) for x in order['items']}
    if order is None:
        abort(404)
    page_title = "Order Number: " + str(order['order-number'])
    return render_template('order_confirm.html', **locals())

<|endoftext|>


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

AUTHOR = u'jchen'
SITENAME = u'BURRITO 4 LYFE'
SITEURL = ''

TIMEZONE = 'ETC/UTC'

DEFAULT_LANG = u'en'

CSS_FILE = 'style.css'

# theme stuff
THEME = './theme'

# plugins
PLUGIN_PATH = './plugins'
PLUGINS = ['gravatar']

# gravatar email
AUTHOR_EMAIL = 'dabestmayne@burrito.sh'

# social
TWITTER_USERNAME = 's_jchen'

# Feed generation is usually not desired when developing
FEED_ALL_ATOM = None
CATEGORY_FEED_ATOM = None
TRANSLATION_FEED_ATOM = None

DEFAULT_PAGINATION = 10

DISPLAY_CATEGORIES_ON_MENU = False
DISPLAY_MENUITEMS_ON_MENU = False
DISPLAY_NAVBAR = False
DISPLAY_PAGES_ON_MENU = False

# Uncomment following line if you want document-relative URLs when developing
#RELATIVE_URLS = True
<commit_msg>update pelicanconf.py<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*- #
from __future__ import unicode_literals

AUTHOR = u'jchen'
SITENAME = u'BURRITO 4 LYFE'
SITEURL = ''

TIMEZONE = 'ETC/UTC'

DEFAULT_LANG = u'en'

CSS_FILE = 'style.css'

# theme stuff
THEME = './theme'

# plugins
PLUGIN_PATH = './plugins'
PLUGINS = ['gravatar']

# gravatar email
AUTHOR_EMAIL = 'dabestmayne@burrito.sh'

# social
TWITTER_USERNAME = 's_jchen'

# Feed generation is usually not desired when developing
FEED_ALL_ATOM = None
CATEGORY_FEED_ATOM = None
TRANSLATION_FEED_ATOM = None

DEFAULT_PAGINATION = 10

DISPLAY_CATEGORIES_ON_MENU = False
DISPLAY_MENUITEMS_ON_MENU = False
DISPLAY_NAVBAR = False
DISPLAY_PAGES_ON_MENU = False

DEFAULT_DATE_FORMAT('%Y-%m-%d')

# Uncomment following line if you want document-relative URLs when developing
#RELATIVE_URLS = True

<|endoftext|>


<commit_before>import RPi.GPIO as GPIO
from lib_nrf24 import NRF24
import time
import spidev
from random import randint
import pygame
import os

# get current working directory
curDir= os.getcwd() +"/"

# Change these to change the game
pause = 10 # how long to wait for a button to be pressed
numberOfNodes =2 # number of buttons
sayNumbers = 0
gamelen = 5 # number of button presses in a game

ready = "readysteadygoeffect.ogg"
countdown = ["one.ogg", "two.ogg", "three.ogg", "four.ogg", "five.ogg", "six.ogg", "seven.ogg", "eight.ogg", "nine.ogg", "ten.ogg"]

pygame.init()
pygame.font.init()
pygame.mixer.init()
pygame.mixer.get_init

window = pygame.display.set_mode((600, 400),)
pygame.display.set_caption("Button Flash")

# print(pygame.font.get_fonts())

#textfont = pygame.font.SysFont("moonspace",100)
textfont = pygame.font.SysFont("videophreak",75)
window.fill((255,255,255))
pygame.display.update()

# print("playing sound")
soundPlay = pygame.mixer.Sound(curDir+"readysteadygoeffect.ogg")
soundPlay.set_volume(1)
# soundPlay.play()

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)

pipes = [[0xE8, 0xE8, 0xF0, 0xF0, 0xE1], [0xF0, 0xF0, 0xF0, 0xF0, 0xE1]]

nodes = ["1P", "2P", "3P", "4P", "5P", "6P", "7P", "8P", "9P", "10P"]
radio = NRF24(GPIO, spidev.SpiDev())
radio.begin (0, 17)  # CE0 value 0 is GPIO 8  CE Value - GPIO 17

radio.setPayloadSize(32)
radio.setChannel(0x76)
radio.setDataRate(NRF24.BR_1MBPS)
radio.setPALevel(NRF24.PA_MAX)

radio.setAutoAck(True)
radio.enableDynamicPayloads()
radio.enableAckPayload()

radio.openWritingPipe(pipes[0])
radio.openReadingPipe(1,pipes[1])
radio.printDetails()
#radio.startListening()
time.sleep(1)

# message = list("3P")
# while len(message) <32:
#     message.append(0)

nodeNumber = 0 # which node to turn on
do = 0 # wait for a button to be pressed to decided if test or play
play = 0 # actually play the game (either test or game)
gamestartime = 0 # start of game in seconds
gameendtime = 0 # end of game in seconds
highscore = 0.0
score = 0.0

while True:
    pygame.event.clear

    highscoretext = textfont.render("High Score: ", 1, (255,0,0))
    highscoreresult = textfont.render(str(highscore), 1, (255,0,0))
    scoretext = textfont.render("Your Score: ", 1, (0,0,0))
    scoreresult = textfont.render(str(score), 1, (0,0,0))

    window.fill((255,255,255))
    window.blit(highscoretext, (20,10))
    window.blit(highscoreresult, (20,90))

    window.blit(scoretext, (20,200))
    window.blit(scoreresult, (20,280))
    pygame.display.update()

    print ("t for test \n\r[return] to play\n\r")
    while  (do == 0):
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_t:
                    do = 1
                    play = 2
                    steps = 1
                    print("Test Mode")
                    message = list("TEST")
                    soundPlay = pygame.mixer.Sound(curDir+"testmode.ogg")
                    soundPlay.play()

                if event.key == pygame.K_p:
                    print("Say Numbers")
                    sayNumbers = 1
                if event.key == pygame.K_s:
                    print("Do Not Say Number")
                    sayNumbers = 0

                if event.key == pygame.K_RETURN:
                    do = 1
                    play = 1
                    steps = gamelen
                    print("Starting Game")
                    soundPlay = pygame.mixer.Sound(curDir+"readysteadygoeffect.ogg")
                    soundPlay.play()
                    time.sleep(5)

    pygame.event.clear
    gamestartime = time.time()
    print ("gamestarttime is "+str(gamestartime))
    if play == 1:
        playtext = textfont.render("PLAY!", 1, (0,0,192))
    else:
        playtext = textfont.render("TEST!", 1, (0,0,192))

    window.fill((255,255,255))
    window.blit(playtext, (200,150))
    pygame.display.update()

    for x in range(0,steps):
        print("Round "+str(x+1))

        if play == 1:
            newnodeNumber=randint(0,numberOfNodes-1)
            while (newnodeNumber == nodeNumber):
                newnodeNumber=randint(0,numberOfNodes-1)
                print("boo picked the same one again nodenumber"+str(nodeNumber)+" | newnodenumber "+str(newnodeNumber)+"\n\r")
            nodeNumber = newnodeNumber
            message = list(nodes[nodeNumber])
            if sayNumbers == 1:
                soundPlay = pygame.mixer.Sound(curDir+countdown[nodeNumber])
                soundPlay.play()

        print(message)
        while len(message) <32:
            message.append(0)

        start = time.time()
        radio.write(message)
        print("sent the message: {}".format(message))
        radio.startListening()

        while not radio.available(0):
            time.sleep(1/100)
            if time.time() - start > pause:
                print("Timed out.")
                break

        receivedMessage = []
        radio.read(receivedMessage, radio.getDynamicPayloadSize())
        print ("Received: {}".format(receivedMessage))

        print("Translating our received message into unicode characters...")
        string = ""

        for n in receivedMessage:
            if (n >=32 and n <= 126):
                string += chr(n)
        print("Our received message decodes to: {}".format(string))

        radio.stopListening()
        time.sleep(0.5)
        if (do == 2):
            time.sleep(3)

        if play == 1:
            playtext = textfont.render("PLAY ! " + str(x+1), 1, (0,0,192))
        else:
            playtext = textfont.render("TEST !", 1, (0,0,192))

        window.fill((255,255,255))
        window.blit(playtext, (150,150))
        pygame.display.update()

    gameendtime = time.time()
    print ("raw score: " + str(gameendtime-gamestartime))
    score = (int((gameendtime-gamestartime)*10)/10)+0.0

    print ("\r\nYour score is: "+ str(score)+"\r\n")
    if play ==1:
        soundPlay = pygame.mixer.Sound("/home/pi/buttonFlash/gameover.ogg")
        soundPlay.play()
        time.sleep(2)
        if score < highscore or highscore == 0:
            soundPlay = pygame.mixer.Sound("/home/pi/buttonFlash/newhighscore.ogg")
            soundPlay.play()
            time.sleep(2)
            highscore = score

        highscoretext = textfont.render("High Score: ", 1, (255,0,0))
        highscoreresult = textfont.render(str(highscore), 1, (255,0,0))
        scoretext = textfont.render("Your Score: ", 1, (0,0,0))
        scoreresult = textfont.render(str(score), 1, (0,0,0))

        window.fill((255,255,255))
        window.blit(highscoretext, (20,10))
        window.blit(highscoreresult, (20,90))

        window.blit(scoretext, (20,200))
        window.blit(scoreresult, (20,280))
        pygame.display.update()
    else:
        score = 0

    do = 0
    play = 0

<commit_msg>fixed some minor niggles.<commit_after>import RPi.GPIO as GPIO
from lib_nrf24 import NRF24
import time
import spidev
from random import randint
import pygame
import os

# get current working directory
curDir= os.getcwd() +"/"

# Change these to change the game
pause = 10 # how long to wait for a button to be pressed
numberOfNodes =2 # number of buttons
sayNumbers = 0
gamelen = 20 # number of button presses in a game

ready = "readysteadygoeffect.ogg"
countdown = ["one.ogg", "two.ogg", "three.ogg", "four.ogg", "five.ogg", "six.ogg", "seven.ogg", "eight.ogg", "nine.ogg", "ten.ogg"]

pygame.init()
pygame.font.init()
pygame.mixer.init()
pygame.mixer.get_init

window = pygame.display.set_mode((600, 400),)
pygame.display.set_caption("Button Flash")

# print(pygame.font.get_fonts())

#textfont = pygame.font.SysFont("moonspace",100)
textfont = pygame.font.SysFont("videophreak",75)
window.fill((255,255,255))
pygame.display.update()

# print("playing sound")
soundPlay = pygame.mixer.Sound(curDir+"readysteadygoeffect.ogg")
soundPlay.set_volume(1)
# soundPlay.play()

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)

pipes = [[0xE8, 0xE8, 0xF0, 0xF0, 0xE1], [0xF0, 0xF0, 0xF0, 0xF0, 0xE1]]

nodes = ["1P", "2P", "3P", "4P", "5P", "6P", "7P", "8P", "9P", "10P"]
radio = NRF24(GPIO, spidev.SpiDev())
radio.begin (0, 17)  # CE0 value 0 is GPIO 8  CE Value - GPIO 17

radio.setPayloadSize(32)
radio.setChannel(0x76)
radio.setDataRate(NRF24.BR_1MBPS)
radio.setPALevel(NRF24.PA_MAX)

radio.setAutoAck(True)
radio.enableDynamicPayloads()
radio.enableAckPayload()

radio.openWritingPipe(pipes[0])
radio.openReadingPipe(1,pipes[1])
radio.printDetails()
#radio.startListening()
time.sleep(1)

# message = list("3P")
# while len(message) <32:
#     message.append(0)

nodeNumber = 0 # which node to turn on
do = 0 # wait for a button to be pressed to decided if test or play
play = 0 # actually play the game (either test or game)
gamestartime = 0 # start of game in seconds
gameendtime = 0 # end of game in seconds
highscore = 0.0
score = 0.0

while True:
    pygame.event.clear

    highscoretext = textfont.render("High Score: ", 1, (255,0,0))
    highscoreresult = textfont.render(str(highscore), 1, (255,0,0))
    scoretext = textfont.render("Your Score: ", 1, (0,0,0))
    scoreresult = textfont.render(str(score), 1, (0,0,0))

    window.fill((255,255,255))
    window.blit(highscoretext, (20,10))
    window.blit(highscoreresult, (20,90))

    window.blit(scoretext, (20,200))
    window.blit(scoreresult, (20,280))
    pygame.display.update()

    print ("t for test \n\r[return] to play\n\r")
    while  (do == 0):
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_t:
                    do = 1
                    play = 2
                    steps = 1
                    print("Test Mode")
                    message = list("TEST")
                    soundPlay = pygame.mixer.Sound(curDir+"testmode.ogg")
                    soundPlay.play()

                if event.key == pygame.K_p:
                    print("Say Numbers")
                    sayNumbers = 1
                if event.key == pygame.K_s:
                    print("Do Not Say Number")
                    sayNumbers = 0

                if event.key == pygame.K_RETURN:
                    do = 1
                    play = 1
                    steps = gamelen
                    print("Starting Game")
                    soundPlay = pygame.mixer.Sound(curDir+"readysteadygoeffect.ogg")
                    soundPlay.play()
                    time.sleep(5)

    pygame.event.clear
    gamestartime = time.time()
    print ("gamestarttime is "+str(gamestartime))
    if play == 1:
        playtext = textfont.render("PLAY !", 1, (0,0,192))
    else:
        playtext = textfont.render("TEST !", 1, (0,0,192))

    window.fill((255,255,255))
    window.blit(playtext, (200,150))
    pygame.display.update()

    for x in range(0,steps):
        print("Round "+str(x+1))

        if play == 1:
            newnodeNumber=randint(0,numberOfNodes-1)
            while (newnodeNumber == nodeNumber):
                newnodeNumber=randint(0,numberOfNodes-1)
                print("boo picked the same one again nodenumber"+str(nodeNumber)+" | newnodenumber "+str(newnodeNumber)+"\n\r")
            nodeNumber = newnodeNumber
            message = list(nodes[nodeNumber])
            if sayNumbers == 1:
                soundPlay = pygame.mixer.Sound(curDir+countdown[nodeNumber])
                soundPlay.play()

        print(message)
        while len(message) <32:
            message.append(0)

        start = time.time()
        radio.write(message)
        print("sent the message: {}".format(message))
        radio.startListening()

        while not radio.available(0):
            time.sleep(1/100)
            if time.time() - start > pause:
                print("Timed out.")
                break

        receivedMessage = []
        radio.read(receivedMessage, radio.getDynamicPayloadSize())
        print ("Received: {}".format(receivedMessage))

        print("Translating our received message into unicode characters...")
        string = ""

        for n in receivedMessage:
            if (n >=32 and n <= 126):
                string += chr(n)
        print("Our received message decodes to: {}".format(string))

        radio.stopListening()
        time.sleep(0.5)
        if (do == 2):
            time.sleep(3)

        if play == 1:
            playtext = textfont.render("PLAY ! " + str(x+1), 1, (0,0,192))
        else:
            playtext = textfont.render("TEST !", 1, (0,0,192))

        window.fill((255,255,255))
        window.blit(playtext, (150,150))
        pygame.display.update()

    gameendtime = time.time()
    print ("raw score: " + str(gameendtime-gamestartime))
    score = (int((gameendtime-gamestartime)*100)/100)+0.0

    print ("\r\nYour score is: "+ str(score)+"\r\n")
    if play ==1:
        soundPlay = pygame.mixer.Sound("/home/pi/buttonFlash/gameover.ogg")
        soundPlay.play()
        time.sleep(2)
        if score < highscore or highscore == 0:
            soundPlay = pygame.mixer.Sound("/home/pi/buttonFlash/newhighscore.ogg")
            soundPlay.play()
            time.sleep(2)
            highscore = score

        highscoretext = textfont.render("High Score: ", 1, (255,0,0))
        highscoreresult = textfont.render(str(highscore), 1, (255,0,0))
        scoretext = textfont.render("Your Score: ", 1, (0,0,0))
        scoreresult = textfont.render(str(score), 1, (0,0,0))

        window.fill((255,255,255))
        window.blit(highscoretext, (20,10))
        window.blit(highscoreresult, (20,90))

        window.blit(scoretext, (20,200))
        window.blit(scoreresult, (20,280))
        pygame.display.update()
    else:
        score = 0

    do = 0
    play = 0

<|endoftext|>


<commit_before>'''
# Gabe Gaster, 2013
#
#   about every minute, eta will report how many iterations
#   have been performed and the Expected Time to Completion (the E.T.C.)
#
#####################################################################
#
# Examples:
#

import timer

for stuff in timer.show_progress(range(100)):
    # .... analysis here
    timer.sleep(.5)

# prints (to standard error) :
  # 0.1 min elapsed, 25.0 % done, ETA:   0.3 min
  # 0.1 min elapsed, 45.0 % done, ETA:   0.3 min
  # 0.2 min elapsed, 65.0 % done, ETA:   0.3 min
  # 0.3 min elapsed, 85.0 % done, ETA:   0.3 min

'''

import time
import sys

def get_time_str(num_secs):
    minutes = num_secs * 1. / 60
    hours = minutes / 60
    days = hours / 24
    if num_secs < 60:
        if num_secs < .001:
            return "%5.3f microsec" % num_secs*10**6
        elif .001 < num_secs < 1:
            return "%5.3f millisec" % num_secs*10**3
        else:
            return "%5.1f sec" % num_secs
    if minutes < 60:
        return "%5.1f min" % minutes
    elif hours < 24:
        return "%5.1f hours" % hours
    else:
        return "%5.1f days" % days

def show_progress(iterable, update_time=60, length=None):
    """Wraps any iterable and passes values right through. Every
    update_time's worth of seconds (defaulting to 60 seconds), print a
    report on total time elapsed, percent done and estimated total
    time of completion.

    If length is not specified, look to the length of iterable (if
    it's defined in __len__).

    If there is no length, then report number (instead of percent)
    done, and report time per iteration (instead of ETA).

    """
    name, length = get_name_length(iterable, length)

    start = last_update = time.time()
    # if the length is unknown, don't estimate completion time, but
    # still show periodic progress updates.

    for count, thing in enumerate(iterable):
        now = time.time()
        if now - last_update > update_time:
            last_update = now
            msg = get_msg(count, length, now, start)
            print >> sys.stderr, "%s : %s" % (name, msg)
        yield thing

    time_string = get_time_str(time.time() - start)
    print >> sys.stderr, "%s : DONE in %s" % (name, time_string)

def get_name_length(iterable, length):
    try:
        name = iterable.__name__
    except AttributeError:
        name = ""  # iterable.__repr__()
    if not hasattr(iterable, "__iter__"):
        raise TypeError("Object %s not iterable" % name)
    if hasattr(iterable, "__len__") and length is None:
        length = iterable.__len__()
    return name, length

def get_msg(count, length, now, start):
    time_elapsed = now - start
    if length:
        percent_done = 1. * count / length
        if percent_done:
            etc_secs = time_elapsed / percent_done
            etc_time = get_time_str(etc_secs)
        else:
            etc_time = "NA"
        msg = "%s elapsed, %5.3f%% done, ETC: %s"
        msg = msg % (get_time_str(time_elapsed),
                     percent_done * 100,
                     etc_time)
    else:
        msg = "%s elapsed, %s done : %s per iter"
        msg = msg % (get_time_str(time_elapsed),
                     count,
                     get_time_str(time_elapsed / count))
    return msg
<commit_msg>change second if statement to elif.<commit_after>'''
# Gabe Gaster, 2013
#
#   about every minute, eta will report how many iterations
#   have been performed and the Expected Time to Completion (the E.T.C.)
#
#####################################################################
#
# Examples:
#

import timer

for stuff in timer.show_progress(range(100)):
    # .... analysis here
    timer.sleep(.5)

# prints (to standard error) :
  # 0.1 min elapsed, 25.0 % done, ETA:   0.3 min
  # 0.1 min elapsed, 45.0 % done, ETA:   0.3 min
  # 0.2 min elapsed, 65.0 % done, ETA:   0.3 min
  # 0.3 min elapsed, 85.0 % done, ETA:   0.3 min

'''

import time
import sys

def get_time_str(num_secs):
    minutes = num_secs * 1. / 60
    hours = minutes / 60
    days = hours / 24
    if num_secs < 60:
        if num_secs < .001:
            return "%5.3f microsec" % num_secs*10**6
        elif .001 < num_secs < 1:
            return "%5.3f millisec" % num_secs*10**3
        else:
            return "%5.1f sec" % num_secs
    if minutes < 60:
        return "%5.1f min" % minutes
    elif hours < 24:
        return "%5.1f hours" % hours
    else:
        return "%5.1f days" % days

def show_progress(iterable, update_time=60, length=None):
    """Wraps any iterable and passes values right through. Every
    update_time's worth of seconds (defaulting to 60 seconds), print a
    report on total time elapsed, percent done and estimated total
    time of completion.

    If length is not specified, look to the length of iterable (if
    it's defined in __len__).

    If there is no length, then report number (instead of percent)
    done, and report time per iteration (instead of ETA).

    """
    name, length = get_name_length(iterable, length)

    start = last_update = time.time()
    # if the length is unknown, don't estimate completion time, but
    # still show periodic progress updates.

    for count, thing in enumerate(iterable):
        now = time.time()
        if now - last_update > update_time:
            last_update = now
            msg = get_msg(count, length, now, start)
            print >> sys.stderr, "%s : %s" % (name, msg)
        yield thing

    time_string = get_time_str(time.time() - start)
    print >> sys.stderr, "%s : DONE in %s" % (name, time_string)

def get_name_length(iterable, length):
    try:
        name = iterable.__name__
    except AttributeError:
        name = ""  # iterable.__repr__()
    if not hasattr(iterable, "__iter__"):
        raise TypeError("Object %s not iterable" % name)
    elif length is None:
        length = iterable.__len__()
    return name, length

def get_msg(count, length, now, start):
    time_elapsed = now - start
    if length:
        percent_done = 1. * count / length
        if percent_done:
            etc_secs = time_elapsed / percent_done
            etc_time = get_time_str(etc_secs)
        else:
            etc_time = "NA"
        msg = "%s elapsed, %5.3f%% done, ETC: %s"
        msg = msg % (get_time_str(time_elapsed),
                     percent_done * 100,
                     etc_time)
    else:
        msg = "%s elapsed, %s done : %s per iter"
        msg = msg % (get_time_str(time_elapsed),
                     count,
                     get_time_str(time_elapsed / count))
    return msg
<|endoftext|>