<commit_before>#
# Copyright (c) 2016 NORDUnet A/S
# All rights reserved.
#
#   Redistribution and use in source and binary forms, with or
#   without modification, are permitted provided that the following
#   conditions are met:
#
#     1. Redistributions of source code must retain the above copyright
#        notice, this list of conditions and the following disclaimer.
#     2. Redistributions in binary form must reproduce the above
#        copyright notice, this list of conditions and the following
#        disclaimer in the documentation and/or other materials provided
#        with the distribution.
#     3. Neither the name of the NORDUnet nor the names of its
#        contributors may be used to endorse or promote products derived
#        from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
"""
Define a `eduid_init_app` function to create a Flask app and update
it with all attributes common to all eduID services.
"""

from werkzeug.contrib.fixers import ProxyFix

from eduid_userdb import UserDB
from eduid_common.authn.middleware import AuthnApp
from eduid_common.api.request import Request
from eduid_common.api.session import SessionFactory
from eduid_common.api.logging import init_logging
from eduid_common.api.utils import init_template_functions
from eduid_common.api.exceptions import init_exception_handlers, init_sentry
from eduid_common.api.middleware import PrefixMiddleware
from eduid_common.config.parsers.etcd import EtcdConfigParser
from eduid_common.stats import NoOpStats, Statsd

def eduid_init_app_no_db(name, config, app_class=AuthnApp):
    """
    Create and prepare the flask app for eduID APIs with all the attributes
    common to all  apps.

     * Parse and merge configurations
     * Add logging
     * Add db connection
     * Add eduID session

    :param name: The name of the instance, it will affect the configuration file
                 loaded from the filesystem.
    :type name: str
    :param config: any additional configuration settings. Specially useful
                   in test cases
    :type config: dict
    :param app_class: The class used to build the flask app. Should be a
                      descendant of flask.Flask
    :type app_class: type

    :return: the flask application.
    :rtype: flask.Flask
    """
    app = app_class(name)
    app.wsgi_app = ProxyFix(app.wsgi_app)
    app.request_class = Request
    app.url_map.strict_slashes = False

    # Init etcd config parsers
    common_parser = EtcdConfigParser('/eduid/webapp/common/')
    app_parser = EtcdConfigParser('/eduid/webapp/{!s}/'.format(name))

    # Load project wide default settings
    app.config.from_object('eduid_webapp.settings.common')

    try:
        # Load optional app specific default settings
        app.config.from_object('eduid_webapp.{!s}.settings.common'.format(name))
    except ImportError:  # No app specific default config found
        pass

    # Load optional project wide settings
    app.config.update(common_parser.read_configuration(silent=True))
    # Load optional app specific settings
    app.config.update(app_parser.read_configuration(silent=True))

    # Load optional app specific secrets
    app.config.from_envvar('SECRETS_FILE', silent=True)

    # Load optional init time settings
    app.config.update(config)

    # Set app url prefix to APPLICATION_ROOT
    app.wsgi_app = PrefixMiddleware(app.wsgi_app, prefix=app.config['APPLICATION_ROOT'])

    # Initialize shared features
    app = init_logging(app)
    app = init_exception_handlers(app)
    app = init_sentry(app)
    app = init_template_functions(app)
    app.session_interface = SessionFactory(app.config)

    stats_host = app.config.get('STATS_HOST', False)
    if not stats_host:
        app.stats = NoOpStats()
    else:
        stats_port = app.config.get('STATS_PORT', 8125)
        app.stats = Statsd(host=stats_host, port=stats_port, prefix=name)

    return app

def eduid_init_app(name, config, app_class=AuthnApp):
    app = eduid_init_app_no_db(name, config, app_class=app_class)
    app.central_userdb = UserDB(app.config['MONGO_URI'], 'eduid_am')  # XXX: Needs updating when we change db
    return app
<commit_msg>SECRETS_FILE -> LOCAL_CFG_FILE<commit_after>#
# Copyright (c) 2016 NORDUnet A/S
# All rights reserved.
#
#   Redistribution and use in source and binary forms, with or
#   without modification, are permitted provided that the following
#   conditions are met:
#
#     1. Redistributions of source code must retain the above copyright
#        notice, this list of conditions and the following disclaimer.
#     2. Redistributions in binary form must reproduce the above
#        copyright notice, this list of conditions and the following
#        disclaimer in the documentation and/or other materials provided
#        with the distribution.
#     3. Neither the name of the NORDUnet nor the names of its
#        contributors may be used to endorse or promote products derived
#        from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
"""
Define a `eduid_init_app` function to create a Flask app and update
it with all attributes common to all eduID services.
"""

from werkzeug.contrib.fixers import ProxyFix

from eduid_userdb import UserDB
from eduid_common.authn.middleware import AuthnApp
from eduid_common.api.request import Request
from eduid_common.api.session import SessionFactory
from eduid_common.api.logging import init_logging
from eduid_common.api.utils import init_template_functions
from eduid_common.api.exceptions import init_exception_handlers, init_sentry
from eduid_common.api.middleware import PrefixMiddleware
from eduid_common.config.parsers.etcd import EtcdConfigParser
from eduid_common.stats import NoOpStats, Statsd

def eduid_init_app_no_db(name, config, app_class=AuthnApp):
    """
    Create and prepare the flask app for eduID APIs with all the attributes
    common to all  apps.

     * Parse and merge configurations
     * Add logging
     * Add db connection
     * Add eduID session

    :param name: The name of the instance, it will affect the configuration file
                 loaded from the filesystem.
    :type name: str
    :param config: any additional configuration settings. Specially useful
                   in test cases
    :type config: dict
    :param app_class: The class used to build the flask app. Should be a
                      descendant of flask.Flask
    :type app_class: type

    :return: the flask application.
    :rtype: flask.Flask
    """
    app = app_class(name)
    app.wsgi_app = ProxyFix(app.wsgi_app)
    app.request_class = Request
    app.url_map.strict_slashes = False

    # Init etcd config parsers
    common_parser = EtcdConfigParser('/eduid/webapp/common/')
    app_parser = EtcdConfigParser('/eduid/webapp/{!s}/'.format(name))

    # Load project wide default settings
    app.config.from_object('eduid_webapp.settings.common')

    try:
        # Load optional app specific default settings
        app.config.from_object('eduid_webapp.{!s}.settings.common'.format(name))
    except ImportError:  # No app specific default config found
        pass

    # Load optional project wide settings
    app.config.update(common_parser.read_configuration(silent=True))
    # Load optional app specific settings
    app.config.update(app_parser.read_configuration(silent=True))

    # Load optional app specific secrets
    app.config.from_envvar('LOCAL_CFG_FILE', silent=True)

    # Load optional init time settings
    app.config.update(config)

    # Set app url prefix to APPLICATION_ROOT
    app.wsgi_app = PrefixMiddleware(app.wsgi_app, prefix=app.config['APPLICATION_ROOT'])

    # Initialize shared features
    app = init_logging(app)
    app = init_exception_handlers(app)
    app = init_sentry(app)
    app = init_template_functions(app)
    app.session_interface = SessionFactory(app.config)

    stats_host = app.config.get('STATS_HOST', False)
    if not stats_host:
        app.stats = NoOpStats()
    else:
        stats_port = app.config.get('STATS_PORT', 8125)
        app.stats = Statsd(host=stats_host, port=stats_port, prefix=name)

    return app

def eduid_init_app(name, config, app_class=AuthnApp):
    app = eduid_init_app_no_db(name, config, app_class=app_class)
    app.central_userdb = UserDB(app.config['MONGO_URI'], 'eduid_am')  # XXX: Needs updating when we change db
    return app
<|endoftext|>


<commit_before>import pytest

from indy_common.constants import NODE
from plenum.common.constants import BLS_KEY, BLS_KEY_PROOF, TXN_TYPE, \
    DATA
from plenum.common.exceptions import InvalidClientRequest
from plenum.common.request import Request
from plenum.test.pool_transactions.helper import prepare_new_node_data
from stp_core.types import Identifier

@pytest.fixture(scope="function")
def pool_req_handler(txnPoolNodeSet):
    return txnPoolNodeSet[0].poolManager.reqHandler

@pytest.fixture(scope="function")
def bls_keys(tconf, tdir):
    new_node_name = "NewNode"
    _, _, bls_key, _, _, _, _, key_proof = prepare_new_node_data(tconf,
                                                                 tdir,
                                                                 new_node_name)
    return bls_key, key_proof

def test_pool_req_handler_static_validation(bls_keys,
                                            pool_req_handler):
    bls_ver_key, key_proof = bls_keys
    node_request = _generate_node_request(bls_key=bls_ver_key,
                                          bls_key_proof=key_proof)
    pool_req_handler.doStaticValidation(node_request)

def test_pool_req_handler_static_validation_with_full_bls(bls_keys,
                                                          pool_req_handler):
    bls_ver_key, key_proof = bls_keys
    node_request = _generate_node_request(bls_key=None,
                                          bls_key_proof=key_proof)
    pool_req_handler.doStaticValidation(node_request)

def test_pool_req_handler_static_validation_with_incorrect_proof(bls_keys,
                                                                 pool_req_handler):
    bls_ver_key, key_proof = bls_keys
    node_request = _generate_node_request(bls_key=bls_ver_key,
                                          bls_key_proof=key_proof.upper())
    with pytest.raises(InvalidClientRequest) as e:
        pool_req_handler.doStaticValidation(node_request)
        assert "Proof of possession {} " \
               "is incorrect for BLS key {}".format(key_proof, bls_ver_key) \
               in e._excinfo[1].args[0]

