skip to navigation
skip to content

calve_machine 0.1.0

Factories for plain old Python objects.

Downloads ↓

Factories for plain old Python objects.

Basic Usage

A simple example:

>>> from should_dsl import should, should_not
>>> from calve_machine import inseminate, pregnant

>>> @inseminate
... def programmer(p):
...     p.name = 'Sheldon Cooper, Ph.D.'
...     p.age = 29
...     p.languages = ['eiffel', 'io', 'erlang']

>>> prog = pregnant.calve('programmer')
>>> prog.name |should| equal_to('Sheldon Cooper, Ph.D.')
>>> prog.age |should| be(29)
>>> prog.languages |should| equal_to(['eiffel', 'io', 'erlang'])

Inheritance

Factories can inherit from other(s):

>>> @inseminate
... def programmer(p):
...     p.name = 'Sheldon Cooper, Ph.D.'
...     p.age = 29
...     p.languages = ['eiffel', 'io', 'erlang']

>>> @inseminate(seed_from='programmer')
... def python_programmer(p):
...     p.languages = ['python']
...     p.foo = 'spam'

>>> prog = pregnant.calve('python_programmer')
>>> prog.name |should| equal_to('Sheldon Cooper, Ph.D.')
>>> prog.age |should| be(29)
>>> prog.languages |should| equal_to(['python'])
>>> prog.foo |should| equal_to('spam')

>>> @inseminate(seed_from='python_programmer')
... def zope_programmer(p):
...     p.languages = ['zcml']
...     p.age = 30

>>> prog = pregnant.calve('zope_programmer')
>>> prog.name |should| equal_to('Sheldon Cooper, Ph.D.')
>>> prog.age |should| be(30)
>>> prog.languages |should| equal_to(['zcml'])
>>> prog.foo |should| equal_to('spam')

Sequences

Factories can generate sequences:

>>> from calve_machine import sequence

>>> @inseminate
... def id_holder(i):
...     i.name = sequence(lambda n: "Crazy Guy %s" %n)
...     i.square_id = sequence(lambda n: n ** 2)

>>> obj = pregnant.calve('id_holder')
>>> obj.name |should| equal_to("Crazy Guy 1")
>>> obj.square_id |should| be(1)

>>> obj = pregnant.calve('id_holder')
>>> obj.name |should| equal_to("Crazy Guy 2")
>>> obj.square_id |should| be(4)

>>> obj = pregnant.calve('id_holder')
>>> obj.name |should| equal_to("Crazy Guy 3")
>>> obj.square_id |should| be(9)

Templating

Objects can be generated using an existing object as template. Given an object:

>>> class Spam(object):
...     def __init__(self, eggs):
...         self.eggs = eggs
...     def fried(self):
...         return self.eggs + ' w/ cholesterol'

>>> spam = Spam("Guava")
>>> guava_prog = pregnant.calve('programmer', template=spam)

Everything from "programmer" act as expected:

>>> guava_prog.name |should| equal_to('Sheldon Cooper, Ph.D.')
>>> guava_prog.age |should| be(29)
>>> guava_prog.languages |should| equal_to(['eiffel', 'io', 'erlang'])

All members from the template object are present:

>>> guava_prog.eggs |should| equal_to('Guava')
>>> guava_prog.fried() |should| equal_to('Guava w/ cholesterol')

The class of newborn object is the same class of the template object:

>>> guava_prog |should| be_instance_of(Spam)

Template object remains untouched:

>>> spam |should_not| respond_to('name')
>>> spam |should_not| respond_to('age')
>>> spam |should_not| respond_to('languages')

Classes as templates

Templates can be classes, not only objects:

>>> class Person:
...     def __init__(self):
...         self.city = 'Campos dos Goytacazes/RJ/Brazil'

>>> prog = pregnant.calve('programmer', template=Person)

Everything from "programmer" act as expected:

>>> prog.name |should| equal_to('Sheldon Cooper, Ph.D.')
>>> prog.age |should| be(29)
>>> prog.languages |should| equal_to(['eiffel', 'io', 'erlang'])

All members from the template class are present:

>>> prog.city |should| equal_to('Campos dos Goytacazes/RJ/Brazil')

The class of newborn object is the same class of the template object:

>>> prog |should| be_instance_of(Person)

If a class have required init parameters:

>>> class User:
...     def __init__(self, email, password):
...         self.email, self.password = email, password

you can use the method init() for defining the constructor parameters:

>>> @inseminate
... def parameterized_programmer(u):
...     u.init('admin@admin.com', 's3cr3t')
...     u.name = 'Sheldon Cooper'

>>> prog = pregnant.calve('parameterized_programmer', template=User)
>>> prog.email |should| equal_to('admin@admin.com')
>>> prog.password |should| equal_to('s3cr3t')
>>> prog.name |should| equal_to('Sheldon Cooper')

Parameters for the constructor are ignored for a class without constructor parameters:

>>> prog = pregnant.calve('parameterized_programmer', template=Person)

Association

calve_machine supports object associations:

>>> from calve_machine import association

>>> @inseminate
... def customer(c):
...     c.name = 'Someone'

>>> @inseminate
... def order(o):
...     o.owner = association('customer')

>>> an_order = pregnant.calve('order')
>>> an_order.owner.name |should| equal_to('Someone')

If the field name equals to the seed name, there's no need to specify the seed name:

>>> @inseminate
... def order(o):
...     o.customer = association()

>>> an_order = pregnant.calve('order')
>>> an_order.customer.name |should| equal_to('Someone')

After build

Arbitrary code can be defined to run over the created object:

>>> class User(object):
...    def __init__(self):
...        self.authorized = False
...    def authorize(self):
...        self.authorized = True

>>> @inseminate
... def user(u):
...     u.email = 'admin@admin.com'
...     u.password = 'adm!npassword'
...     u.after_build(lambda user: user.authorize())

>>> user = pregnant.calve('user', template=User())
>>> user |should| be_authorized

How to install

For the latest release, run:

pip install calve_machine

You can also install the current development version directly from Github:

pip install -e git+https://github.com/rodrigomanhaes/calve_machine.git#egg=calve_machine

How to run tests

Just run:

make test

for install all test dependencies (Should-DSL and Specloud, at the moment) and run the tests. calve_machine itself has no dependencies.

Ideas

calve_machine is freely inspired by factory_girl.

 
File Type Py Version Uploaded on Size # downloads
calve_machine-0.1.0.tar.gz (md5) Source 2011-08-30 6KB 229