/usr/lib/python2.7/dist-packages/model_mommy/recipe.py is in python-model-mommy 1.5.1-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | #coding: utf-8
from functools import wraps
import inspect
import itertools
from . import mommy
from .timezone import tz_aware
from .exceptions import RecipeNotFound, RecipeIteratorEmpty
from six import string_types
import datetime
# Python 2.6.x compatibility code
itertools_count = itertools.count
try:
itertools_count(0, 1)
except TypeError:
def count(start=0, step=1):
n = start
while True:
yield n
n += step
itertools_count = count
finder = mommy.ModelFinder()
class Recipe(object):
def __init__(self, _model, **attrs):
self.attr_mapping = attrs
self._model = _model
# _iterator_backups will hold values of the form (backup_iterator, usable_iterator).
self._iterator_backups = {}
def _mapping(self, new_attrs):
_save_related = new_attrs.get('_save_related', True)
rel_fields_attrs = dict((k, v) for k, v in new_attrs.items() if '__' in k)
new_attrs = dict((k, v) for k, v in new_attrs.items() if not '__' in k)
mapping = self.attr_mapping.copy()
for k, v in self.attr_mapping.items():
# do not generate values if field value is provided
if new_attrs.get(k):
continue
elif mommy.is_iterator(v):
if isinstance(self._model, string_types):
m = finder.get_model(self._model)
else:
m = self._model
if k not in self._iterator_backups or m.objects.count() == 0:
self._iterator_backups[k] = itertools.tee(self._iterator_backups.get(k, [v])[0])
mapping[k] = self._iterator_backups[k][1]
elif isinstance(v, RecipeForeignKey):
a={}
for key, value in list(rel_fields_attrs.items()):
if key.startswith('%s__' % k):
a[key] = rel_fields_attrs.pop(key)
recipe_attrs = mommy.filter_rel_attrs(k, **a)
if _save_related:
mapping[k] = v.recipe.make(**recipe_attrs)
else:
mapping[k] = v.recipe.prepare(**recipe_attrs)
elif isinstance(v, related):
mapping[k] = v.make()
mapping.update(new_attrs)
mapping.update(rel_fields_attrs)
return mapping
def make(self, **attrs):
return mommy.make(self._model, **self._mapping(attrs))
def prepare(self, **attrs):
defaults = {'_save_related': False}
defaults.update(attrs)
return mommy.prepare(self._model, **self._mapping(defaults))
def extend(self, **attrs):
attr_mapping = self.attr_mapping.copy()
attr_mapping.update(attrs)
return Recipe(self._model, **attr_mapping)
class RecipeForeignKey(object):
def __init__(self, recipe):
if isinstance(recipe, Recipe):
self.recipe = recipe
elif isinstance(recipe, string_types):
frame = inspect.stack()[2]
caller_module = inspect.getmodule(frame[0])
recipe = getattr(caller_module, recipe)
if recipe:
self.recipe = recipe
else:
raise RecipeNotFound
else:
raise TypeError('Not a recipe')
def foreign_key(recipe):
"""
Returns the callable, so that the associated _model
will not be created during the recipe definition.
"""
return RecipeForeignKey(recipe)
def _total_secs(td):
"""
python 2.6 compatible timedelta total seconds calculation
backport from
https://docs.python.org/2.7/library/datetime.html#datetime.timedelta.total_seconds
"""
if hasattr(td, 'total_seconds'):
return td.total_seconds()
else:
#py26
return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10.0**6
def seq(value, increment_by=1):
if type(value) in [datetime.datetime, datetime.date, datetime.time]:
if type(value) is datetime.date:
date = datetime.datetime.combine(value, datetime.datetime.now().time())
elif type(value) is datetime.time:
date = datetime.datetime.combine(datetime.date.today(), value)
else:
date = value
# convert to epoch time
start = _total_secs((date - datetime.datetime(1970, 1, 1)))
increment_by = _total_secs(increment_by)
for n in itertools_count(increment_by, increment_by):
series_date = tz_aware(datetime.datetime.utcfromtimestamp(start + n))
if type(value) is datetime.time:
yield series_date.time()
elif type(value) is datetime.date:
yield series_date.date()
else:
yield series_date
else:
for n in itertools_count(increment_by, increment_by):
yield value + type(value)(n)
class related(object):
def __init__(self, *args):
self.related = []
for recipe in args:
if isinstance(recipe, Recipe):
self.related.append(recipe)
elif isinstance(recipe, string_types):
frame = inspect.stack()[1]
caller_module = inspect.getmodule(frame[0])
recipe = getattr(caller_module, recipe)
if recipe:
self.related.append(recipe)
else:
raise RecipeNotFound
else:
raise TypeError('Not a recipe')
def make(self):
"""
Persists objects to m2m relation
"""
return [m.make() for m in self.related]
|