def test_pool_req_handler_static_validation_with_full_proof(bls_keys,
                                                            pool_req_handler):
    bls_ver_key, key_proof = bls_keys
    node_request = _generate_node_request(bls_key=bls_ver_key,
                                          bls_key_proof=None)
    with pytest.raises(InvalidClientRequest) as e:
        pool_req_handler.doStaticValidation(node_request)
        assert "A Proof of possession must be provided with BLS key" \
               in e._excinfo[1].args[0]

def _generate_node_request(bls_key=None,
                           bls_key_proof=None) -> Request:
    op = {
        DATA: {
            BLS_KEY: bls_key,
            BLS_KEY_PROOF: bls_key_proof
        },
        TXN_TYPE: NODE
    }
    return Request(operation=op,
                   reqId=123,
                   identifier=Identifier("idr"))
<commit_msg>INDY-1389: fix test_pool_req_handler_static_validation imports<commit_after>import pytest

from plenum.common.constants import BLS_KEY, BLS_KEY_PROOF, TXN_TYPE, \
    DATA, NODE
from plenum.common.exceptions import InvalidClientRequest
from plenum.common.request import Request
from plenum.test.pool_transactions.helper import prepare_new_node_data
from stp_core.types import Identifier

@pytest.fixture(scope="function")
def pool_req_handler(txnPoolNodeSet):
    return txnPoolNodeSet[0].poolManager.reqHandler

@pytest.fixture(scope="function")
def bls_keys(tconf, tdir):
    new_node_name = "NewNode"
    _, _, bls_key, _, _, _, _, key_proof = prepare_new_node_data(tconf,
                                                                 tdir,
                                                                 new_node_name)
    return bls_key, key_proof

def test_pool_req_handler_static_validation(bls_keys,
                                            pool_req_handler):
    bls_ver_key, key_proof = bls_keys
    node_request = _generate_node_request(bls_key=bls_ver_key,
                                          bls_key_proof=key_proof)
    pool_req_handler.doStaticValidation(node_request)

def test_pool_req_handler_static_validation_with_full_bls(bls_keys,
                                                          pool_req_handler):
    bls_ver_key, key_proof = bls_keys
    node_request = _generate_node_request(bls_key=None,
                                          bls_key_proof=key_proof)
    pool_req_handler.doStaticValidation(node_request)

def test_pool_req_handler_static_validation_with_incorrect_proof(bls_keys,
                                                                 pool_req_handler):
    bls_ver_key, key_proof = bls_keys
    node_request = _generate_node_request(bls_key=bls_ver_key,
                                          bls_key_proof=key_proof.upper())
    with pytest.raises(InvalidClientRequest) as e:
        pool_req_handler.doStaticValidation(node_request)
        assert "Proof of possession {} " \
               "is incorrect for BLS key {}".format(key_proof, bls_ver_key) \
               in e._excinfo[1].args[0]

def test_pool_req_handler_static_validation_with_full_proof(bls_keys,
                                                            pool_req_handler):
    bls_ver_key, key_proof = bls_keys
    node_request = _generate_node_request(bls_key=bls_ver_key,
                                          bls_key_proof=None)
    with pytest.raises(InvalidClientRequest) as e:
        pool_req_handler.doStaticValidation(node_request)
        assert "A Proof of possession must be provided with BLS key" \
               in e._excinfo[1].args[0]

def _generate_node_request(bls_key=None,
                           bls_key_proof=None) -> Request:
    op = {
        DATA: {
            BLS_KEY: bls_key,
            BLS_KEY_PROOF: bls_key_proof
        },
        TXN_TYPE: NODE
    }
    return Request(operation=op,
                   reqId=123,
                   identifier=Identifier("idr"))
<|endoftext|>


<commit_before>"""
`plotly_express` is a terse, consistent, high-level wrapper around `plotly` for rapid \
data exploration and figure generation. See the gallery at https://plotly.github.io/plotly_express
"""

__version__ = "0.3.0"

from ._chart_types import (  # noqa: F401
    scatter,
    scatter_3d,
    scatter_polar,
    scatter_ternary,
    scatter_mapbox,
    scatter_geo,
    line,
    line_3d,
    line_polar,
    line_ternary,
    line_mapbox,
    line_geo,
    area,
    bar,
    bar_polar,
    violin,
    box,
    strip,
    histogram,
    scatter_matrix,
    parallel_coordinates,
    parallel_categories,
    choropleth,
    density_contour,
    density_heatmap,
)

from ._core import (  # noqa: F401
    set_mapbox_access_token,
    defaults,
    get_trendline_results,
)

from . import data, colors  # noqa: F401

__all__ = [
    "scatter",
    "scatter_3d",
    "scatter_polar",
    "scatter_ternary",
    "scatter_mapbox",
    "scatter_geo",
    "scatter_matrix",
    "density_contour",
    "density_heatmap",
    "line",
    "line_polar",
    "line_ternary",
    "line_mapbox",
    "line_geo",
    "parallel_coordinates",
    "parallel_categories",
    "area",
    "bar",
    "bar_polar",
    "violin",
    "box",
    "strip",
    "histogram",
    "choropleth",
    "data",
    "colors",
    "set_mapbox_access_token",
    "get_trendline_results",
]
<commit_msg>adds back in missing function name<commit_after>"""
`plotly_express` is a terse, consistent, high-level wrapper around `plotly` for rapid \
data exploration and figure generation. See the gallery at https://plotly.github.io/plotly_express
"""

__version__ = "0.3.0"

from ._chart_types import (  # noqa: F401
    scatter,
    scatter_3d,
    scatter_polar,
    scatter_ternary,
    scatter_mapbox,
    scatter_geo,
    line,
    line_3d,
    line_polar,
    line_ternary,
    line_mapbox,
    line_geo,
    area,
    bar,
    bar_polar,
    violin,
    box,
    strip,
    histogram,
    scatter_matrix,
    parallel_coordinates,
    parallel_categories,
    choropleth,
    density_contour,
    density_heatmap,
)

from ._core import (  # noqa: F401
    set_mapbox_access_token,
    defaults,
    get_trendline_results,
)

from . import data, colors  # noqa: F401

__all__ = [
    "scatter",
    "scatter_3d",
    "scatter_polar",
    "scatter_ternary",
    "scatter_mapbox",
    "scatter_geo",
    "scatter_matrix",
    "density_contour",
    "density_heatmap",
    "line",
    "line_3d",
    "line_polar",
    "line_ternary",
    "line_mapbox",
    "line_geo",
    "parallel_coordinates",
    "parallel_categories",
    "area",
    "bar",
    "bar_polar",
    "violin",
    "box",
    "strip",
    "histogram",
    "choropleth",
    "data",
    "colors",
    "set_mapbox_access_token",
    "get_trendline_results",
]
<|endoftext|>


<commit_before># encoding: utf-8

"""MongoDB filter, projection, and update operation helpers.

These encapsulate the functionality of creating combinable mappings
"""

from __future__ import unicode_literals

from itertools import chain
from copy import deepcopy
from collections import Mapping, MutableMapping
from marrow.schema import Container, Attribute
from marrow.schema.compat import odict

from ..util import SENTINEL
from ..util.compat import py3, unicode

if __debug__:
	_simple_safety_check = lambda s, o: (s.__allowed_operators__ and o not in s.__allowed_operators__) or o in s.__disallowed_operators__
	_complex_safety_check = lambda s, o: (s.__allowed_operators__ and not s.__allowed_operators__.intersection(o)) or s.__disallowed_operators__.intersection(o)

class Ops(Container):
	operations = Attribute(default=None)

	def __init__(self, *args, **kw):
		super(Ops, self).__init__(*args, **kw)

		if self.operations is None:
			self.operations = odict()

	def __repr__(self):
		return "{}({})".format(
				self.__class__.__name__,
				repr(list(self.items())).replace("(u'", "('").replace("', u'", "', '")
			)

	@property
	def as_query(self):
		return self.operations

	# Binary Operator Protocols

	def __and__(self, other):
		operations = deepcopy(self.operations)
		extra = {k: self.__data__[k] for k in self.__attributes__ if k != 'operations'}

		if isinstance(other, Op):
			other = self.__class__(operations=other.as_query)

		for k, v in getattr(other, 'operations', []).items():
			if k not in operations:
				operations[k] = v
			else:
				if not isinstance(operations[k], Mapping):
					operations[k] = odict((('$eq', operations[k]), ))

				if not isinstance(v, Mapping):
					v = odict((('$eq', v), ))

				operations[k].update(v)

		return self.__class__(operations=operations, **extra)

	def __or__(self, other):
		operations = deepcopy(self.operations)
		extra = {k: self.__data__[k] for k in self.__attributes__ if k != 'operations'}

		if isinstance(other, Op):
			other = self.__class__(operations=other.as_query, **extra)

		if len(operations) == 1 and '$or' in operations:
			# Update existing $or.
			operations['$or'].append(other)
			return self.__class__(operations=operations, **extra)

		return self.__class__(operations={'$or': [operations, other]})

	# Mapping Protocol

	def __getitem__(self, name):
		return self.operations[name]

	def __setitem__(self, name, value):
		self.operations[name] = value

	def __delitem__(self, name):
		del self.operations[name]

	def __iter__(self):
		return iter(self.operations.keys())

	def __len__(self):
		return len(self.operations)

	if py3:
		def keys(self):
			return self.operations.keys()

		def items(self):
			return self.operations.items()

		def values(self):
			return self.operations.values()

	else:
		def keys(self):
			return self.operations.iterkeys()

		def items(self):
			return self.operations.iteritems()

		def values(self):
			return self.operations.itervalues()

	def __contains__(self, key):
		return key in self.operations

	def __eq__(self, other):
		return self.operations == other

	def __ne__(self, other):
		return self.operations != other

	def get(self, key, default=None):
		return self.operations.get(key, default)

	def clear(self):
		self.operations.clear()

	def pop(self, name, default=SENTINEL):
		if default is SENTINEL:
			return self.operations.pop(name)

		return self.operations.pop(name, default)

	def popitem(self):
		return self.operations.popitem()

	def update(self, *args, **kw):
		self.operations.update(*args, **kw)

	def setdefault(self, key, value=None):
		return self.operations.setdefault(key, value)

