Skip to main content
Donate to the Python Software Foundation or Purchase a PyCharm License to Benefit the PSF! Donate Now

Factories for plain old Python objects.

Project description

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.

Project details


Release history Release notifications

Download files

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

Filename, size & hash SHA256 hash help File type Python version Upload date
calve_machine-0.1.0.tar.gz (6.3 kB) Copy SHA256 hash SHA256 Source None

Supported by

Elastic Elastic Search Pingdom Pingdom Monitoring Google Google BigQuery Sentry Sentry Error logging AWS AWS Cloud computing DataDog DataDog Monitoring Fastly Fastly CDN SignalFx SignalFx Supporter DigiCert DigiCert EV certificate StatusPage StatusPage Status page