Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

python-testdata

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

python-testdata - pypi Package Compare versions

Comparing version
1.0.3
to
1.0.5
+80
testdata/childrentree.py
from collections import defaultdict
from .errors import UnmetDependentFields
from .base import Factory, DependentField
class ChildrenTree(object):
def __init__(self):
self._tree = defaultdict(dict)
def load_bases(self, bases):
ChildrenTree._fuse_tree(self._tree, ChildrenTree._load_bases(bases))
@staticmethod
def _load_bases(bases):
all_tree = ChildrenTree()
for base in bases:
if Factory == base: # means we reached the DictFactory cls
return ChildrenTree()
current_tree = base._child_factory_tree + ChildrenTree._load_bases(base.__bases__)
all_tree += current_tree
return all_tree
@staticmethod
def _fuse_tree(a, b):
for key in b.keys():
a[key].update(b[key])
def __add__(self, other):
new_tree = self._tree.copy()
ChildrenTree._fuse_tree(new_tree, other._tree)
new_children_tree = ChildrenTree()
new_children_tree._tree = new_tree
return new_children_tree
def __iadd__(self, o):
ChildrenTree._fuse_tree(self._tree, o._tree)
return self
def __repr__(self):
return '{}'.format(repr(self._tree))
def keys(self):
return self._tree.keys()
def __getitem__(self, key):
return self._tree.__getitem__(key)
def update(self, factories_dct):
dependent_factories = {}
for key, value in factories_dct.iteritems():
if issubclass(type(value), DependentField):
dependent_factories[key] = value
continue
if issubclass(type(value), Factory):
self._tree[0][key] = value
self._build_dependency_tree(dependent_factories)
def _build_dependency_tree(self, dependent_factories):
leftover_factories = set(dependent_factories.keys())
unplaced_fields = set()
while leftover_factories:
unplaced_fields = self._build_tree(leftover_factories, dependent_factories)
if unplaced_fields == leftover_factories: # means that no placement has happened!
raise UnmetDependentFields("The fields: {} - depend on fields that aren't defined!".format(unplaced_fields))
leftover_factories = unplaced_fields
def _build_tree(self, leftover_factory_names, all_dependent_factories):
unplaced_fields = set([])
for factory_name in leftover_factory_names:
needed_factories = set(all_dependent_factories[factory_name].depending_field_names) # we need to know which fields are needed
for generation in sorted(self._tree.keys()): # will give the available generations
needed_factories -= set(self._tree[generation].keys()) # the factory names available in this generation
if not needed_factories:
break
if needed_factories: # if after traversing the generations, we didn't find all the dependencies, we save this for later
unplaced_fields.add(factory_name)
else:
self._tree[generation + 1][factory_name] = all_dependent_factories[factory_name]
return unplaced_fields
+29
-4
Metadata-Version: 1.1
Name: python-testdata
Version: 1.0.3
Version: 1.0.5
Summary: A small package that helps generate content to fill databases for tests.

@@ -98,5 +98,5 @@ Home-page: http://github.com/arieb/python-testdata

We also have factories that allow us to generate different data distributed by different percentage, for example,
lets say we want to create an 'Job', that will have an assigned user field, a state field and a description field.
we want the state to be 'pending' in 90% of dictionaries and 'error' the rest of the time. In addition, we want that if the 'state' field is
'error' the assigned user will be 'support', else it should be 'admin'.
lets say we want to create a 'Job', that will have an assigned user field, a state field and a description field.
We want the state to be 'pending' in 90% of dictionaries and 'error' in the rest of them. In addition, we want that if the 'state' field is
'error' the assigned user will be 'support', or else it should be 'admin'.

