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 165
|
from datetime import datetime, date, timedelta
from decimal import Decimal
import threading
from django.core.exceptions import ImproperlyConfigured
try:
from django.utils.timezone import now
except ImportError:
now = datetime.now
try:
from django.contrib.gis.geos import *
except ImproperlyConfigured:
pass # environment without geo libs
except Exception:
pass # Avoid errors like GDALException
from django_dynamic_fixture.fixture_algorithms.default_fixture import BaseDataFixture, GeoDjangoFixtureMixin, PostgresFixtureMixin
from django_dynamic_fixture.django_helper import field_is_unique
class AutoDataFiller:
"""
Responsibility: generate a unique and sequential value for each key.
"""
def __init__(self):
self.__data_controller_map = {} # key => counter
self.__locks = {} # key => lock
# synchronized by key
def next(self, key):
if key not in self.__data_controller_map:
self.__data_controller_map[key] = 0
self.__locks[key] = threading.RLock()
self.__locks[key].acquire()
self.__data_controller_map[key] += 1
value = self.__data_controller_map[key]
self.__locks[key].release()
return value
def current(self, key):
if key not in self.__data_controller_map:
self.next(key)
return self.__data_controller_map[key]
class SequentialDataFixture(BaseDataFixture, GeoDjangoFixtureMixin, PostgresFixtureMixin):
def __init__(self):
super().__init__()
self.filler = AutoDataFiller()
def get_value(self, field, key):
return self.filler.next(key)
# NUMBERS
def integerfield_config(self, field, key):
return self.get_value(field, key)
def smallintegerfield_config(self, field, key):
return self.integerfield_config(field, key)
def positiveintegerfield_config(self, field, key):
return self.integerfield_config(field, key)
def positivesmallintegerfield_config(self, field, key):
return self.integerfield_config(field, key)
def bigintegerfield_config(self, field, key):
return self.integerfield_config(field, key)
def floatfield_config(self, field, key):
return float(self.get_value(field, key))
def decimalfield_config(self, field, key):
data = self.get_value(field, key)
number_of_digits = field.max_digits - field.decimal_places
max_value = 10 ** number_of_digits
data = data % max_value
return Decimal(str(data))
# STRINGS
def charfield_config(self, field, key):
data = self.get_value(field, key)
if field.max_length:
max_value = (10 ** field.max_length) - 1
data = str(data % max_value)
data = data[:field.max_length]
else:
data = str(data)
return data
def textfield_config(self, field, key):
return self.charfield_config(field, key)
def slugfield_config(self, field, key):
return self.charfield_config(field, key)
def commaseparatedintegerfield_config(self, field, key):
return self.charfield_config(field, key)
# BOOLEAN
def booleanfield_config(self, field, key):
return False
def nullbooleanfield_config(self, field, key):
return None
# DATE/TIME RELATED
def datefield_config(self, field, key):
data = self.get_value(field, key)
return date.today() - timedelta(days=data)
def timefield_config(self, field, key):
data = self.get_value(field, key)
return (now() - timedelta(seconds=data)).time()
def datetimefield_config(self, field, key):
data = self.get_value(field, key)
return now() - timedelta(seconds=data)
# FORMATTED STRINGS
def emailfield_config(self, field, key):
return f'a{self.get_value(field, key)}@dynamicfixture.com'
def urlfield_config(self, field, key):
return f'http://dynamicfixture{self.get_value(field, key)}.com'
# Deprecated in Django >= 1.7
def ipaddressfield_config(self, field, key):
# TODO: better workaround (this suppose ip field is not unique)
data = self.get_value(field, key)
a = '1'
b = '1'
c = '1'
d = data % 256
return f'{a}.{b}.{c}.{d}'
def xmlfield_config(self, field, key):
return f'<a>{self.get_value(field, key)}</a>'
# FILES
def filepathfield_config(self, field, key):
return str(self.get_value(field, key))
def filefield_config(self, field, key):
return str(self.get_value(field, key))
def imagefield_config(self, field, key):
return str(self.get_value(field, key))
class GlobalSequentialDataFixture(SequentialDataFixture):
def get_value(self, field, key):
return self.filler.next('ddf-global-key')
class StaticSequentialDataFixture(SequentialDataFixture):
def get_value(self, field, key):
if field_is_unique(field):
return self.filler.next(key)
else:
return self.filler.current(key)
|