MutableMapping.register(Ops)  # Metaclass conflict if we subclass.

class Op(Container):
	field = Attribute(default=None)
	operation = Attribute(default=None)
	value = Attribute(default=SENTINEL)

	def __repr__(self):
		return "Op({})".format(repr(self.as_query))

	def clone(self, **kw):
		arguments = dict(field=self.field, operation=self.operation, value=self.value)
		arguments.update(kw)
		return self.__class__(**arguments)

	# Logical Query Selectors
	# https://docs.mongodb.org/manual/reference/operator/query/#logical

	def __or__(self, other):
		return Op(None, 'or', [self, other])

	def __and__(self, other):
		if getattr(other, 'field', None) is None or self.field is None:
			return Op(None, 'and', [self, other])

		return Ops(odict(chain(self.as_query.items(), other.as_query.items())))

	def __invert__(self): # not
		return Op(None, 'not', self)

	@property
	def as_query(self):
		value = getattr(self.value, 'as_query', self.value)
		if value is SENTINEL:
			value = None

		if isinstance(value, list):
			value = [getattr(i, 'as_query', i) for i in value]

		if not self.operation or self.operation == 'eq':
			if not self.field:
				return value

			if self.value is SENTINEL:
				return {unicode(self.field): {'$exists': 1}}

			return {unicode(self.field): value}

		if not self.field:
			return {'$' + unicode(self.operation): value}

		return {unicode(self.field): {'$' + unicode(self.operation): value}}

class Queryable(object):
	"""A convienent mix-in which adds the ability to generate Op instances during comparison.

	Assumes the following are populated:

	 * `self.transformer.foreign` -- a function to convert Python values into MongoDB ones.
	 * `self.__str__` -- calling `str()` (or `unicode()` in Python 2) across `self` should return a field name.
	 * `self.__allowed_operators__` -- a set of allowed operators
	 * `self.__disallowed_operators__` -- a blacklist set of operators
	"""

	__allowed_operators__ = set()
	__disallowed_operators__ = set()

	# Comparison Query Selectors
	# Documentation: https://docs.mongodb.org/manual/reference/operator/query/#comparison

	def __eq__(self, other):
		"""Matches values that are equal to the specified value.

			Document.field == "hOI!"

		Comparison operator: {$eq: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/eq/#op._S_eq
		"""
		if __debug__ and _simple_safety_check(self, '$eq'):  # Optimize this away in production; diagnosic aide.
			raise NotImplementedError("{self.__class__.__name__} does not allow $eq comparison.".format(self=self))

		return Op(self, 'eq', self.transformer.foreign(other, self))

	def __gt__(self, other):
		"""Matches values that are greater than a specified value.

			Document.field > 65

		Comparison operator: {$gt: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/gt/#op._S_gt
		"""
		if __debug__ and _complex_safety_check(self, {'$gt', '#rel'}):  # Optimize this away in production.
			raise NotImplementedError("{self.__class__.__name__} does not allow $gt comparison.".format(self=self))

		return Op(self, 'gt', self.transformer.foreign(other, self))

	def __ge__(self, other):
		"""Matches values that are greater than or equal to a specified value.

			Document.field >= 21

		Comparison operator: {$gte: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/gte/#op._S_gte
		"""
		if __debug__ and _complex_safety_check(self, {'$gte', '#rel'}):  # Optimize this away in production.
			raise NotImplementedError("{self.__class__.__name__} does not allow $gte comparison.".format(self=self))

		return Op(self, 'gte', self.transformer.foreign(other, self))

	def __lt__(self, other):
		"""Matches values that are less than or equal to a specified value.

			Document.field < 18

		Comparison operator: {$lt: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/lt/#op._S_lt
		"""
		if __debug__ and _complex_safety_check(self, {'$lt', '#rel'}):  # Optimize this away in production.
			raise NotImplementedError("{self.__class__.__name__} does not allow $lt comparison.".format(self=self))

		return Op(self, 'lt', self.transformer.foreign(other, self))

	def __le__(self, other):
		"""Matches values that are less than or equal to a specified value.

			Document.field <= 27

		Comparison operator: {$lte: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/lte/#op._S_lte
		"""
		if __debug__ and _complex_safety_check(self, {'$lte', '#rel'}):  # Optimize this away in production.
			raise NotImplementedError("{self.__class__.__name__} does not allow $lte comparison.".format(self=self))

		return Op(self, 'lte', self.transformer.foreign(other, self))

	def __ne__(self, other):
		"""Matches all values that are not equal to a specified value.

			Document.field != 42

		Comparison operator: {$ne: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/ne/#op._S_ne
		"""
		if __debug__ and _complex_safety_check(self, {'$ne', '$eq'}):  # Optimize this away in production.
			raise NotImplementedError("{self.__class__.__name__} does not allow $ne comparison.".format(self=self))

		return Op(self, 'ne', self.transformer.foreign(other, self))

	def any(self, *args):
		"""Matches any of the values specified in an array.

			Document.field.any([1, 2, 3, 5, 8, 13])

		Individual elements may be passed positionally instead, for convienence.

		Comparison operator: {$in: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/in/#op._S_in
		"""
		if __debug__ and _complex_safety_check(self, {'$in', '$eq'}):  # Optimize this away in production.
			raise NotImplementedError("{self.__class__.__name__} does not allow $in comparison.".format(self=self))

		other = args if len(args) > 1 else args[0]

		return Op(self, 'in', [self.transformer.foreign(value, self) for i, value in enumerate(other)])

	def none(self, other):
		"""Matches none of the values specified in an array.

			Document.field.none([2, 3, 5, 7, 11, 13, 17 19, 23, 29])

		Comparison operator: {$nin: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/nin/#op._S_nin
		"""
		return Op(self, 'nin', [self.transformer.foreign(value, self) for i, value in enumerate(other)])

	# Logical Query Selectors
	# https://docs.mongodb.org/manual/reference/operator/query/#logical

	def __or__(self, other):
		raise NotImplementedError()

	def __and__(self, other):
		raise NotImplementedError()

	def __invert__(self):
		raise NotImplementedError()

	# Array Query Selectors
	# https://docs.mongodb.org/manual/reference/operator/query/#array

	def all(self, other):
		"""Matches arrays that contain all elements specified in the query.

			Document.field.all(['hocuspocus', 'xyzzy', 'abracadabra'])

		Array operator: {$all: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/all/#op._S_all
		"""
		if __debug__ and _complex_safety_check(self, {'$all', '#array'}):  # Optimize this away in production.
			raise NotImplementedError("{self.__class__.__name__} does not allow $all comparison.".format(self=self))

		return Op(self, 'all', [self.transformer.foreign(value, self) for i, value in enumerate(other)])

	def match(self, q):
		"""Selects documents if element in the array field matches all the specified conditions.

			Document.field.match(...)

		Array operator: {$elemMatch: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/elemMatch/#op._S_elemMatch
		"""
		if __debug__ and _complex_safety_check(self, {'$elemMatch', '#document'}):  # Optimize this away in production.
			raise NotImplementedError("{self.__class__.__name__} does not allow $elemMatch comparison.".format(self=self))

		if hasattr(q, 'as_query'):
			q = q.as_query

		return Op(self, 'elemMatch', q)

	def range(self, gte, lt):
		"""Matches values that are between a minimum and maximum value, semi-inclusive.

			Document.field.range(4, 12)

		This will find documents with a field whose value is greater than or equal to 4, and less than 12.

		Comparison operator: {$gte: gte, $lt: lt}
		"""
		if __debug__ and _simple_safety_check(self, '#range'):  # Optimize this away in production; diagnosic aide.
			raise NotImplementedError("{self.__class__.__name__} does not allow range comparison.".format(self=self))

		return Ops((self >= gte).as_query) & Ops((self < lt).as_query)

	def size(self, value):
		"""Selects documents if the array field is a specified size.

			Document.field.size(5)

		Array operator: {$size: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/size/#op._S_size
		"""
		if __debug__ and _complex_safety_check(self, {'$size', '#array'}):  # Optimize this away in production.
			raise NotImplementedError("{self.__class__.__name__} does not allow $size comparison.".format(self=self))

		return Op(self, 'size', int(value))

	# Element Query Selectors
	# https://docs.mongodb.org/manual/reference/operator/query/#element

	def __neg__(self):
		"""Matches documents that don't have the specified field.

			-Document.field

		Element operator: {$exists: false}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/exists/#op._S_exists
		"""
		return Op(self, 'exists', 0)

	def __pos__(self):
		"""Matches documents that have the specified field.

			+Document.field

		Element operator: {$exists: true}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/exists/#op._S_exists
		"""
		return Op(self, 'exists', 1)

	def of_type(self, *args):
		"""Selects documents if a field is of the correct type.

			Document.field.of_type()
			Document.field.of_type('string')

		Element operator: {$type: self.__foreign__}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/type/#op._S_type
		"""

		if args:
			return Op(self, 'type', args[0])

		return Op(self, 'type', self.__foreign__)
<commit_msg>Only preserve attributes with assigned values.<commit_after># encoding: utf-8

"""MongoDB filter, projection, and update operation helpers.

These encapsulate the functionality of creating combinable mappings
"""

from __future__ import unicode_literals

from itertools import chain
from copy import deepcopy
from collections import Mapping, MutableMapping
from marrow.schema import Container, Attribute
from marrow.schema.compat import odict

from ..util import SENTINEL
from ..util.compat import py3, unicode

if __debug__:
	_simple_safety_check = lambda s, o: (s.__allowed_operators__ and o not in s.__allowed_operators__) or o in s.__disallowed_operators__
	_complex_safety_check = lambda s, o: (s.__allowed_operators__ and not s.__allowed_operators__.intersection(o)) or s.__disallowed_operators__.intersection(o)

class Ops(Container):
	operations = Attribute(default=None)

	def __init__(self, *args, **kw):
		super(Ops, self).__init__(*args, **kw)

		if self.operations is None:
			self.operations = odict()

	def __repr__(self):
		return "{}({})".format(
				self.__class__.__name__,
				repr(list(self.items())).replace("(u'", "('").replace("', u'", "', '")
			)

	@property
	def as_query(self):
		return self.operations

	# Binary Operator Protocols

	def __and__(self, other):
		operations = deepcopy(self.operations)
		extra = {k: self.__data__[k] for k in self.__data__ if k != 'operations'}

		if isinstance(other, Op):
			other = self.__class__(operations=other.as_query)

		for k, v in getattr(other, 'operations', []).items():
			if k not in operations:
				operations[k] = v
			else:
				if not isinstance(operations[k], Mapping):
					operations[k] = odict((('$eq', operations[k]), ))

				if not isinstance(v, Mapping):
					v = odict((('$eq', v), ))

				operations[k].update(v)

		return self.__class__(operations=operations, **extra)

	def __or__(self, other):
		operations = deepcopy(self.operations)
		extra = {k: self.__data__[k] for k in self.__data__ if k != 'operations'}

		if isinstance(other, Op):
			other = self.__class__(operations=other.as_query, **extra)

		if len(operations) == 1 and '$or' in operations:
			# Update existing $or.
			operations['$or'].append(other)
			return self.__class__(operations=operations, **extra)

		return self.__class__(operations={'$or': [operations, other]})

	# Mapping Protocol

	def __getitem__(self, name):
		return self.operations[name]

	def __setitem__(self, name, value):
		self.operations[name] = value

	def __delitem__(self, name):
		del self.operations[name]

	def __iter__(self):
		return iter(self.operations.keys())

	def __len__(self):
		return len(self.operations)

	if py3:
		def keys(self):
			return self.operations.keys()

		def items(self):
			return self.operations.items()

		def values(self):
			return self.operations.values()

	else:
		def keys(self):
			return self.operations.iterkeys()

		def items(self):
			return self.operations.iteritems()

		def values(self):
			return self.operations.itervalues()

	def __contains__(self, key):
		return key in self.operations

	def __eq__(self, other):
		return self.operations == other

	def __ne__(self, other):
		return self.operations != other

	def get(self, key, default=None):
		return self.operations.get(key, default)

	def clear(self):
		self.operations.clear()

	def pop(self, name, default=SENTINEL):
		if default is SENTINEL:
			return self.operations.pop(name)

		return self.operations.pop(name, default)

	def popitem(self):
		return self.operations.popitem()

	def update(self, *args, **kw):
		self.operations.update(*args, **kw)

	def setdefault(self, key, value=None):
		return self.operations.setdefault(key, value)

MutableMapping.register(Ops)  # Metaclass conflict if we subclass.

class Op(Container):
	field = Attribute(default=None)
	operation = Attribute(default=None)
	value = Attribute(default=SENTINEL)

	def __repr__(self):
		return "Op({})".format(repr(self.as_query))

	def clone(self, **kw):
		arguments = dict(field=self.field, operation=self.operation, value=self.value)
		arguments.update(kw)
		return self.__class__(**arguments)

	# Logical Query Selectors
	# https://docs.mongodb.org/manual/reference/operator/query/#logical

	def __or__(self, other):
		return Op(None, 'or', [self, other])

	def __and__(self, other):
		if getattr(other, 'field', None) is None or self.field is None:
			return Op(None, 'and', [self, other])

		return Ops(odict(chain(self.as_query.items(), other.as_query.items())))

	def __invert__(self): # not
		return Op(None, 'not', self)

	@property
	def as_query(self):
		value = getattr(self.value, 'as_query', self.value)
		if value is SENTINEL:
			value = None

		if isinstance(value, list):
			value = [getattr(i, 'as_query', i) for i in value]

		if not self.operation or self.operation == 'eq':
			if not self.field:
				return value

			if self.value is SENTINEL:
				return {unicode(self.field): {'$exists': 1}}

			return {unicode(self.field): value}

		if not self.field:
			return {'$' + unicode(self.operation): value}

		return {unicode(self.field): {'$' + unicode(self.operation): value}}

class Queryable(object):
	"""A convienent mix-in which adds the ability to generate Op instances during comparison.

	Assumes the following are populated:

	 * `self.transformer.foreign` -- a function to convert Python values into MongoDB ones.
	 * `self.__str__` -- calling `str()` (or `unicode()` in Python 2) across `self` should return a field name.
	 * `self.__allowed_operators__` -- a set of allowed operators
	 * `self.__disallowed_operators__` -- a blacklist set of operators
	"""

	__allowed_operators__ = set()
	__disallowed_operators__ = set()

	# Comparison Query Selectors
	# Documentation: https://docs.mongodb.org/manual/reference/operator/query/#comparison

	def __eq__(self, other):
		"""Matches values that are equal to the specified value.

			Document.field == "hOI!"

		Comparison operator: {$eq: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/eq/#op._S_eq
		"""
		if __debug__ and _simple_safety_check(self, '$eq'):  # Optimize this away in production; diagnosic aide.
			raise NotImplementedError("{self.__class__.__name__} does not allow $eq comparison.".format(self=self))

		return Op(self, 'eq', self.transformer.foreign(other, self))

	def __gt__(self, other):
		"""Matches values that are greater than a specified value.

			Document.field > 65

		Comparison operator: {$gt: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/gt/#op._S_gt
		"""
		if __debug__ and _complex_safety_check(self, {'$gt', '#rel'}):  # Optimize this away in production.
			raise NotImplementedError("{self.__class__.__name__} does not allow $gt comparison.".format(self=self))

		return Op(self, 'gt', self.transformer.foreign(other, self))

	def __ge__(self, other):
		"""Matches values that are greater than or equal to a specified value.

			Document.field >= 21

		Comparison operator: {$gte: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/gte/#op._S_gte
		"""
		if __debug__ and _complex_safety_check(self, {'$gte', '#rel'}):  # Optimize this away in production.
			raise NotImplementedError("{self.__class__.__name__} does not allow $gte comparison.".format(self=self))

		return Op(self, 'gte', self.transformer.foreign(other, self))

	def __lt__(self, other):
		"""Matches values that are less than or equal to a specified value.

			Document.field < 18

		Comparison operator: {$lt: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/lt/#op._S_lt
		"""
		if __debug__ and _complex_safety_check(self, {'$lt', '#rel'}):  # Optimize this away in production.
			raise NotImplementedError("{self.__class__.__name__} does not allow $lt comparison.".format(self=self))

		return Op(self, 'lt', self.transformer.foreign(other, self))

	def __le__(self, other):
		"""Matches values that are less than or equal to a specified value.

			Document.field <= 27

		Comparison operator: {$lte: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/lte/#op._S_lte
		"""
		if __debug__ and _complex_safety_check(self, {'$lte', '#rel'}):  # Optimize this away in production.
			raise NotImplementedError("{self.__class__.__name__} does not allow $lte comparison.".format(self=self))

		return Op(self, 'lte', self.transformer.foreign(other, self))

	def __ne__(self, other):
		"""Matches all values that are not equal to a specified value.

			Document.field != 42

		Comparison operator: {$ne: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/ne/#op._S_ne
		"""
		if __debug__ and _complex_safety_check(self, {'$ne', '$eq'}):  # Optimize this away in production.
			raise NotImplementedError("{self.__class__.__name__} does not allow $ne comparison.".format(self=self))

		return Op(self, 'ne', self.transformer.foreign(other, self))

	def any(self, *args):
		"""Matches any of the values specified in an array.

			Document.field.any([1, 2, 3, 5, 8, 13])

		Individual elements may be passed positionally instead, for convienence.

		Comparison operator: {$in: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/in/#op._S_in
		"""
		if __debug__ and _complex_safety_check(self, {'$in', '$eq'}):  # Optimize this away in production.
			raise NotImplementedError("{self.__class__.__name__} does not allow $in comparison.".format(self=self))

		other = args if len(args) > 1 else args[0]

		return Op(self, 'in', [self.transformer.foreign(value, self) for i, value in enumerate(other)])

	def none(self, other):
		"""Matches none of the values specified in an array.

			Document.field.none([2, 3, 5, 7, 11, 13, 17 19, 23, 29])

		Comparison operator: {$nin: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/nin/#op._S_nin
		"""
		return Op(self, 'nin', [self.transformer.foreign(value, self) for i, value in enumerate(other)])

	# Logical Query Selectors
	# https://docs.mongodb.org/manual/reference/operator/query/#logical

	def __or__(self, other):
		raise NotImplementedError()

	def __and__(self, other):
		raise NotImplementedError()

	def __invert__(self):
		raise NotImplementedError()

	# Array Query Selectors
	# https://docs.mongodb.org/manual/reference/operator/query/#array

	def all(self, other):
		"""Matches arrays that contain all elements specified in the query.

			Document.field.all(['hocuspocus', 'xyzzy', 'abracadabra'])

		Array operator: {$all: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/all/#op._S_all
		"""
		if __debug__ and _complex_safety_check(self, {'$all', '#array'}):  # Optimize this away in production.
			raise NotImplementedError("{self.__class__.__name__} does not allow $all comparison.".format(self=self))

		return Op(self, 'all', [self.transformer.foreign(value, self) for i, value in enumerate(other)])

	def match(self, q):
		"""Selects documents if element in the array field matches all the specified conditions.

			Document.field.match(...)

		Array operator: {$elemMatch: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/elemMatch/#op._S_elemMatch
		"""
		if __debug__ and _complex_safety_check(self, {'$elemMatch', '#document'}):  # Optimize this away in production.
			raise NotImplementedError("{self.__class__.__name__} does not allow $elemMatch comparison.".format(self=self))

		if hasattr(q, 'as_query'):
			q = q.as_query

		return Op(self, 'elemMatch', q)

	def range(self, gte, lt):
		"""Matches values that are between a minimum and maximum value, semi-inclusive.

			Document.field.range(4, 12)

		This will find documents with a field whose value is greater than or equal to 4, and less than 12.

		Comparison operator: {$gte: gte, $lt: lt}
		"""
		if __debug__ and _simple_safety_check(self, '#range'):  # Optimize this away in production; diagnosic aide.
			raise NotImplementedError("{self.__class__.__name__} does not allow range comparison.".format(self=self))

		return Ops((self >= gte).as_query) & Ops((self < lt).as_query)

	def size(self, value):
		"""Selects documents if the array field is a specified size.

			Document.field.size(5)

		Array operator: {$size: value}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/size/#op._S_size
		"""
		if __debug__ and _complex_safety_check(self, {'$size', '#array'}):  # Optimize this away in production.
			raise NotImplementedError("{self.__class__.__name__} does not allow $size comparison.".format(self=self))

		return Op(self, 'size', int(value))

	# Element Query Selectors
	# https://docs.mongodb.org/manual/reference/operator/query/#element

	def __neg__(self):
		"""Matches documents that don't have the specified field.

			-Document.field

		Element operator: {$exists: false}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/exists/#op._S_exists
		"""
		return Op(self, 'exists', 0)

	def __pos__(self):
		"""Matches documents that have the specified field.

			+Document.field

		Element operator: {$exists: true}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/exists/#op._S_exists
		"""
		return Op(self, 'exists', 1)

	def of_type(self, *args):
		"""Selects documents if a field is of the correct type.

			Document.field.of_type()
			Document.field.of_type('string')

		Element operator: {$type: self.__foreign__}
		Documentation: https://docs.mongodb.org/manual/reference/operator/query/type/#op._S_type
		"""

		if args:
			return Op(self, 'type', args[0])

		return Op(self, 'type', self.__foreign__)