@@ -123,2 +123,26 @@ ```python

In version 1.0.5 we extended the DictFactory to support passing additional factories, or overriding existing factories, for a specific instance.
Lets take for example our 'User' example from the begining.
```python
import testdata
class Users(testdata.DictFactory):
id = testdata.CountingFactory(10)
firstname = testdata.FakeDataFactory('firstName')
lastname = testdata.FakeDataFactory('lastName')
address = testdata.FakeDataFactory('address')
age = testdata.RandomInteger(10, 30)
gender = testdata.RandomSelection(['female', 'male'])
```
But lets override it so the 'firstname' always returns John, and make the age be a random integer between 40 and 60 and add an 'email' field.
```python
for user in Users(firstname=testdata.Constant('John'), age=testdata.RandomInteger(40, 60), email=testdata.FakeDataFactory('email')).generate(10): # let say we only want 10 users
print user
#{'firstname': 'John', 'gender': 'male', 'age': 54, 'email': 'hazle.wehner@brekke.com', 'lastname': 'Willms', 'address': '245 Pfeffer Light Apt. 309\nEast Audieside, IN 11931', 'id': 10}
#{'firstname': 'John', 'gender': 'male', 'age': 47, 'email': 'mariam25@gmail.com', 'lastname': 'Ratke', 'address': '98710 Freddy Gateway\nDelilahborough, GU 50849', 'id': 11}
#{'firstname': 'John', 'gender': 'male', 'age': 55, 'email': 'tyler22@yahoo.com', 'lastname': 'Cormier', 'address': '432 Block Locks Apt. 547\nNew Estel, NJ 54026', 'id': 12}
# or more likely you'd want to insert them into your favorite database (MongoDB, ElasticSearch, ..)
```
## Factories

@@ -134,2 +158,3 @@ See the Factorie's Docstrings for more examples and doctests.

| Callable | Gets a callable object as an argument and returns the result of calling the object on every iteration |
| DependentCallable | Gets a callable object as an argument and returns the result of calling the object passing the defined fields as arguments on every iteration |
| ClonedField | A factory that copies the value of another factory. |

@@ -136,0 +161,0 @@ #### Dates

Metadata-Version: 1.1
Name: python-testdata
Version: 1.0.3
Version: 1.0.5
Summary: A small package that helps generate content to fill databases for tests.

@@ -98,5 +98,5 @@ Home-page: http://github.com/arieb/python-testdata

We also have factories that allow us to generate different data distributed by different percentage, for example,
lets say we want to create an 'Job', that will have an assigned user field, a state field and a description field.
we want the state to be 'pending' in 90% of dictionaries and 'error' the rest of the time. In addition, we want that if the 'state' field is
'error' the assigned user will be 'support', else it should be 'admin'.
lets say we want to create a 'Job', that will have an assigned user field, a state field and a description field.
We want the state to be 'pending' in 90% of dictionaries and 'error' in the rest of them. In addition, we want that if the 'state' field is
'error' the assigned user will be 'support', or else it should be 'admin'.

@@ -123,2 +123,26 @@ ```python

In version 1.0.5 we extended the DictFactory to support passing additional factories, or overriding existing factories, for a specific instance.
Lets take for example our 'User' example from the begining.
```python
import testdata
class Users(testdata.DictFactory):
id = testdata.CountingFactory(10)
firstname = testdata.FakeDataFactory('firstName')
lastname = testdata.FakeDataFactory('lastName')
address = testdata.FakeDataFactory('address')
age = testdata.RandomInteger(10, 30)
gender = testdata.RandomSelection(['female', 'male'])
```
But lets override it so the 'firstname' always returns John, and make the age be a random integer between 40 and 60 and add an 'email' field.
```python
for user in Users(firstname=testdata.Constant('John'), age=testdata.RandomInteger(40, 60), email=testdata.FakeDataFactory('email')).generate(10): # let say we only want 10 users
print user
#{'firstname': 'John', 'gender': 'male', 'age': 54, 'email': 'hazle.wehner@brekke.com', 'lastname': 'Willms', 'address': '245 Pfeffer Light Apt. 309\nEast Audieside, IN 11931', 'id': 10}
#{'firstname': 'John', 'gender': 'male', 'age': 47, 'email': 'mariam25@gmail.com', 'lastname': 'Ratke', 'address': '98710 Freddy Gateway\nDelilahborough, GU 50849', 'id': 11}
#{'firstname': 'John', 'gender': 'male', 'age': 55, 'email': 'tyler22@yahoo.com', 'lastname': 'Cormier', 'address': '432 Block Locks Apt. 547\nNew Estel, NJ 54026', 'id': 12}
# or more likely you'd want to insert them into your favorite database (MongoDB, ElasticSearch, ..)
```
## Factories

@@ -134,2 +158,3 @@ See the Factorie's Docstrings for more examples and doctests.

