Skip to main content
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 Baluster, placeholders
import psycopg2

class ApplicationRoot(Baluster):
    @placeholders.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()

    @placeholders.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 Baluster, placeholders

class AsyncApplicationRoot(Baluster):

    @placeholders.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 Baluster, placeholders
import psycopg2

class Fixtures(Baluster):

    @placeholders.factory
    def cr(self, root):
        conn = psycopg2.connect("dbname=test user=postgres")
        return conn.cursor()

    class users(Baluster):

        @placeholders.factory
        def user(self, root):
            root.cr.execute('SELECT * FROM user WHERE id=1')
            return User(root.cr.fetchone())

        @placeholders.factory
        def customer(self, root):
            root.cr.execute('SELECT * FROM customer WHERE id=1')
            return Customer(root.cr.fetchone())

    class orders(Baluster):

        @placeholders.factory
        def amount(self, root):
            return 100

        @placeholders.factory
        def quantity(self, root):
            return 1

        @placeholders.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
            )

        @placeholders.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.

Test

pytest

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.

Release files for Baluster 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for Baluster 0.2.1
File Size Uploaded
Baluster-0.2.1.tar.gz 8.9 kB Details

Release files / Baluster-0.2.1.tar.gz

Download URL Baluster-0.2.1.tar.gz
Size 8.9 kB
Tags Source
SHA-256 checksum
How to use checksums
5bbfee5bf113eb1c7285c4445bc9bf5de9b2e7e0595975423b062f6301971edd
BLAKE2b-256 checksum
How to use checksums
897ff25028e9b2ab6a830222562c826a19ac4906ddab82a2246b4b0e3f799632
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Release history Release notifications | RSS feed

This release

0.2.1 This release

1 release file

0.2

1 release file

0.1

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page