<|endoftext|>


<commit_before>import random
import string
from chainer.training.triggers import EarlyStoppingTrigger
from chainermn.extensions import ObservationAggregator

class MultiNodeEarlyStoppingTrigger(object):
    """__init__(\
        self, comm, check_trigger=(1, 'epoch'), monitor='main/loss', \
        patience=3, mode='auto', verbose=False, \
        max_trigger=(100, 'epoch'))

    Trigger for Early Stopping in Multiple Node Environments

    It serves almost the same as
    :class:`~chainer.training.triggers.EarlyStoppingTrigger`,
    but it can correctly work in multiple node environments.

    The difference between it and
    :class:`~chainer.training.triggers.EarlyStoppingTrigger` is that,
    in each check interval, it computes the mean of the accumulated
    values *across all nodes*. In this way, all nodes will have the same
    value to determine the timing at which the trigger fires so that
    they will stop at the same time.

    Args:
        comm : ChainerMN communicator
        check_trigger: Trigger that decides the comparison
            interval between current best value and new value.
            This must be a tuple in the form of ``<int>,
            'epoch'`` or ``<int>, 'iteration'`` which is passed to
            :class:`~chainer.training.triggers.IntervalTrigger`.
        monitor (str) : The metric you want to monitor
        patience (int) : Counts to let the trigger be patient.
            The trigger will not fire until the condition is met
            for successive ``patience`` checks.
        mode (str) : ``'max'``, ``'min'``, or ``'auto'``.
            It is used to determine how to compare the monitored values.
        verbose (bool) : Enable verbose output.
            If verbose is true, you can get more information
        max_trigger: Upper bound of the number of training loops
        suffix (str): Suffix added to the name of the monitored
            metric after aggregation.

    .. note::
       ``patients`` is also available as an alias of ``patience`` for
       historical reason.
    """

    def __init__(self, comm, check_trigger=(1, 'epoch'), monitor='main/loss',
                 patience=None, mode='auto', verbose=False,
                 max_trigger=(100, 'epoch'), suffix='_aggregated', **kwargs):

        # `patients` as an alias of `patience`
        monitor_aggregated = monitor + suffix

        self.actual_trigger = EarlyStoppingTrigger(check_trigger=check_trigger,
                                                   monitor=monitor_aggregated,
                                                   patience=patience,
                                                   mode=mode, verbose=verbose,
                                                   max_trigger=max_trigger,
                                                   **kwargs)
        self.aggregator = ObservationAggregator(comm, monitor,
                                                monitor_aggregated,
                                                check_trigger)

    def __call__(self, trainer):
        self.aggregator(trainer)
        return self.actual_trigger(trainer)

    def _stop_condition(self):
        return self.actual_trigger._stop_condition()

    def _init_summary(self):
        return self.actual_trigger._init_summary()

    def get_training_length(self):
        return self.actual_trigger.get_training_length()
<commit_msg>remove unused imports<commit_after>from chainer.training.triggers import EarlyStoppingTrigger
from chainermn.extensions import ObservationAggregator

class MultiNodeEarlyStoppingTrigger(object):
    """__init__(\
        self, comm, check_trigger=(1, 'epoch'), monitor='main/loss', \
        patience=3, mode='auto', verbose=False, \
        max_trigger=(100, 'epoch'))

    Trigger for Early Stopping in Multiple Node Environments

    It serves almost the same as
    :class:`~chainer.training.triggers.EarlyStoppingTrigger`,
    but it can correctly work in multiple node environments.

    The difference between it and
    :class:`~chainer.training.triggers.EarlyStoppingTrigger` is that,
    in each check interval, it computes the mean of the accumulated
    values *across all nodes*. In this way, all nodes will have the same
    value to determine the timing at which the trigger fires so that
    they will stop at the same time.

    Args:
        comm : ChainerMN communicator
        check_trigger: Trigger that decides the comparison
            interval between current best value and new value.
            This must be a tuple in the form of ``<int>,
            'epoch'`` or ``<int>, 'iteration'`` which is passed to
            :class:`~chainer.training.triggers.IntervalTrigger`.
        monitor (str) : The metric you want to monitor
        patience (int) : Counts to let the trigger be patient.
            The trigger will not fire until the condition is met
            for successive ``patience`` checks.
        mode (str) : ``'max'``, ``'min'``, or ``'auto'``.
            It is used to determine how to compare the monitored values.
        verbose (bool) : Enable verbose output.
            If verbose is true, you can get more information
        max_trigger: Upper bound of the number of training loops
        suffix (str): Suffix added to the name of the monitored
            metric after aggregation.

    .. note::
       ``patients`` is also available as an alias of ``patience`` for
       historical reason.
    """

    def __init__(self, comm, check_trigger=(1, 'epoch'), monitor='main/loss',
                 patience=None, mode='auto', verbose=False,
                 max_trigger=(100, 'epoch'), suffix='_aggregated', **kwargs):

        # `patients` as an alias of `patience`
        monitor_aggregated = monitor + suffix

        self.actual_trigger = EarlyStoppingTrigger(check_trigger=check_trigger,
                                                   monitor=monitor_aggregated,
                                                   patience=patience,
                                                   mode=mode, verbose=verbose,
                                                   max_trigger=max_trigger,
                                                   **kwargs)
        self.aggregator = ObservationAggregator(comm, monitor,
                                                monitor_aggregated,
                                                check_trigger)

    def __call__(self, trainer):
        self.aggregator(trainer)
        return self.actual_trigger(trainer)

    def _stop_condition(self):
        return self.actual_trigger._stop_condition()

    def _init_summary(self):
        return self.actual_trigger._init_summary()

    def get_training_length(self):
        return self.actual_trigger.get_training_length()
<|endoftext|>


<commit_before>"""
===========================
Analytical energy demand model algorithm
===========================
File history and credits:
J. Fonseca  script development          24.08.15
D. Thomas   formatting, refactoring, debugging and cleaning
D. Thomas   integration in toolbox
J. Fonseca  refactoring to new properties file   22.03.16
G. Happle   BuildingPropsThermalLoads   27.05.2016
"""
from __future__ import division

import pandas as pd
import contributions.thermal_loads_new_ventilation.simple_window_generator as simple_window_generator
from geopandas import GeoDataFrame as gpdf
import epwreader
import functions as f
import globalvar
import inputlocator
import maker as m

__author__ = "Jimeno A. Fonseca"
__copyright__ = "Copyright 2015, Architecture and Building Systems - ETH Zurich"
__credits__ = ["Jimeno A. Fonseca", "Daren Thomas", "Gabriel Happle"]
__license__ = "MIT"
__version__ = "0.1"
__maintainer__ = "Daren Thomas"
__email__ = "thomas@arch.ethz.ch"
__status__ = "Production"

reload(f)
reload(globalvar)

