GeneralManager 0.3.2__py3-none-any.whl → 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- general_manager/factory/__init__.py +1 -1
- general_manager/factory/factories.py +71 -54
- general_manager/factory/factoryMethods.py +109 -0
- general_manager/measurement/measurement.py +8 -0
- {generalmanager-0.3.2.dist-info → generalmanager-0.4.0.dist-info}/METADATA +1 -1
- {generalmanager-0.3.2.dist-info → generalmanager-0.4.0.dist-info}/RECORD +9 -9
- {generalmanager-0.3.2.dist-info → generalmanager-0.4.0.dist-info}/WHEEL +1 -1
- general_manager/factory/lazy_methods.py +0 -38
- {generalmanager-0.3.2.dist-info → generalmanager-0.4.0.dist-info}/licenses/LICENSE +0 -0
- {generalmanager-0.3.2.dist-info → generalmanager-0.4.0.dist-info}/top_level.txt +0 -0
@@ -1,17 +1,16 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
from typing import TYPE_CHECKING, Type, Callable, Union, Any, TypeVar, Literal, cast
|
3
|
-
from factory.declarations import LazyFunction
|
3
|
+
from factory.declarations import LazyFunction
|
4
4
|
from factory.faker import Faker
|
5
5
|
import exrex # type: ignore
|
6
6
|
from django.db import models
|
7
7
|
from django.core.validators import RegexValidator
|
8
8
|
from factory.django import DjangoModelFactory
|
9
|
-
from django.utils import timezone
|
10
9
|
import random
|
11
10
|
from decimal import Decimal
|
12
11
|
from general_manager.measurement.measurement import Measurement
|
13
12
|
from general_manager.measurement.measurementField import MeasurementField
|
14
|
-
from datetime import date, datetime, time
|
13
|
+
from datetime import date, datetime, time, timezone
|
15
14
|
|
16
15
|
if TYPE_CHECKING:
|
17
16
|
from general_manager.interface.databaseInterface import (
|
@@ -33,7 +32,7 @@ class AutoFactory(DjangoModelFactory[modelsModel]):
|
|
33
32
|
) = None
|
34
33
|
|
35
34
|
@classmethod
|
36
|
-
def _generate(
|
35
|
+
def _generate(
|
37
36
|
cls, strategy: Literal["build", "create"], params: dict[str, Any]
|
38
37
|
) -> models.Model | list[models.Model]:
|
39
38
|
cls._original_params = params
|
@@ -64,7 +63,7 @@ class AutoFactory(DjangoModelFactory[modelsModel]):
|
|
64
63
|
continue # Skip fields that are already set
|
65
64
|
if isinstance(field, models.AutoField) or field.auto_created:
|
66
65
|
continue # Skip auto fields
|
67
|
-
params[field.name] =
|
66
|
+
params[field.name] = getFieldValue(field)
|
68
67
|
|
69
68
|
obj: list[models.Model] | models.Model = super()._generate(strategy, params)
|
70
69
|
if isinstance(obj, list):
|
@@ -84,7 +83,7 @@ class AutoFactory(DjangoModelFactory[modelsModel]):
|
|
84
83
|
if field.name in attrs:
|
85
84
|
m2m_values = attrs[field.name]
|
86
85
|
else:
|
87
|
-
m2m_values =
|
86
|
+
m2m_values = getManyToManyFieldValue(field)
|
88
87
|
if m2m_values:
|
89
88
|
getattr(obj, field.name).set(m2m_values)
|
90
89
|
|
@@ -98,7 +97,7 @@ class AutoFactory(DjangoModelFactory[modelsModel]):
|
|
98
97
|
return kwargs
|
99
98
|
|
100
99
|
@classmethod
|
101
|
-
def _create(
|
100
|
+
def _create(
|
102
101
|
cls, model_class: Type[models.Model], *args: list[Any], **kwargs: dict[str, Any]
|
103
102
|
) -> models.Model | list[models.Model]:
|
104
103
|
kwargs = cls._adjust_kwargs(**kwargs)
|
@@ -107,7 +106,7 @@ class AutoFactory(DjangoModelFactory[modelsModel]):
|
|
107
106
|
return cls._modelCreation(model_class, **kwargs)
|
108
107
|
|
109
108
|
@classmethod
|
110
|
-
def _build(
|
109
|
+
def _build(
|
111
110
|
cls, model_class: Type[models.Model], *args: list[Any], **kwargs: dict[str, Any]
|
112
111
|
) -> models.Model | list[models.Model]:
|
113
112
|
kwargs = cls._adjust_kwargs(**kwargs)
|
@@ -157,7 +156,7 @@ class AutoFactory(DjangoModelFactory[modelsModel]):
|
|
157
156
|
return created_objects
|
158
157
|
|
159
158
|
|
160
|
-
def
|
159
|
+
def getFieldValue(field: models.Field[Any, Any] | models.ForeignObjectRel) -> object:
|
161
160
|
"""
|
162
161
|
Returns a suitable value for a given Django model field.
|
163
162
|
"""
|
@@ -166,22 +165,12 @@ def get_field_value(field: models.Field[Any, Any] | models.ForeignObjectRel) ->
|
|
166
165
|
return None
|
167
166
|
|
168
167
|
if isinstance(field, MeasurementField):
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
regex = None
|
176
|
-
for validator in field.validators:
|
177
|
-
if isinstance(validator, RegexValidator):
|
178
|
-
regex = getattr(validator.regex, "pattern", None)
|
179
|
-
break
|
180
|
-
if regex:
|
181
|
-
# Use exrex to generate a string matching the regex
|
182
|
-
return LazyFunction(lambda: exrex.getone(regex)) # type: ignore
|
183
|
-
else:
|
184
|
-
return cast(str, Faker("text", max_nb_chars=max_length))
|
168
|
+
|
169
|
+
def _measurement():
|
170
|
+
value = Decimal(random.randrange(0, 10_000_000)) / Decimal("100") # two dp
|
171
|
+
return Measurement(value, field.base_unit)
|
172
|
+
|
173
|
+
return LazyFunction(_measurement)
|
185
174
|
elif isinstance(field, models.TextField):
|
186
175
|
return cast(str, Faker("paragraph"))
|
187
176
|
elif isinstance(field, models.IntegerField):
|
@@ -201,8 +190,6 @@ def get_field_value(field: models.Field[Any, Any] | models.ForeignObjectRel) ->
|
|
201
190
|
)
|
202
191
|
elif isinstance(field, models.FloatField):
|
203
192
|
return cast(float, Faker("pyfloat", positive=True))
|
204
|
-
elif isinstance(field, models.DateField):
|
205
|
-
return cast(date, Faker("date_between", start_date="-1y", end_date="today"))
|
206
193
|
elif isinstance(field, models.DateTimeField):
|
207
194
|
return cast(
|
208
195
|
datetime,
|
@@ -213,10 +200,11 @@ def get_field_value(field: models.Field[Any, Any] | models.ForeignObjectRel) ->
|
|
213
200
|
tzinfo=timezone.utc,
|
214
201
|
),
|
215
202
|
)
|
203
|
+
elif isinstance(field, models.DateField):
|
204
|
+
return cast(date, Faker("date_between", start_date="-1y", end_date="today"))
|
216
205
|
elif isinstance(field, models.BooleanField):
|
217
206
|
return cast(bool, Faker("pybool"))
|
218
|
-
elif isinstance(field, models.
|
219
|
-
# Create or get an instance of the related model
|
207
|
+
elif isinstance(field, models.OneToOneField):
|
220
208
|
if hasattr(field.related_model, "_general_manager_class"):
|
221
209
|
related_factory = field.related_model._general_manager_class.Factory
|
222
210
|
return related_factory()
|
@@ -229,11 +217,19 @@ def get_field_value(field: models.Field[Any, Any] | models.ForeignObjectRel) ->
|
|
229
217
|
raise ValueError(
|
230
218
|
f"No factory found for {field.related_model.__name__} and no instances found"
|
231
219
|
)
|
232
|
-
elif isinstance(field, models.
|
233
|
-
#
|
220
|
+
elif isinstance(field, models.ForeignKey):
|
221
|
+
# Create or get an instance of the related model
|
234
222
|
if hasattr(field.related_model, "_general_manager_class"):
|
223
|
+
create_a_new_instance = random.choice([True, True, False])
|
224
|
+
if not create_a_new_instance:
|
225
|
+
existing_instances = list(field.related_model.objects.all())
|
226
|
+
if existing_instances:
|
227
|
+
# Pick a random existing instance
|
228
|
+
return LazyFunction(lambda: random.choice(existing_instances))
|
229
|
+
|
235
230
|
related_factory = field.related_model._general_manager_class.Factory
|
236
231
|
return related_factory()
|
232
|
+
|
237
233
|
else:
|
238
234
|
# If no factory exists, pick a random existing instance
|
239
235
|
related_instances = list(field.related_model.objects.all())
|
@@ -253,35 +249,56 @@ def get_field_value(field: models.Field[Any, Any] | models.ForeignObjectRel) ->
|
|
253
249
|
return cast(str, Faker("uuid4"))
|
254
250
|
elif isinstance(field, models.DurationField):
|
255
251
|
return cast(time, Faker("time_delta"))
|
252
|
+
elif isinstance(field, models.CharField):
|
253
|
+
max_length = field.max_length or 100
|
254
|
+
# Check for RegexValidator
|
255
|
+
regex = None
|
256
|
+
for validator in field.validators:
|
257
|
+
if isinstance(validator, RegexValidator):
|
258
|
+
regex = getattr(validator.regex, "pattern", None)
|
259
|
+
break
|
260
|
+
if regex:
|
261
|
+
# Use exrex to generate a string matching the regex
|
262
|
+
return LazyFunction(lambda: exrex.getone(regex)) # type: ignore
|
263
|
+
else:
|
264
|
+
return cast(str, Faker("text", max_nb_chars=max_length))
|
256
265
|
else:
|
257
266
|
return None # For unsupported field types
|
258
267
|
|
259
268
|
|
260
|
-
def
|
269
|
+
def getManyToManyFieldValue(
|
270
|
+
field: models.ManyToManyField,
|
271
|
+
) -> list[models.Model]:
|
261
272
|
"""
|
262
273
|
Returns a list of instances for a ManyToMany field.
|
263
274
|
"""
|
264
|
-
related_factory =
|
265
|
-
|
275
|
+
related_factory = None
|
276
|
+
related_instances = list(field.related_model.objects.all())
|
277
|
+
if hasattr(field.related_model, "_general_manager_class"):
|
278
|
+
related_factory = field.related_model._general_manager_class.Factory
|
266
279
|
|
267
|
-
if
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
280
|
+
min_required = 0 if field.blank else 1
|
281
|
+
number_of_instances = random.randint(min_required, 10)
|
282
|
+
if related_factory and related_instances:
|
283
|
+
number_to_create = random.randint(min_required, number_of_instances)
|
284
|
+
number_to_pick = number_of_instances - number_to_create
|
285
|
+
if number_to_pick > len(related_instances):
|
286
|
+
number_to_pick = len(related_instances)
|
287
|
+
existing_instances = random.sample(related_instances, number_to_pick)
|
288
|
+
new_instances = [related_factory() for _ in range(number_to_create)]
|
289
|
+
return existing_instances + new_instances
|
290
|
+
elif related_factory:
|
291
|
+
number_to_create = number_of_instances
|
292
|
+
new_instances = [related_factory() for _ in range(number_to_create)]
|
293
|
+
return new_instances
|
294
|
+
elif related_instances:
|
295
|
+
number_to_create = 0
|
296
|
+
number_to_pick = number_of_instances
|
297
|
+
if number_to_pick > len(related_instances):
|
298
|
+
number_to_pick = len(related_instances)
|
299
|
+
existing_instances = random.sample(related_instances, number_to_pick)
|
300
|
+
return existing_instances
|
278
301
|
else:
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
num_instances = random.randint(0, max_instances)
|
283
|
-
return random.sample(existing_instances, num_instances)
|
284
|
-
else:
|
285
|
-
raise ValueError(
|
286
|
-
f"No factory found for {field.related_model.__name__} and no instances found"
|
287
|
-
)
|
302
|
+
raise ValueError(
|
303
|
+
f"No factory found for {field.related_model.__name__} and no instances found"
|
304
|
+
)
|
@@ -0,0 +1,109 @@
|
|
1
|
+
from typing import Any, Optional
|
2
|
+
from factory.declarations import LazyFunction, LazyAttribute, LazyAttributeSequence
|
3
|
+
import random
|
4
|
+
from general_manager.measurement.measurement import Measurement
|
5
|
+
from datetime import timedelta, date, datetime
|
6
|
+
from faker import Faker
|
7
|
+
import uuid
|
8
|
+
from decimal import Decimal
|
9
|
+
|
10
|
+
fake = Faker()
|
11
|
+
|
12
|
+
|
13
|
+
def LazyMeasurement(
|
14
|
+
min_value: int | float, max_value: int | float, unit: str
|
15
|
+
) -> LazyFunction:
|
16
|
+
return LazyFunction(
|
17
|
+
lambda: Measurement(str(random.uniform(min_value, max_value))[:10], unit)
|
18
|
+
)
|
19
|
+
|
20
|
+
|
21
|
+
def LazyDeltaDate(avg_delta_days: int, base_attribute: str) -> LazyAttribute:
|
22
|
+
return LazyAttribute(
|
23
|
+
lambda obj: (getattr(obj, base_attribute) or date.today())
|
24
|
+
+ timedelta(days=random.randint(avg_delta_days // 2, avg_delta_days * 3 // 2))
|
25
|
+
)
|
26
|
+
|
27
|
+
|
28
|
+
def LazyProjectName() -> LazyFunction:
|
29
|
+
return LazyFunction(
|
30
|
+
lambda: (
|
31
|
+
f"{fake.word().capitalize()} "
|
32
|
+
f"{fake.word().capitalize()} "
|
33
|
+
f"{fake.random_element(elements=('X', 'Z', 'G'))}"
|
34
|
+
f"-{fake.random_int(min=1, max=1000)}"
|
35
|
+
)
|
36
|
+
)
|
37
|
+
|
38
|
+
|
39
|
+
def LazyDateToday() -> LazyFunction:
|
40
|
+
return LazyFunction(lambda: date.today())
|
41
|
+
|
42
|
+
|
43
|
+
def LazyDateBetween(start_date: date, end_date: date) -> LazyAttribute:
|
44
|
+
delta = (end_date - start_date).days
|
45
|
+
return LazyAttribute(
|
46
|
+
lambda obj: start_date + timedelta(days=random.randint(0, delta))
|
47
|
+
)
|
48
|
+
|
49
|
+
|
50
|
+
def LazyDateTimeBetween(start: datetime, end: datetime) -> LazyAttribute:
|
51
|
+
span = (end - start).total_seconds()
|
52
|
+
return LazyAttribute(
|
53
|
+
lambda obj: start + timedelta(seconds=random.randint(0, int(span)))
|
54
|
+
)
|
55
|
+
|
56
|
+
|
57
|
+
def LazyInteger(min_value: int, max_value: int) -> LazyFunction:
|
58
|
+
return LazyFunction(lambda: random.randint(min_value, max_value))
|
59
|
+
|
60
|
+
|
61
|
+
def LazyDecimal(min_value: float, max_value: float, precision: int = 2) -> LazyFunction:
|
62
|
+
fmt = f"{{:.{precision}f}}"
|
63
|
+
return LazyFunction(
|
64
|
+
lambda: Decimal(fmt.format(random.uniform(min_value, max_value)))
|
65
|
+
)
|
66
|
+
|
67
|
+
|
68
|
+
def LazyChoice(options: list[Any]) -> LazyFunction:
|
69
|
+
return LazyFunction(lambda: random.choice(options))
|
70
|
+
|
71
|
+
|
72
|
+
def LazySequence(start: int = 0, step: int = 1) -> LazyAttributeSequence:
|
73
|
+
return LazyAttributeSequence(lambda obj, n: start + n * step)
|
74
|
+
|
75
|
+
|
76
|
+
def LazyBoolean(trues_ratio: float = 0.5) -> LazyFunction:
|
77
|
+
return LazyFunction(lambda: random.random() < trues_ratio)
|
78
|
+
|
79
|
+
|
80
|
+
def LazyUUID() -> LazyFunction:
|
81
|
+
return LazyFunction(lambda: str(uuid.uuid4()))
|
82
|
+
|
83
|
+
|
84
|
+
def LazyFakerName() -> LazyFunction:
|
85
|
+
return LazyFunction(lambda: fake.name())
|
86
|
+
|
87
|
+
|
88
|
+
def LazyFakerEmail(
|
89
|
+
name: Optional[str] = None, domain: Optional[str] = None
|
90
|
+
) -> LazyFunction:
|
91
|
+
if not name and not domain:
|
92
|
+
return LazyFunction(lambda: fake.email(domain=domain))
|
93
|
+
if not name:
|
94
|
+
name = fake.name()
|
95
|
+
if not domain:
|
96
|
+
domain = fake.domain_name()
|
97
|
+
return LazyFunction(lambda: name.replace(" ", "_") + "@" + domain)
|
98
|
+
|
99
|
+
|
100
|
+
def LazyFakerSentence(number_of_words: int = 6) -> LazyFunction:
|
101
|
+
return LazyFunction(lambda: fake.sentence(nb_words=number_of_words))
|
102
|
+
|
103
|
+
|
104
|
+
def LazyFakerAddress() -> LazyFunction:
|
105
|
+
return LazyFunction(lambda: fake.address())
|
106
|
+
|
107
|
+
|
108
|
+
def LazyFakerUrl() -> LazyFunction:
|
109
|
+
return LazyFunction(lambda: fake.url())
|
@@ -46,6 +46,14 @@ class Measurement:
|
|
46
46
|
def quantity(self) -> pint.Quantity:
|
47
47
|
return self.__quantity
|
48
48
|
|
49
|
+
@property
|
50
|
+
def magnitude(self) -> Decimal:
|
51
|
+
return self.__quantity.magnitude
|
52
|
+
|
53
|
+
@property
|
54
|
+
def unit(self) -> str:
|
55
|
+
return str(self.__quantity.units)
|
56
|
+
|
49
57
|
@classmethod
|
50
58
|
def from_string(cls, value: str) -> Measurement:
|
51
59
|
value, unit = value.split(" ")
|
@@ -15,9 +15,9 @@ general_manager/cache/cacheTracker.py,sha256=rRw3OhBDf86hTC2Xbt1ocRgZqwu8_kXk4lc
|
|
15
15
|
general_manager/cache/dependencyIndex.py,sha256=kEbIAzzMzKlQgplKfcMYBPZ562zCBkOBKvJusxO_iC4,10537
|
16
16
|
general_manager/cache/modelDependencyCollector.py,sha256=wS2edbZsQ1aTfRlHj02lhuasZHCc2ucRGob-E7ejuoY,2433
|
17
17
|
general_manager/cache/signals.py,sha256=ZHeXKFMN7tj9t0J-vSqf_05_NhGqEF2sZtbZO3vaRqI,1234
|
18
|
-
general_manager/factory/__init__.py,sha256=
|
19
|
-
general_manager/factory/factories.py,sha256=
|
20
|
-
general_manager/factory/
|
18
|
+
general_manager/factory/__init__.py,sha256=wbPIGyBlWBHa7aGWUd-1IUMPWUS-M6YqtPUL1iKXW8U,93
|
19
|
+
general_manager/factory/factories.py,sha256=R2_iAVRspfysDNT_cKyJuMT38RFkNbjnPR3yjAXZRkc,12188
|
20
|
+
general_manager/factory/factoryMethods.py,sha256=9Bag891j0XHe3dUBAFi7gUKcKeUwcBZN3cDLBobyBiI,3225
|
21
21
|
general_manager/interface/__init__.py,sha256=6x5adQLefTugvrJeyPcAxstyqgLAYeaJ1EPdAbac9pE,213
|
22
22
|
general_manager/interface/baseInterface.py,sha256=mvSKUlA-0fazNnaIXGBwkiZxmX8DM_sOn-SaAIpaW8I,10273
|
23
23
|
general_manager/interface/calculationInterface.py,sha256=GzSNXjU6Z7bFz60gHyMKkI5xNUDIPuniV8wbyVtQT50,14250
|
@@ -28,7 +28,7 @@ general_manager/manager/groupManager.py,sha256=O4FABqbm7KlZw6t36Ot3HU1FsBYN0h6Zh
|
|
28
28
|
general_manager/manager/input.py,sha256=iKawV3P1QICz-0AQUF00OvH7LZYxussg3svpvCUl8hE,2977
|
29
29
|
general_manager/manager/meta.py,sha256=5wHrCVnua5c38vpVZSCesrNvgydQDH8h6pxW6_QgCDg,3107
|
30
30
|
general_manager/measurement/__init__.py,sha256=X97meFujBldE5v0WMF7SmKeGpC5R0JTczfLo_Lq1Xek,84
|
31
|
-
general_manager/measurement/measurement.py,sha256=
|
31
|
+
general_manager/measurement/measurement.py,sha256=IMUY8vmoEIrclMW9FWLgL2Wi61rH1J0NMSmjYdMkMHM,9516
|
32
32
|
general_manager/measurement/measurementField.py,sha256=iq9Hqe6ZGX8CxXm4nIqTAWTRkQVptzpqE9ExX-jFyNs,5928
|
33
33
|
general_manager/permission/__init__.py,sha256=5UlDERN60Vn8obGVkT-cOM8kHjzmoxgK5w5FgTCDhGE,59
|
34
34
|
general_manager/permission/basePermission.py,sha256=PsJiX-UNeSh6xUlcUwuQNCLYvHZipWUJ0kAoMkdxXJc,6113
|
@@ -39,8 +39,8 @@ general_manager/permission/permissionDataManager.py,sha256=Ji7fsnuaKTa6M8yzCGyzr
|
|
39
39
|
general_manager/rule/__init__.py,sha256=4Har5cfPD1fmOsilTDod-ZUz3Com-tkl58jz7yY4fD0,23
|
40
40
|
general_manager/rule/handler.py,sha256=z8SFHTIZ0LbLh3fV56Mud0V4_OvWkqJjlHvFqau7Qfk,7334
|
41
41
|
general_manager/rule/rule.py,sha256=3FVCKGL7BTVoStdgOTdWQwuoVRIxAIAilV4VOzouDpc,10759
|
42
|
-
generalmanager-0.
|
43
|
-
generalmanager-0.
|
44
|
-
generalmanager-0.
|
45
|
-
generalmanager-0.
|
46
|
-
generalmanager-0.
|
42
|
+
generalmanager-0.4.0.dist-info/licenses/LICENSE,sha256=YGFm0ieb4KpkMRRt2qnWue6uFh0cUMtobwEBkHwajhc,1450
|
43
|
+
generalmanager-0.4.0.dist-info/METADATA,sha256=hA9V_hws-DSJegQQBxWgjhOnrDxIdeEJq_f7gHeOzPo,8188
|
44
|
+
generalmanager-0.4.0.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
|
45
|
+
generalmanager-0.4.0.dist-info/top_level.txt,sha256=sTDtExP9ga-YP3h3h42yivUY-A2Q23C2nw6LNKOho4I,16
|
46
|
+
generalmanager-0.4.0.dist-info/RECORD,,
|
@@ -1,38 +0,0 @@
|
|
1
|
-
from typing import Any
|
2
|
-
from factory.declarations import LazyFunction, LazyAttribute, LazyAttributeSequence
|
3
|
-
import random
|
4
|
-
from general_manager.measurement.measurement import Measurement
|
5
|
-
from datetime import timedelta, date
|
6
|
-
from faker import Faker
|
7
|
-
|
8
|
-
fake = Faker()
|
9
|
-
|
10
|
-
|
11
|
-
def LazyMeasurement(
|
12
|
-
min_value: int | float, max_value: int | float, unit: str
|
13
|
-
) -> LazyFunction:
|
14
|
-
return LazyFunction(
|
15
|
-
lambda: Measurement(str(random.uniform(min_value, max_value))[:10], unit)
|
16
|
-
)
|
17
|
-
|
18
|
-
|
19
|
-
def LazyDeltaDate(avg_delta_days: int, base_attribute: str) -> LazyAttribute:
|
20
|
-
return LazyAttribute(
|
21
|
-
lambda obj: (getattr(obj, base_attribute) or date.today())
|
22
|
-
+ timedelta(days=random.randint(avg_delta_days // 2, avg_delta_days * 3 // 2))
|
23
|
-
)
|
24
|
-
|
25
|
-
|
26
|
-
def LazyProjectName() -> LazyFunction:
|
27
|
-
return LazyFunction(
|
28
|
-
lambda: (
|
29
|
-
f"{fake.word().capitalize()} "
|
30
|
-
f"{fake.word().capitalize()} "
|
31
|
-
f"{fake.random_element(elements=('X', 'Z', 'G'))}"
|
32
|
-
f"-{fake.random_int(min=1, max=1000)}"
|
33
|
-
)
|
34
|
-
)
|
35
|
-
|
36
|
-
|
37
|
-
def LazySapNumber() -> LazyAttributeSequence:
|
38
|
-
return LazyAttributeSequence(lambda obj, n: f"60{n:04d}")
|
File without changes
|
File without changes
|