Skip to main content

Provides hierarchical factory

Project description

https://travis-ci.org/palankai/baluster.svg?branch=master

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

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

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

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

$ pip install baluster

Dependencies

The package is independent, using only the python standard library.

Development

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

Baluster-0.1.tar.gz (5.3 kB view details)

Uploaded Source

File details

Details for the file Baluster-0.1.tar.gz.

File metadata

  • Download URL: Baluster-0.1.tar.gz
  • Upload date:
  • Size: 5.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for Baluster-0.1.tar.gz
Algorithm Hash digest
SHA256 8bb81d4c503023dfb2e9cfa9f230a0cd61854d4488004e0205210d01431298e1
MD5 effdb00c0764b9d826a6abd5a1a72e3c
BLAKE2b-256 bcfa7be8565a13457fcb62ba0e24f8f3fa3e5b959e6b506d75571c9a239b5d41

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page