| Callable | Gets a callable object as an argument and returns the result of calling the object on every iteration |
| DependentCallable | Gets a callable object as an argument and returns the result of calling the object passing the defined fields as arguments on every iteration |
| ClonedField | A factory that copies the value of another factory. |

@@ -136,0 +161,0 @@ #### Dates

@@ -12,2 +12,3 @@ MANIFEST.in

testdata/base.py
testdata/childrentree.py
testdata/dictionary.py

@@ -14,0 +15,0 @@ testdata/errors.py

@@ -90,5 +90,5 @@ python-testdata

We also have factories that allow us to generate different data distributed by different percentage, for example,
lets say we want to create an 'Job', that will have an assigned user field, a state field and a description field.
we want the state to be 'pending' in 90% of dictionaries and 'error' the rest of the time. In addition, we want that if the 'state' field is
'error' the assigned user will be 'support', else it should be 'admin'.
lets say we want to create a 'Job', that will have an assigned user field, a state field and a description field.
We want the state to be 'pending' in 90% of dictionaries and 'error' in the rest of them. In addition, we want that if the 'state' field is
'error' the assigned user will be 'support', or else it should be 'admin'.

@@ -115,2 +115,26 @@ ```python

In version 1.0.5 we extended the DictFactory to support passing additional factories, or overriding existing factories, for a specific instance.
Lets take for example our 'User' example from the begining.
```python
import testdata
class Users(testdata.DictFactory):
id = testdata.CountingFactory(10)
firstname = testdata.FakeDataFactory('firstName')
lastname = testdata.FakeDataFactory('lastName')
address = testdata.FakeDataFactory('address')
age = testdata.RandomInteger(10, 30)
gender = testdata.RandomSelection(['female', 'male'])
```
But lets override it so the 'firstname' always returns John, and make the age be a random integer between 40 and 60 and add an 'email' field.
```python
for user in Users(firstname=testdata.Constant('John'), age=testdata.RandomInteger(40, 60), email=testdata.FakeDataFactory('email')).generate(10): # let say we only want 10 users
print user
#{'firstname': 'John', 'gender': 'male', 'age': 54, 'email': 'hazle.wehner@brekke.com', 'lastname': 'Willms', 'address': '245 Pfeffer Light Apt. 309\nEast Audieside, IN 11931', 'id': 10}
#{'firstname': 'John', 'gender': 'male', 'age': 47, 'email': 'mariam25@gmail.com', 'lastname': 'Ratke', 'address': '98710 Freddy Gateway\nDelilahborough, GU 50849', 'id': 11}
#{'firstname': 'John', 'gender': 'male', 'age': 55, 'email': 'tyler22@yahoo.com', 'lastname': 'Cormier', 'address': '432 Block Locks Apt. 547\nNew Estel, NJ 54026', 'id': 12}
# or more likely you'd want to insert them into your favorite database (MongoDB, ElasticSearch, ..)
```
## Factories

@@ -126,2 +150,3 @@ See the Factorie's Docstrings for more examples and doctests.

| Callable | Gets a callable object as an argument and returns the result of calling the object on every iteration |
| DependentCallable | Gets a callable object as an argument and returns the result of calling the object passing the defined fields as arguments on every iteration |
| ClonedField | A factory that copies the value of another factory. |

@@ -128,0 +153,0 @@ #### Dates

@@ -145,2 +145,34 @@ from copy import deepcopy

class DependentCallable(DependentField):
"""
Allows us to call a callable object (like a function), and pass it
other fields as parameters.
:param callable_obj: the object to __call__() on each iteration
:param fields: a list of fields that their values should be passed as parameters on each call.
Example,
>>> import testdata
>>> def sum_fields(x, y):
... return x + y
>>> class A(testdata.DictFactory):
... x = testdata.CountingFactory(100)
... y = testdata.CountingFactory(1)
... sum = DependentCallable(sum_fields, ['x', 'y'])
>>> 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
"""
def __init__(self, callable_obj, fields=[]):
super(DependentCallable, self).__init__(fields)
self._callable_obj = callable_obj
self._fields = fields
def __call__(self):
super(DependentCallable, self).__call__()
return self._callable_obj(**self.depending_fields)
class ClonedField(DependentField):

@@ -147,0 +179,0 @@ """

+4
-3

@@ -1,2 +0,2 @@

from copy import deepcopy
from copy import deepcopy, copy
from .base import Factory

@@ -25,5 +25,6 @@ from .metaclasses import DictFactoryBuilder

def __init__(self):
def __init__(self, **factories):
super(DictFactory, self).__init__()
self._child_factories = deepcopy(self._child_factory_tree)
self._child_factories.update(factories)
self._oldest_generation = max(self._child_factories.keys())

@@ -36,3 +37,3 @@

def _iter_child_factories(self):
child_factories = self._child_factories.copy()
child_factories = copy(self._child_factories)
for generation in child_factories.keys():

@@ -39,0 +40,0 @@ for key in child_factories[generation].keys():

@@ -8,4 +8,3 @@ class TestDataError(Exception): pass

class UnmetDependentFields(TestDataError): pass
class NoFactoriesDefined(TestDataError): pass
class NoFactoriesProvided(TestDataError): pass
class InvalidTotalPrecentage(TestDataError): pass

@@ -1,6 +0,4 @@

from collections import defaultdict
from .errors import UnmetDependentFields, NoFactoriesDefined
from .base import Factory
from .childrentree import ChildrenTree
from .base import Factory, DependentField
class DictFactoryBuilder(type):

@@ -11,7 +9,5 @@ """

def __new__(meta, name, bases, dct):
if name == "DictFactory": # we only modify the children of DictFactory, not the DictFactory itself
return super(DictFactoryBuilder, meta).__new__(meta, name, bases, dct)
_child_factory_tree = DictFactoryBuilder._collect_bases_children_trees(bases)
DictFactoryBuilder._build_children_tree(_child_factory_tree, dct)
_child_factory_tree = ChildrenTree()
_child_factory_tree.load_bases(bases)
_child_factory_tree.update(dct)
DictFactoryBuilder._clean_factories(dct)

@@ -22,20 +18,2 @@ dct["_child_factory_tree"] = _child_factory_tree

@staticmethod
def _collect_bases_children_trees(bases):
all_tree = defaultdict(dict)
for base in bases:
if Factory in base.__bases__: # means we reached the DictFactory cls
return defaultdict(dict)
current_tree = DictFactoryBuilder._fuse_child_trees(
base._child_factory_tree,
DictFactoryBuilder._collect_bases_children_trees(base.__bases__))
DictFactoryBuilder._fuse_child_trees(all_tree, current_tree)
return all_tree
@staticmethod
def _fuse_child_trees(p,q):
for key in q.keys():
p[key].update(q[key])
return p
@staticmethod
def _clean_factories(dct):

@@ -47,41 +25,2 @@ """

if issubclass(type(dct[key]), Factory):
del dct[key]
@staticmethod
def _build_children_tree(child_tree, dct):
dependent_factories = {}
for key, value in dct.iteritems():
if issubclass(type(value), DependentField):
dependent_factories[key] = value
continue
if issubclass(type(value), Factory):
child_tree[0][key] = value
if not child_tree:
raise NoFactoriesDefined("DictFactory needs to contain at least one Factory")
DictFactoryBuilder._build_dependency_tree(child_tree, dependent_factories)
@staticmethod
def _build_dependency_tree(child_tree, dependent_factories):
leftover_factories = set(dependent_factories.keys())
unplaced_fields = set()
while leftover_factories:
unplaced_fields = DictFactoryBuilder._build_tree(child_tree, leftover_factories, dependent_factories)
if unplaced_fields == leftover_factories: # means that no placement has happened!
raise UnmetDependentFields("The fields: {} - depend on fields that aren't defined!".format(unplaced_fields))
leftover_factories = unplaced_fields
@staticmethod
def _build_tree(child_tree, leftover_factory_names, all_dependent_factories):
unplaced_fields = set([])
for factory_name in leftover_factory_names:
needed_factories = set(all_dependent_factories[factory_name].depending_field_names) # we need to know which fields are needed
for generation in sorted(child_tree.keys()): # will give the available generations
needed_factories -= set(child_tree[generation].keys()) # the factory names available in this generation
if not needed_factories:
break
if needed_factories: # if after traversing the generations, we didn't find all the dependencies, we save this for later
unplaced_fields.add(factory_name)
else:
child_tree[generation + 1][factory_name] = all_dependent_factories[factory_name]
return unplaced_fields
dct.pop(key)

@@ -1,1 +0,1 @@

1.0.3
1.0.5