def demand_calculation(locator, weather_path, gv):
    """
    Algorithm to calculate the hourly demand of energy services in buildings
    using the integrated model of Fonseca et al. 2015. Applied energy.

    Parameters
    ----------
    :param locator: An InputLocator to locate input files
    :type locator: inputlocator.InputLocator

    :param weather_path: A path to the EnergyPlus weather data file (.epw)
    :type weather_path: str

    :param gv: A GlobalVariable (context) instance
    :type gv: globalvar.GlobalVariable

    Returns
    -------

    None

    Side effects
    ------------

    Produces a demand file per building and a total demand file for the whole zone of interest.

    FIXME: update this part of the documentation
    single_demand: .csv
        csv file for every building with hourly demand data
    total_demand: .csv
        csv file of yearly demand data per buidling.
    """
    # local variables

    # initialize function inputs
    weather_data = epwreader.epw_reader(weather_path)[['drybulb_C', 'relhum_percent', 'windspd_ms']]
    building_properties = read_building_properties(locator, gv)
    # get list of uses
    list_uses = list(building_properties._prop_occupancy.drop('PFloor', axis=1).columns)
    # get date
    date = pd.date_range(gv.date_start, periods=8760, freq='H')

    gv.log("reading occupancy schedules")
    # get schedules
    schedules = m.schedule_maker(date, locator, list_uses)
    gv.log("done")

    # construct schedules dict for input to function
    usage_schedules = {'list_uses': list_uses,
                       'schedules': schedules}

    # get timeseries of demand
    num_buildings = len(building_properties.get_list_building_name())
    counter = 0

    for building in building_properties.get_list_building_name():
        gv.models['calc-thermal-loads'](building, building_properties, weather_data, usage_schedules, date, gv,
                                        locator.get_demand_results_folder(), locator.get_temporary_folder())

        gv.log('Building No. %(bno)i completed out of %(btot)i', bno=counter + 1, btot=num_buildings)
        counter += 1

    # get total file

    counter = 0
    for name in building_properties.get_list_building_name():
        temporary_file = locator.get_temporary_file('%(name)sT.csv' % locals())
        # TODO: check this logic
        if counter == 0:
            df = pd.read_csv(temporary_file)
            counter += 1
        else:
            df2 = pd.read_csv(temporary_file)
            df = df.append(df2, ignore_index=True)
    df.to_csv(locator.get_total_demand(), index=False, float_format='%.2f')

    gv.log('finished')

def get_temperatures(locator, prop_HVAC):
    prop_emission_heating = pd.read_excel(locator.get_technical_emission_systems(), 'heating')
    prop_emission_cooling = pd.read_excel(locator.get_technical_emission_systems(), 'cooling')
    prop_emission_dhw = pd.read_excel(locator.get_technical_emission_systems(), 'dhw')

    df = prop_HVAC.merge(prop_emission_heating, left_on='type_hs', right_on='code')
    df2 = prop_HVAC.merge(prop_emission_cooling, left_on='type_cs', right_on='code')
    df3 = prop_HVAC.merge(prop_emission_dhw, left_on='type_dhw', right_on='code')

    fields = ['Name', 'type_hs', 'type_cs', 'type_dhw', 'type_ctrl', 'Tshs0_C', 'dThs0_C', 'Qhsmax_Wm2']
    fields2 = ['Name', 'Tscs0_C', 'dTcs0_C', 'Qcsmax_Wm2']
    fields3 = ['Name', 'Tsww0_C', 'dTww0_C', 'Qwwmax_Wm2']

    result = df[fields].merge(df2[fields2], on='Name').merge(df3[fields3], on='Name')
    return result

class BuildingProperties(object):
    """
    Groups building properties used for the calc-thermal-loads functions. Stores the full DataFrame for each of the
    building properties and provides methods for indexing them by name.

    G. Happle   BuildingPropsThermalLoads   27.05.2016
    """
    def __init__(self, prop_geometry=None, prop_architecture=None, prop_occupancy=None, prop_HVAC_result=None,
                 prop_RC_model=None, prop_comfort=None, prop_internal_loads=None, prop_age=None, solar=None,
                 prop_windows=None):
        self._prop_geometry = prop_geometry
        self._prop_architecture = prop_architecture
        self._prop_occupancy = prop_occupancy
        self._prop_HVAC_result = prop_HVAC_result
        self._prop_RC_model = prop_RC_model
        self._prop_comfort = prop_comfort
        self._prop_internal_loads = prop_internal_loads
        self._prop_age = prop_age
        self._solar = solar
        self._prop_windows = prop_windows

    def get_list_building_name(self):
        """get list of all building names"""
        return self._prop_RC_model.index

    def get_prop_geometry(self, name_building):
        """get geometry of a building by name"""
        return self._prop_geometry.ix[name_building]

    def get_prop_architecture(self, name_building):
        """get the architecture properties of a building by name"""
        return self._prop_architecture.ix[name_building]

    def get_prop_occupancy(self, name_building):
        """get the occupancy properties of a building by name"""
        return self._prop_occupancy.ix[name_building]

    def get_prop_hvac(self, name_building):
        """get HVAC properties of a building by name"""
        return self._prop_HVAC_result.ix[name_building]

    def get_prop_rc_model(self, name_building):
        """get RC-model properties of a building by name"""
        return self._prop_RC_model.ix[name_building]

    def get_prop_comfort(self, name_building):
        """get comfort properties of a building by name"""
        return self._prop_comfort.ix[name_building]

    def get_prop_internal_loads(self, name_building):
        """get internal loads properties of a building by name"""
        return self._prop_internal_loads.ix[name_building]

    def get_prop_age(self, name_building):
        """get age properties of a building by name"""
        return self._prop_age.ix[name_building]

    def get_solar(self, name_building):
        """get solar properties of a building by name"""
        return self._solar.ix[name_building]

    def get_prop_windows(self, name_building):
        """get windows and their properties of a building by name"""
        return self._prop_windows.loc[self._prop_windows['name_building'] == name_building].to_dict('list')

def read_building_properties(locator, gv):
    """
    Read building properties from input shape files.

    Parameters
    ----------

    :param locator: an InputLocator for locating the input files
    :type locator: cea.inputlocator.InputLocator

    :param gv: contains the context (constants and models) for the calculation
    :type gv: cea.globalvar.GlobalVariables

    Returns
    -------

    :returns: object of type BuildingProperties
    :rtype: BuildingProperties

    Input files used
    ----------------

    - locator.get_radiation(): scenario/outputs/data/solar-radiation/radiation.csv
    - locator.get_surface_properties(): scenario/outputs/data/solar-radiation/properties_surfaces.csv
    - locator.get_building_geometry(): scenario/inputs/building-geometry/zone.shp
    - locator.get_building_hvac(): scenario/inputs/building-properties/technical_systems.shp
    - locator.get_building_thermal(): scenario/inputs/building-properties/thermal_properties.shp
    - locator.get_building_occupancy(): scenario/inputs/building-properties/occupancy.shp
    - locator.get_building_architecture(): scenario/inputs/building-properties/architecture.shp
    - locator.get_building_age(): scenario/inputs/building-properties/age.shp
    - locator.get_building_comfort(): scenario/inputs/building-properties/indoor_comfort.shp'
    - locator.get_building_internal(): scenario/inputs/building-properties/internal_loads.shp
    """

    gv.log("reading input files")
    solar = pd.read_csv(locator.get_radiation()).set_index('Name')
    surface_properties = pd.read_csv(locator.get_surface_properties())
    prop_geometry = gpdf.from_file(locator.get_building_geometry())
    prop_geometry['footprint'] = prop_geometry.area
    prop_geometry['perimeter'] = prop_geometry.length
    prop_geometry = prop_geometry.drop('geometry', axis=1).set_index('Name')
    prop_HVAC = gpdf.from_file(locator.get_building_hvac()).drop('geometry', axis=1)
    prop_thermal = gpdf.from_file(locator.get_building_thermal()).drop('geometry', axis=1).set_index('Name')
    prop_occupancy_df = gpdf.from_file(locator.get_building_occupancy()).drop('geometry', axis=1).set_index('Name')
    prop_occupancy = prop_occupancy_df.loc[:, (prop_occupancy_df != 0).any(
        axis=0)]  # trick to erase occupancies that are not being used (it speeds up the code)
    prop_architecture = gpdf.from_file(locator.get_building_architecture()).drop('geometry', axis=1).set_index('Name')
    prop_age = gpdf.from_file(locator.get_building_age()).drop('geometry', axis=1).set_index('Name')
    prop_comfort = gpdf.from_file(locator.get_building_comfort()).drop('geometry', axis=1).set_index('Name')
    prop_internal_loads = gpdf.from_file(locator.get_building_internal()).drop('geometry', axis=1).set_index('Name')
    # get temperatures of operation
    prop_HVAC_result = get_temperatures(locator, prop_HVAC).set_index('Name')
    gv.log('done')

    gv.log("calculating thermal properties")
    prop_RC_model = f.get_prop_RC_model(prop_occupancy, prop_architecture, prop_thermal, prop_geometry,
                                        prop_HVAC_result, surface_properties, gv)
    gv.log("done")

    gv.log("creating windows")
    df_windows = simple_window_generator.create_windows(surface_properties, prop_architecture)
    gv.log("done")

    # construct function input object
    return BuildingProperties(prop_geometry=prop_geometry, prop_occupancy=prop_occupancy,
                              prop_architecture=prop_architecture, prop_age=prop_age,
                              prop_comfort=prop_comfort, prop_internal_loads=prop_internal_loads,
                              prop_HVAC_result=prop_HVAC_result, prop_RC_model=prop_RC_model,
                              solar=solar, prop_windows=df_windows)

def test_demand():
    locator = inputlocator.InputLocator(scenario_path=r'C:\reference-case\baseline')
    # for the interface, the user should pick a file out of of those in ...DB/Weather/...
    weather_path = locator.get_default_weather()
    gv = globalvar.GlobalVariables()
    demand_calculation(locator=locator, weather_path=weather_path, gv=gv)
    print "test_demand() succeeded"

