Skip to content
This repository has been archived by the owner on Sep 23, 2020. It is now read-only.
/ assemblage Public archive

A small Python framework for building objects in dependency-injection style.

License

Notifications You must be signed in to change notification settings

pmatiello/assemblage

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Assemblage

Assemblage is an object assembler for Python programs. It can produce instances of arbitrary classes, along which the required dependencies, effortlessly.

Installing

Assemblage can be installed by easy_install:

# easy_install assemblage

Producing an assembler

An assembler object, capable of instantiate registered types and and their dependencies, is easily produced:

import assemblage

assembler = assemblage.assembler()

Registering and instantiating types

Let lightbulb be a type defined as below:

class lightbulb(object):
    pass

The following line registers this type in the assembler object:

assembler.register(lightbulb)

And a instance of lightbulb is built by the following call:

assembler.provide(lightbulb)

Declaring dependencies

Types might have dependencies. Assemblage is capable of providing these dependencies by passing them to the type constructor.

Let bedroom be a type defined as below:

class car(object):

    def __init__(self, bed, wardrobe, lightbulb):
        self.bed = bed
        self.wardrobe = wardrobe
        self.lightbulb = lightbulb

Instances of bedroom require instances of the types bed, wardrobe and lightbulb. These requirements, therefore, must be expressed when the bedroom type is registered in the assembler:

assembler.register(bedroom, requires=[bed, wardrobe, lightbulb])

Instances of the required classes will be automatically provided when an instance of bedroom is requested:

assembler.provide(bedroom)

Using factories

Often, an usable object cannot be built by a simple constructor call. In cases like these, a factory method can be provided to instruct the assembler on how to build the desired type.

Let trash_can be a type as defined below:

class trash_can(object):

    def __init__(self):
        self.bag = None
    
    def set_plastic_bag(self, bag):
        self.bag = bag

The assembler can produce instances of the trash_can class, and automatically feed them instances of plastic_bag, through the usage of a factory method:

def make_trash_can(plastic_bag):
    trash = trash_can()
    bag = plastic_bag()
    trash.set_plastic_bag(bag)
    return trash

assembler.register(trash_can, depends=[plastic_bag], factory=make_trash_can)

Avoiding instance sharing

By default, the assembler will cache every object it produces. Then, when an instance of a type is requested, the assembler will return the previously cached instance of that type, if it exists.

It's possible to have a new instance produced at every provide call by registering the type as uncacheable:

assembler.register(plastic_bag, cacheable=False)

Scoping

It's possible to implement different scopes for the objects in an application by using different assembler objects. Still, it's convenient to have different assemblers sharing cached instances and construction rules.

Given an assembler, an child assembler can be produced:

child_assembler = parent_assembler.spawn_child()

The child assembler have access to all construction rules and cached instances present in the parent assembler.

About

A small Python framework for building objects in dependency-injection style.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages