Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 15 additions & 12 deletions testdata/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from copy import deepcopy
from .compat import implements_iterator
from .errors import MissingElementAmountValue, FactoryStartedAlready, MissingRequiredFields

@implements_iterator
class Factory(object):
"""
The base class of all the factories.
Expand All @@ -18,7 +20,7 @@ def __iter__(self):

return self

def next(self):
def __next__(self):
if self.current_index >= self.element_amount:
raise StopIteration

Expand Down Expand Up @@ -123,7 +125,7 @@ def set_element_amount(self, element_amount):
self._factory.set_element_amount(element_amount * self._elements_per_list)

def __call__(self):
return [self._factory.next() for i in xrange(self._elements_per_list)]
return [next(self._factory) for i in range(self._elements_per_list)]

class Callable(Factory):
"""
Expand Down Expand Up @@ -158,12 +160,11 @@ class DependentCallable(DependentField):
... x = testdata.CountingFactory(100)
... y = testdata.CountingFactory(1)
... sum = DependentCallable(sum_fields, ['x', 'y'])
>>> got = []
>>> for i in A().generate(4):
... print i['x'], i['y'], i['sum']
100 1 101
101 2 103
102 3 105
103 4 107
... got.append((i['x'], i['y'], i['sum']))
>>> got == [(100, 1, 101), (101, 2, 103), (102, 3, 105), (103, 4, 107)]
True
"""
def __init__(self, callable_obj, fields=[]):
super(DependentCallable, self).__init__(fields)
Expand All @@ -189,11 +190,13 @@ class ClonedField(DependentField):
>>> [result] = [i for i in Foo().generate(1)]
>>> result['id'] == result['cloned_id']
True
>>> class Bar(testdata.DictFactory):
... id = testdata.CountingFactory(0)
... cloned_id = ClonedField("_id")
Traceback (most recent call last):
UnmetDependentFields: The fields: set(['cloned_id']) - depend on fields that aren't defined!
>>> try:
... class Bar(testdata.DictFactory):
... id = testdata.CountingFactory(0)
... cloned_id = ClonedField("_id")
... raise AssertionError('not raise UnmetDependentFields')
... except testdata.errors.UnmetDependentFields:
... pass
"""
def __init__(self, cloned_field_name):
super(ClonedField, self).__init__([cloned_field_name])
Expand Down
2 changes: 1 addition & 1 deletion testdata/childrentree.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def __getitem__(self, key):

def update(self, factories_dct):
dependent_factories = {}
for key, value in factories_dct.iteritems():
for key, value in factories_dct.items():
if issubclass(type(value), DependentField):
dependent_factories[key] = value
continue
Expand Down
30 changes: 30 additions & 0 deletions testdata/compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import sys


PY2 = sys.version_info[0] == 2

if PY2:
def implements_iterator(cls):
cls.next = cls.__next__
del cls.__next__
return cls
else:
implements_iterator = lambda x: x


def with_metaclass(meta, *bases):
"""Create a class with a metaclass.

Source: http://lucumr.pocoo.org/2013/5/21/porting-to-python-3-redux/

"""

class metaclass(meta):
__call__ = type.__call__
__init__ = type.__init__

def __new__(cls, name, this_bases, d):
if this_bases is None:
return type.__new__(cls, name, (), d)
return meta(name, bases, d)
return metaclass('temporary_class', None, {})
18 changes: 9 additions & 9 deletions testdata/dictionary.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from copy import deepcopy, copy
from .base import Factory
from .metaclasses import DictFactoryBuilder
from .compat import with_metaclass

class DictFactory(Factory):
class DictFactory(with_metaclass(DictFactoryBuilder, Factory)):
"""
One of the most useful and basic factories.
This factory is meant to be subclassed, and other factories should be defined
Expand All @@ -17,10 +18,9 @@ class DictFactory(Factory):
... age = testdata.RandomInteger(10, 10)
... gender = testdata.RandomSelection(['male'])
>>> [result] = [i for i in Users().generate(1)]
>>> result
{'gender': 'male', 'age': 10, 'id': 10}
>>> result == {'id': 10, 'age': 10, 'gender': 'male'}
True
"""
__metaclass__ = DictFactoryBuilder

def __init__(self, **factories):
super(DictFactory, self).__init__()
Expand All @@ -43,13 +43,13 @@ def _get_oldest_generation(self):

def __call__(self):
result = {}
for factory_name, factory in self._child_factories[0].iteritems():
for factory_name, factory in self._child_factories[0].items():
result[factory_name] = factory()

# now we call all Factories subclassing the DependentField
for i in xrange(1, self._oldest_generation + 1):
for i in range(1, self._oldest_generation + 1):
generation_result = {}
for factory_name, factory in self._child_factories[i].iteritems():
for factory_name, factory in self._child_factories[i].items():
factory.update_depending(result)
generation_result[factory_name] = factory()

Expand All @@ -59,12 +59,12 @@ def __call__(self):

def increase_index(self):
super(DictFactory, self).increase_index()
for i in xrange(self._oldest_generation + 1):
for i in range(self._oldest_generation + 1):
for child_factory in self._child_factories[i].values():
child_factory.increase_index()

def set_element_amount(self, new_element_amount):
super(DictFactory, self).set_element_amount(new_element_amount)
for i in xrange(self._oldest_generation + 1):
for i in range(self._oldest_generation + 1):
for child_factory in self._child_factories[i].values():
child_factory.set_element_amount(new_element_amount)
2 changes: 1 addition & 1 deletion testdata/extra/mongodb.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
try:
import pymongo
except ImportError, import_err:
except ImportError as import_err:
raise ImportError("{}. in order to use the mongodb extra you must install pymongo (pip install pymongo)".format(str(import_err)))