if __name__ == '__main__':
    test_demand()<commit_msg>renamed `gpdf` in demand to `GeoDataFrame` (PEP8)<commit_after>"""
===========================
Analytical energy demand model algorithm
===========================
File history and credits:
J. Fonseca  script development          24.08.15
D. Thomas   formatting, refactoring, debugging and cleaning
D. Thomas   integration in toolbox
J. Fonseca  refactoring to new properties file   22.03.16
G. Happle   BuildingPropsThermalLoads   27.05.2016
"""
from __future__ import division

import pandas as pd
import contributions.thermal_loads_new_ventilation.simple_window_generator as simple_window_generator
from geopandas import GeoDataFrame
import epwreader
import functions as f
import globalvar
import inputlocator
import maker as m

__author__ = "Jimeno A. Fonseca"
__copyright__ = "Copyright 2015, Architecture and Building Systems - ETH Zurich"
__credits__ = ["Jimeno A. Fonseca", "Daren Thomas", "Gabriel Happle"]
__license__ = "MIT"
__version__ = "0.1"
__maintainer__ = "Daren Thomas"
__email__ = "thomas@arch.ethz.ch"
__status__ = "Production"

reload(f)
reload(globalvar)

def demand_calculation(locator, weather_path, gv):
    """
    Algorithm to calculate the hourly demand of energy services in buildings
    using the integrated model of Fonseca et al. 2015. Applied energy.

    Parameters
    ----------
    :param locator: An InputLocator to locate input files
    :type locator: inputlocator.InputLocator

    :param weather_path: A path to the EnergyPlus weather data file (.epw)
    :type weather_path: str

    :param gv: A GlobalVariable (context) instance
    :type gv: globalvar.GlobalVariable

    Returns
    -------

    None

    Side effects
    ------------

    Produces a demand file per building and a total demand file for the whole zone of interest.

    FIXME: update this part of the documentation
    single_demand: .csv
        csv file for every building with hourly demand data
    total_demand: .csv
        csv file of yearly demand data per buidling.
    """
    # local variables

    # initialize function inputs
    weather_data = epwreader.epw_reader(weather_path)[['drybulb_C', 'relhum_percent', 'windspd_ms']]
    building_properties = read_building_properties(locator, gv)
    # get list of uses
    list_uses = list(building_properties._prop_occupancy.drop('PFloor', axis=1).columns)
    # get date
    date = pd.date_range(gv.date_start, periods=8760, freq='H')

    gv.log("reading occupancy schedules")
    # get schedules
    schedules = m.schedule_maker(date, locator, list_uses)
    gv.log("done")

    # construct schedules dict for input to function
    usage_schedules = {'list_uses': list_uses,
                       'schedules': schedules}

    # get timeseries of demand
    num_buildings = len(building_properties.get_list_building_name())
    counter = 0

    for building in building_properties.get_list_building_name():
        gv.models['calc-thermal-loads'](building, building_properties, weather_data, usage_schedules, date, gv,
                                        locator.get_demand_results_folder(), locator.get_temporary_folder())

        gv.log('Building No. %(bno)i completed out of %(btot)i', bno=counter + 1, btot=num_buildings)
        counter += 1

    # get total file

    counter = 0
    for name in building_properties.get_list_building_name():
        temporary_file = locator.get_temporary_file('%(name)sT.csv' % locals())
        # TODO: check this logic
        if counter == 0:
            df = pd.read_csv(temporary_file)
            counter += 1
        else:
            df2 = pd.read_csv(temporary_file)
            df = df.append(df2, ignore_index=True)
    df.to_csv(locator.get_total_demand(), index=False, float_format='%.2f')

    gv.log('finished')

def get_temperatures(locator, prop_HVAC):
    prop_emission_heating = pd.read_excel(locator.get_technical_emission_systems(), 'heating')
    prop_emission_cooling = pd.read_excel(locator.get_technical_emission_systems(), 'cooling')
    prop_emission_dhw = pd.read_excel(locator.get_technical_emission_systems(), 'dhw')

    df = prop_HVAC.merge(prop_emission_heating, left_on='type_hs', right_on='code')
    df2 = prop_HVAC.merge(prop_emission_cooling, left_on='type_cs', right_on='code')
    df3 = prop_HVAC.merge(prop_emission_dhw, left_on='type_dhw', right_on='code')

    fields = ['Name', 'type_hs', 'type_cs', 'type_dhw', 'type_ctrl', 'Tshs0_C', 'dThs0_C', 'Qhsmax_Wm2']
    fields2 = ['Name', 'Tscs0_C', 'dTcs0_C', 'Qcsmax_Wm2']
    fields3 = ['Name', 'Tsww0_C', 'dTww0_C', 'Qwwmax_Wm2']

    result = df[fields].merge(df2[fields2], on='Name').merge(df3[fields3], on='Name')
    return result

class BuildingProperties(object):
    """
    Groups building properties used for the calc-thermal-loads functions. Stores the full DataFrame for each of the
    building properties and provides methods for indexing them by name.

    G. Happle   BuildingPropsThermalLoads   27.05.2016
    """
    def __init__(self, prop_geometry=None, prop_architecture=None, prop_occupancy=None, prop_HVAC_result=None,
                 prop_RC_model=None, prop_comfort=None, prop_internal_loads=None, prop_age=None, solar=None,
                 prop_windows=None):
        self._prop_geometry = prop_geometry
        self._prop_architecture = prop_architecture
        self._prop_occupancy = prop_occupancy
        self._prop_HVAC_result = prop_HVAC_result
        self._prop_RC_model = prop_RC_model
        self._prop_comfort = prop_comfort
        self._prop_internal_loads = prop_internal_loads
        self._prop_age = prop_age
        self._solar = solar
        self._prop_windows = prop_windows

    def get_list_building_name(self):
        """get list of all building names"""
        return self._prop_RC_model.index

    def get_prop_geometry(self, name_building):
        """get geometry of a building by name"""
        return self._prop_geometry.ix[name_building]

    def get_prop_architecture(self, name_building):
        """get the architecture properties of a building by name"""
        return self._prop_architecture.ix[name_building]

    def get_prop_occupancy(self, name_building):
        """get the occupancy properties of a building by name"""
        return self._prop_occupancy.ix[name_building]

    def get_prop_hvac(self, name_building):
        """get HVAC properties of a building by name"""
        return self._prop_HVAC_result.ix[name_building]

    def get_prop_rc_model(self, name_building):
        """get RC-model properties of a building by name"""
        return self._prop_RC_model.ix[name_building]

    def get_prop_comfort(self, name_building):
        """get comfort properties of a building by name"""
        return self._prop_comfort.ix[name_building]

    def get_prop_internal_loads(self, name_building):
        """get internal loads properties of a building by name"""
        return self._prop_internal_loads.ix[name_building]

    def get_prop_age(self, name_building):
        """get age properties of a building by name"""
        return self._prop_age.ix[name_building]

    def get_solar(self, name_building):
        """get solar properties of a building by name"""
        return self._solar.ix[name_building]

    def get_prop_windows(self, name_building):
        """get windows and their properties of a building by name"""
        return self._prop_windows.loc[self._prop_windows['name_building'] == name_building].to_dict('list')

def read_building_properties(locator, gv):
    """
    Read building properties from input shape files.

    Parameters
    ----------

    :param locator: an InputLocator for locating the input files
    :type locator: cea.inputlocator.InputLocator

    :param gv: contains the context (constants and models) for the calculation
    :type gv: cea.globalvar.GlobalVariables

    Returns
    -------

    :returns: object of type BuildingProperties
    :rtype: BuildingProperties

    Input files used
    ----------------

    - locator.get_radiation(): scenario/outputs/data/solar-radiation/radiation.csv
    - locator.get_surface_properties(): scenario/outputs/data/solar-radiation/properties_surfaces.csv
    - locator.get_building_geometry(): scenario/inputs/building-geometry/zone.shp
    - locator.get_building_hvac(): scenario/inputs/building-properties/technical_systems.shp
    - locator.get_building_thermal(): scenario/inputs/building-properties/thermal_properties.shp
    - locator.get_building_occupancy(): scenario/inputs/building-properties/occupancy.shp
    - locator.get_building_architecture(): scenario/inputs/building-properties/architecture.shp
    - locator.get_building_age(): scenario/inputs/building-properties/age.shp
    - locator.get_building_comfort(): scenario/inputs/building-properties/indoor_comfort.shp'
    - locator.get_building_internal(): scenario/inputs/building-properties/internal_loads.shp
    """

    gv.log("reading input files")
    solar = pd.read_csv(locator.get_radiation()).set_index('Name')
    surface_properties = pd.read_csv(locator.get_surface_properties())
    prop_geometry = GeoDataFrame.from_file(locator.get_building_geometry())
    prop_geometry['footprint'] = prop_geometry.area
    prop_geometry['perimeter'] = prop_geometry.length
    prop_geometry = prop_geometry.drop('geometry', axis=1).set_index('Name')
    prop_HVAC = GeoDataFrame.from_file(locator.get_building_hvac()).drop('geometry', axis=1)
    prop_thermal = GeoDataFrame.from_file(locator.get_building_thermal()).drop('geometry', axis=1).set_index('Name')
    prop_occupancy_df = GeoDataFrame.from_file(locator.get_building_occupancy()).drop('geometry', axis=1).set_index('Name')
    prop_occupancy = prop_occupancy_df.loc[:, (prop_occupancy_df != 0).any(
        axis=0)]  # trick to erase occupancies that are not being used (it speeds up the code)
    prop_architecture = GeoDataFrame.from_file(locator.get_building_architecture()).drop('geometry', axis=1).set_index('Name')
    prop_age = GeoDataFrame.from_file(locator.get_building_age()).drop('geometry', axis=1).set_index('Name')
    prop_comfort = GeoDataFrame.from_file(locator.get_building_comfort()).drop('geometry', axis=1).set_index('Name')
    prop_internal_loads = GeoDataFrame.from_file(locator.get_building_internal()).drop('geometry', axis=1).set_index('Name')
    # get temperatures of operation
    prop_HVAC_result = get_temperatures(locator, prop_HVAC).set_index('Name')
    gv.log('done')

    gv.log("calculating thermal properties")
    prop_RC_model = f.get_prop_RC_model(prop_occupancy, prop_architecture, prop_thermal, prop_geometry,
                                        prop_HVAC_result, surface_properties, gv)
    gv.log("done")

    gv.log("creating windows")
    df_windows = simple_window_generator.create_windows(surface_properties, prop_architecture)
    gv.log("done")

    # construct function input object
    return BuildingProperties(prop_geometry=prop_geometry, prop_occupancy=prop_occupancy,
                              prop_architecture=prop_architecture, prop_age=prop_age,
                              prop_comfort=prop_comfort, prop_internal_loads=prop_internal_loads,
                              prop_HVAC_result=prop_HVAC_result, prop_RC_model=prop_RC_model,
                              solar=solar, prop_windows=df_windows)

