summer.tests.examples.appcontext.appcontext — py-summer 0.6.0 documentation

# Source code for summer.tests.examples.appcontext.appcontext

    # -*- coding: utf-8 -*-
    # Time-stamp: < appcontext.py (2016-01-31 04:04) >

    # Copyright (C) 2009-2016 Martin Slouf <martin.slouf@sourceforge.net>
    #
    # This file is a part of Summer.
    #
    # Summer is free software; you can redistribute it and/or modify it under
    # the terms of the GNU Lesser 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 Lesser General Public License for more details.
    #
    # You should have received a copy of the GNU Lesser General Public License
    # along with this program; if not, write to the Free Software
    # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

    """This module demonstrates the very core usage of the summer application
    framework.

    For people familiar with Java spring framework -- this file defines the
    ``ApplicationContext`` class.  All configuration is placed directly in your
    *Python* code.

    Among other resources somewhere in your application you will have a file
    like this -- a file defining a 'context' for your application business
    layer.  You can of course have more layers, more contexts, ...

    Such a context class serves as a container for your business objects.  Once
    you have you context initialized, you may usually access all your
    application's services from one single place.  The best is, that all the
    creation, dependency and initialization logic among your business objects
    is defined there.

    Objects deployed into the context should be stateless and can be treated as
    singletons (but there is no rule for that and you can deploy whatever you
    want in any way you like it) -- please see any discussion on inversion of
    control containers (IoC) for more info.

    This simple example shows:

      1. sample context definition with very simple declarative transaction
      handling

      2. basic concept how to use logging and custom configuration files --
      logging config (defined by Python stdlib), summer framework config
      (including database connection definition) and custom config for your
      project

      3. So you get an idea, what its all about :-)

    """

    # usual imports
    import logging
    import optparse

    # import the summer framework
    import summer

    # reasonable and simple convention on getting a logger
    logger = logging.getLogger(__name__)

    class OptionParser(optparse.OptionParser):

        """Command line parser.

        This class has access to custom config to appropriately set the default
        values.

        """

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

    class Entity(summer.Entity):

        """Entities are usually ORM mapped classes :py:class:`summer.domain.Entity`"""
        pass

    class EntityDao(summer.Dao):

        """Dao object for our :py:class:`Entity`.

        Entity persistence logic is usually managed by a Dao object; usually
        you will subclass those provided by py-summer, see
        :py:class:`summer.dao.Dao` for details.

        """

        def __init__(self, session_factory):
            summer.Dao.__init__(self, session_factory)

        @summer.transactional
        def find(self, filter):
            """Dao methods are usually declared as transactional.  That does not say
            they always run in separate transaction, but it says that such a
            method can be run in transaction if run inside a transactional
            proxy :py:class:`summer.txaop.TransactionalProxy`.

            """
            pass

    class EntityManager(object):

        """This class manages entities using the Dao, probably it adds some
        business logic for creating a new object and such.

        """

        def __init__(self, entity_dao):
            pass

        @summer.transactional
        def create_entity(self, entity):
            """Method is marked as transactional.  See below how transactional proxy is
            created.

            """
            logger.info("creating new entity")

    class ApplicationContext(summer.Context):

        """The much anticipated application context class."""

        def __init__(self, path_to_module, customcfg):
            """:py:class:`summer.context.Context` has some more arguments, but usually
            those 2 are the only ones required, as the others defaults to
            reasonable values, see api doc.  See how easy is to pass a
            'path_to_module' in 'run.py'.

            """
            summer.Context.__init__(self, path_to_module, customcfg)

        def context_init(self):
            """
            Please see api doc.

            By now we suppose we have some core objects defined in context
            based on configuration.
            """

            # on the first lines you will probably complete your SQLAlchemy
            # ORM, if you use one, with something like below, but for now, lets
            # just skip it, once done, your ORM layer is fully configured and
            # ready to use
            # self.table_definitions = TableDefinitions(self.session_factory)
            # self.class_mappings = ClassMappings(self.session_factory)

            # we deploy our command line parser -- which access some settings
            # from our config file, so it holds a reference to it
            self.option_parser = OptionParser(self.config)

            # lets deploy our only DAO -- any data access object should have a
            # reference to session factory to obtain session from it any time
            # it accesses data
            self.entity_dao = EntityDao(self.session_factory)
            # also any data aware object, that has some transactional methods,
            # can be deployed as transactional proxy, the proxy itself accesses
            # the session factory, but is capable to obtain it from the target
            # object -- no need to pass it as a constructor arg -- there is a
            # very simple convention -- it just looks for 'session_factory'
            # attribute in the target object (ie. our DAO)
            self.entity_dao_proxy = summer.TransactionProxy(self.entity_dao)

            # the same as for EntityDao is for EntityManager, we deploy the
            # non-proxied dao and as it defines its own transaction boundaries
            # we deploy also a transaction proxy.  we should provide the
            # session factory now, because the detection mechanism is not very
            # smart and just checks for an attribute named 'session_factory'
            # inside a target object as said earlier and apparently
            # EntityManager class has no such attribute
            self.entity_manager = EntityManager(self.entity_dao)
            self.entity_manager_proxy = summer.TransactionProxy(
                self.entity_manager,
                self.session_factory)