Metadata-Version: 1.2
Name: Baluster
Version: 0.1
Summary: Provides hierarchical factory
Home-page: https://gitlab.com/palankai/factory_tree
Author: Csaba Palankai
Author-email: csaba.palankai@gmail.com
License: MIT
Description: ==================================
        Baluster - Python Composition tool
        ==================================
        
        .. image:: https://travis-ci.org/palankai/baluster.svg?branch=master
            :target: https://travis-ci.org/palankai/baluster
        
        | Project homepage: `<https://github.com/palankai/baluster>`_
        | Issues: `<https://github.com/palankai/baluster/issues>`_
        |
        
        What is this package for
        ------------------------
        
        This package provides a simple way to build back structure of application.
        Can be used building composite root as acting a factory for resources,
        building a fixture factory for tests.
        
        Features
        --------
        
          - Lazy initialisation
          - Simple composition and dependency handling
        
        
        Example - composie root
        -----------------------
        
        .. code:: python
        
            from baluster import Holder
            import psycopg2
        
            class ApplicationRoot(Holder):
                @Holder.factory
                def db(self, root):
                    # Will be called at the first use
                    # Will be cached so won't be called again
                    return psycopg2.connect("dbname=test user=postgres")
        
                @db.close
                def _close_db(self, root, db):
                    db.close()
        
                @Holder.factory
                def cr(self, root):
                    return self.db.cursor()
        
                @cr.close
                def _close_cr(self, root, cr):
                    cr.close()
        
        
            def main():
                approot = ApplicationRoot()
                with approot:
                    approot.cr.execute('SELECT * FROM user')
        
                # at this point the connection and the cursor has already been closed
        
        
        Example - async composie root
        -----------------------------
        
        .. code:: python
        
            from baluster import Holder
        
            class AsyncApplicationRoot(Holder):
        
                @Holder.factory
                async def resource(self, root):
                    # Will be called at the first use
                    # Will be cached so won't be called again
                    return await some_aync_resource()
        
                @db.close
                async def _close_resource(self, root, resource):
                    await resource.close()
        
        
            def main():
                approot = AsyncApplicationRoot()
                async with approot:
                    conn = await approot.resource
                    await conn.operation(...)
        
                # at this point the resource has already been closed
        
        
        Example - fixture factory for tests
        -----------------------------------
        
        .. code:: python
        
            from baluster import Holder
            import psycopg2
        
            class Fixtures(Holder):
        
                @Holder.factory
                def cr(self, root):
                    conn = psycopg2.connect("dbname=test user=postgres")
                    return conn.cursor()
        
                class users(Holder):
        
                    @Holder.factory
                    def user(self, root):
                        root.cr.execute('SELECT * FROM user WHERE id=1')
                        return User(root.cr.fetchone())
        
                    @Holder.factory
                    def customer(self, root):
                        root.cr.execute('SELECT * FROM customer WHERE id=1')
                        return Customer(root.cr.fetchone())
        
                class orders(Holder):
        
                    @Holder.factory
                    def amount(self, root):
                        return 100
        
                    @Holder.factory
                    def quantity(self, root):
                        return 1
        
                    @Holder.factory
                    def order(self, root):
                        customer = root.users.customer
                        created_by = root.users.user
                        amount = self.amount
                        # Fictive order object...
                        return Order(
                            customer=customer, created_by=created_by,
                            amount=amount, quantity=quantity
                        )
        
                    @Holder.factory
                    def shipped_order(self, root):
                        order = self.order
                        order.mark_shipped()
                        return order
        
        
            def test_order():
                # Demonstrate a few use fictive usecase
        
                # Creating order with defaults
                f = Fixtures()
                assert f.order.calculated_total_value == 100
                assert f.order.shipping_address == f.users.customer.address
        
                # Create new fixtures, but keep some cached data
                f2 = f.copy('cr', 'users')
        
                # Set some value
                f2.order.amount = 50
                f2.order.quantity = 3
                assert f2.order.calculated_total_value == 150
        
                # Manage different stage of object life
                f3 = f.copy('cr', 'users')
                order = f3.shipped_order
        
                with pytest.raises(OrderException):
                    order.cancel()
                    # as it is shipped
        
        
        Installation
        ------------
        
        Python target: >=3.6
        
        .. code::
        
            $ pip install baluster
        
        Dependencies
        ------------
        
        The package is independent, using only the python standard library.
        
        
        Development
        -----------
        
        .. code::
        
           pip install -r requirements-dev.txt
        
        This installs the package in development mode (`setup.py develop`)
        and the testing packages.
        I would like to achive nearly 100% test coverage.
        
        
        Contribution
        ------------
        
        I really welcome any comments!
        I would be happy if you fork my code and create pull requests.
        For an approved pull request flake8 have to pass just as all of tests.
        
Keywords: context,context manager,async
Platform: UNKNOWN
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Natural Language :: English
Classifier: Programming Language :: Python :: 3.6
Classifier: Operating System :: OS Independent
Requires-Python: >=3.6