def test_demand():
    locator = inputlocator.InputLocator(scenario_path=r'C:\reference-case\baseline')
    # for the interface, the user should pick a file out of of those in ...DB/Weather/...
    weather_path = locator.get_default_weather()
    gv = globalvar.GlobalVariables()
    demand_calculation(locator=locator, weather_path=weather_path, gv=gv)
    print "test_demand() succeeded"

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


<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
#    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/>.
#
##############################################################################

from osv import fields, osv
import tools

class report_event_registration(osv.osv):

    _name = "report.event.registration"
    _description = "Events Analysis"
    _auto = False
    _rec_name = 'date'
    _columns = {
        'event_date': fields.char('Event Start Date', size=64, readonly=True),
        'year': fields.char('Year', size=4, readonly=True),
        'month': fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'),
            ('05','May'), ('06','June'), ('07','July'), ('08','August'), ('09','September'),
            ('10','October'), ('11','November'), ('12','December')], 'Month',readonly=True),
        'event_id': fields.many2one('event.event', 'Event', required=True),
        'draft_state': fields.integer(' # No of Draft Registrations', size=20),
        'confirm_state': fields.integer(' # No of Confirmed Registrations', size=20),
        'register_max': fields.integer('Maximum Registrations'),
        'nbevent': fields.integer('Number Of Events'),
        'event_type': fields.many2one('event.type', 'Event Type'),
        'registration_state': fields.selection([('draft', 'Draft'), ('confirm', 'Confirmed'), ('done', 'Attended'), ('cancel', 'Cancelled')], 'Registration State', readonly=True, required=True),
        'event_state': fields.selection([('draft', 'Draft'), ('confirm', 'Confirmed'), ('done', 'Done'), ('cancel', 'Cancelled')], 'Event State', readonly=True, required=True),
        'user_id': fields.many2one('res.users', 'Event Responsible', readonly=True),
        'user_id_registration': fields.many2one('res.users', 'Register', readonly=True),
        'name_registration': fields.char('Participant / Contact Name',size=45, readonly=True),
        'speaker_id': fields.many2one('res.partner', 'Speaker', readonly=True),
        'company_id': fields.many2one('res.company', 'Company', readonly=True),
    }
    _order = 'event_date desc'
    def init(self, cr):
        """
        initialize the sql view for the event registration
        cr -- the cursor
        """
        tools.drop_view_if_exists(cr, 'report_event_registration')
        cr.execute("""
         CREATE OR REPLACE view report_event_registration AS (
                SELECT
                event_id,
                r.id,
                e.user_id AS user_id,
                r.user_id AS user_id_registration,
                r.name AS name_registration,
                e.company_id AS company_id,
                e.main_speaker_id AS speaker_id,
                to_char(e.date_begin, 'YYYY-MM-DD') AS event_date,
                to_char(e.date_begin, 'YYYY') AS year,
                to_char(e.date_begin, 'MM') AS month,
                count(e.id) AS nbevent,
                CASE WHEN r.state IN ('draft') THEN r.nb_register ELSE 0 END AS draft_state,
                CASE WHEN r.state IN ('open','done') THEN r.nb_register ELSE 0 END AS confirm_state,
                e.type AS event_type,
                e.register_max AS register_max,
                e.state AS  event_state,
                r.state AS  registration_state
                FROM
                event_event e

                LEFT JOIN
                    event_registration r ON (e.id=r.event_id)

               GROUP BY
                event_id,
                user_id_registration,
                e.id,
                r.id,
                registration_state,
                r.nb_register,
                event_type, e.id, e.date_begin, e.main_speaker_id,
                e.register_max,event_id, e.user_id,e.company_id,
                e.user_id,
                event_state,
                e.company_id,
                e.main_speaker_id,
                year,
                month,
                e.register_max,
                name_registration

              )
                """)

report_event_registration()

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<commit_msg>[FIX] event: removed invalid _rec_name.<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
#    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/>.
#
##############################################################################

from osv import fields, osv
import tools

class report_event_registration(osv.osv):

    _name = "report.event.registration"
    _description = "Events Analysis"
    _auto = False
    _columns = {
        'event_date': fields.char('Event Start Date', size=64, readonly=True),
        'year': fields.char('Year', size=4, readonly=True),
        'month': fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'),
            ('05','May'), ('06','June'), ('07','July'), ('08','August'), ('09','September'),
            ('10','October'), ('11','November'), ('12','December')], 'Month',readonly=True),
        'event_id': fields.many2one('event.event', 'Event', required=True),
        'draft_state': fields.integer(' # No of Draft Registrations', size=20),
        'confirm_state': fields.integer(' # No of Confirmed Registrations', size=20),
        'register_max': fields.integer('Maximum Registrations'),
        'nbevent': fields.integer('Number Of Events'),
        'event_type': fields.many2one('event.type', 'Event Type'),
        'registration_state': fields.selection([('draft', 'Draft'), ('confirm', 'Confirmed'), ('done', 'Attended'), ('cancel', 'Cancelled')], 'Registration State', readonly=True, required=True),
        'event_state': fields.selection([('draft', 'Draft'), ('confirm', 'Confirmed'), ('done', 'Done'), ('cancel', 'Cancelled')], 'Event State', readonly=True, required=True),
        'user_id': fields.many2one('res.users', 'Event Responsible', readonly=True),
        'user_id_registration': fields.many2one('res.users', 'Register', readonly=True),
        'name_registration': fields.char('Participant / Contact Name',size=45, readonly=True),
        'speaker_id': fields.many2one('res.partner', 'Speaker', readonly=True),
        'company_id': fields.many2one('res.company', 'Company', readonly=True),
    }
    _order = 'event_date desc'
    def init(self, cr):
        """
        initialize the sql view for the event registration
        cr -- the cursor
        """
        tools.drop_view_if_exists(cr, 'report_event_registration')
        cr.execute("""
         CREATE OR REPLACE view report_event_registration AS (
                SELECT
                event_id,
                r.id,
                e.user_id AS user_id,
                r.user_id AS user_id_registration,
                r.name AS name_registration,
                e.company_id AS company_id,
                e.main_speaker_id AS speaker_id,
                to_char(e.date_begin, 'YYYY-MM-DD') AS event_date,
                to_char(e.date_begin, 'YYYY') AS year,
                to_char(e.date_begin, 'MM') AS month,
                count(e.id) AS nbevent,
                CASE WHEN r.state IN ('draft') THEN r.nb_register ELSE 0 END AS draft_state,
                CASE WHEN r.state IN ('open','done') THEN r.nb_register ELSE 0 END AS confirm_state,
                e.type AS event_type,
                e.register_max AS register_max,
                e.state AS  event_state,
                r.state AS  registration_state
                FROM
                event_event e

                LEFT JOIN
                    event_registration r ON (e.id=r.event_id)

               GROUP BY
                event_id,
                user_id_registration,
                e.id,
                r.id,
                registration_state,
                r.nb_register,
                event_type, e.id, e.date_begin, e.main_speaker_id,
                e.register_max,event_id, e.user_id,e.company_id,
                e.user_id,
                event_state,
                e.company_id,
                e.main_speaker_id,
                year,
                month,
                e.register_max,
                name_registration

              )
                """)

report_event_registration()

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<|endoftext|>


<commit_before>from .models import Errata

from rest_framework import serializers

class ErrataSerializer(serializers.ModelSerializer):
    resolution_date = serializers.DateField(read_only=True)

    class Meta:
        model = Errata
        fields = ('id',
                  'created',
                  'modified',
                  'book',
                  'status',
                  'resolution',
                  'reviewed_date',
                  'corrected_date',
                  'archived',
                  'is_assessment_errata',
                  'location',
                  'detail',
                  'short_detail',
                  'resolution_date',
                  'resolution_notes',
                  'error_type',
                  'error_type_other',
                  'resource',
                  'resource_other',
                  'submitted_by',
                  'submitter_email_address',
                  'file_1',
                  'file_2')
<commit_msg>replace submitted user information on errata post api<commit_after>from .models import Errata

from rest_framework import serializers

class ErrataSerializer(serializers.ModelSerializer):
    resolution_date = serializers.DateField(read_only=True)

    class Meta:
        model = Errata
        fields = ('id',
                  'created',
                  'modified',
                  'book',
                  'status',
                  'resolution',
                  'reviewed_date',
                  'corrected_date',
                  'archived',
                  'is_assessment_errata',
                  'location',
                  'detail',
                  'short_detail',
                  'resolution_date',
                  'resolution_notes',
                  'error_type',
                  'error_type_other',
                  'resource',
                  'resource_other',
                  'submitted_by_account_id',
                  'file_1',
                  'file_2')
<|endoftext|>