from ..factories.sequences import RandomSelection
Expand Down
22 changes: 11 additions & 11 deletions testdata/factories/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ class Sum(Factory):
:param sum_func: The function that will be used for summing the factories' results.

A simple Example,
>>> from __future__ import print_function
>>> import testdata
>>> for i in testdata.Sum([testdata.CountingFactory(10, 5), testdata.CountingFactory(1, 1)]).generate(5):
... print i
... print(i)
11
17
23
Expand Down Expand Up @@ -94,7 +95,7 @@ def set_element_amount(self, element_amount):
self._factory.set_element_amount(element_amount * self._max_items)

def __call__(self):
return [self._factory.next() for i in xrange(random.randint(self._min_items, self._max_items))]
return [next(self._factory) for i in range(random.randint(self._min_items, self._max_items))]

class ConditionalValueField(DependentField):
"""
Expand All @@ -109,17 +110,16 @@ class ConditionalValueField(DependentField):
>>> class Bar(testdata.DictFactory):
... a = testdata.CountingFactory(0)
... b = ConditionalValueField('a', {0: 'a', 1: 'b', 2: 'c'}, -1)
>>> got = []
>>> for i in Bar().generate(3):
... print i
{'a': 0, 'b': 'a'}
{'a': 1, 'b': 'b'}
{'a': 2, 'b': 'c'}
... got.append(i)
>>> got == [{'a': 0, 'b': 'a'}, {'a': 1, 'b': 'b'}, {'a': 2, 'b': 'c'}]
True
>>> got = []
>>> for i in Bar().generate(4):
... print i
{'a': 0, 'b': 'a'}
{'a': 1, 'b': 'b'}
{'a': 2, 'b': 'c'}
{'a': 3, 'b': -1}
... got.append(i)
>>> got == [{'a': 0, 'b': 'a'}, {'a': 1, 'b': 'b'}, {'a': 2, 'b': 'c'}, {'a': 3, 'b': -1}]
True
"""
def __init__(self, other_field, possible_values, default_value):
super(ConditionalValueField, self).__init__([other_field])
Expand Down
4 changes: 2 additions & 2 deletions testdata/factories/numbers.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ class RelativeNumber(DependentField):
>>> class Foo(testdata.DictFactory):
... a = testdata.CountingFactory(1)
... b = RelativeNumber('a', 1)
>>> [i for i in Foo().generate(3)]
[{'a': 1, 'b': 2}, {'a': 2, 'b': 3}, {'a': 3, 'b': 4}]
>>> [i for i in Foo().generate(3)] == [{'a': 1, 'b': 2}, {'a': 2, 'b': 3}, {'a': 3, 'b': 4}]
True
"""
def __init__(self, other_number_field, delta):
super(RelativeNumber, self).__init__([other_number_field])
Expand Down
8 changes: 5 additions & 3 deletions testdata/factories/sequences.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ class CycleSequenceFactory(Factory):
all the items.

Example,
>>> from __future__ import print_function
>>> for i in CycleSequenceFactory([1, 2, 3]).generate(9):
... print i
... print(i)
1
2
3
Expand All @@ -33,12 +34,13 @@ class RandomSelection(Factory):
Randomly chooses an element for the give sequence.

Example,
>>> from __future__ import print_function
>>> possible_values = set([1, 2, 3])
>>> while possible_values:
... for i in RandomSelection([1, 2, 3]).generate(100):
... possible_values.discard(i)
>>> print possible_values
set([])
>>> possible_values == set()
True
"""
def __init__(self, sequence):
super(RandomSelection, self).__init__()
Expand Down
8 changes: 5 additions & 3 deletions testdata/factories/statistical.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ class StatisticalPercentageFactory(Factory):
2
>>> f.count('bar')
2
>>> f = [i for i in StatisticalPercentageFactory([(testdata.Constant('foo'), 50), (testdata.Constant('bar'), 20)]).generate(4)]
Traceback (most recent call last):
InvalidTotalPrecentage: Need a total of a 100 precent. got 70 instead
>>> try:
... f = [i for i in StatisticalPercentageFactory([(testdata.Constant('foo'), 50), (testdata.Constant('bar'), 20)]).generate(4)]
... raise AssesionError('InvalidTotalPercentage not raised')
... except InvalidTotalPrecentage:
... pass
"""
def __init__(self, factories):
super(StatisticalPercentageFactory, self).__init__()
Expand Down
4 changes: 2 additions & 2 deletions testdata/factories/strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def __init__(self, min_chars=None, max_chars=None, prefix=None, suffix=None):

def __call__(self):
length = random.randint(self._min_chars, self._max_chars)
random_string = [random.choice(string.ascii_letters) for i in xrange(length)]
random_string = [random.choice(string.ascii_letters) for i in range(length)]
random_string.insert(0, self._prefix)
random_string.append(self._suffix)

Expand Down Expand Up @@ -60,5 +60,5 @@ def __init__(self, hash_class):

def __call__(self):
length = random.randint(self._MIN_VALUE_LENGTH, self._MAX_VALUE_LENGTH)
random_string = ''.join([random.choice(string.ascii_letters) for i in xrange(length)])
random_string = ''.join([random.choice(string.ascii_letters) for i in range(length)])
return self._hash_class(random_string).hexdigest()
6 changes: 5 additions & 1 deletion testdata/metaclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ def _clean_factories(dct):
"""
After we create the children factory, we don't need it anymore
"""
keys = []
for key in dct.keys():
if issubclass(type(dct[key]), Factory):
dct.pop(key)
# avoid change dict in loop
keys.append(key)
for key in keys:
dct.pop(key)