Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/django/db/models/utils.py: 50%
34 statements
« prev ^ index » next coverage.py v7.0.5, created at 2023-01-17 06:13 +0000
« prev ^ index » next coverage.py v7.0.5, created at 2023-01-17 06:13 +0000
1import functools
2from collections import namedtuple
5def make_model_tuple(model):
6 """
7 Take a model or a string of the form "app_label.ModelName" and return a
8 corresponding ("app_label", "modelname") tuple. If a tuple is passed in,
9 assume it's a valid model tuple already and return it unchanged.
10 """
11 try:
12 if isinstance(model, tuple):
13 model_tuple = model
14 elif isinstance(model, str):
15 app_label, model_name = model.split(".")
16 model_tuple = app_label, model_name.lower()
17 else:
18 model_tuple = model._meta.app_label, model._meta.model_name
19 assert len(model_tuple) == 2
20 return model_tuple
21 except (ValueError, AssertionError):
22 raise ValueError(
23 "Invalid model reference '%s'. String model references "
24 "must be of the form 'app_label.ModelName'." % model
25 )
28def resolve_callables(mapping):
29 """
30 Generate key/value pairs for the given mapping where the values are
31 evaluated if they're callable.
32 """
33 for k, v in mapping.items():
34 yield k, v() if callable(v) else v
37def unpickle_named_row(names, values):
38 return create_namedtuple_class(*names)(*values)
41@functools.lru_cache
42def create_namedtuple_class(*names):
43 # Cache type() with @lru_cache since it's too slow to be called for every
44 # QuerySet evaluation.
45 def __reduce__(self):
46 return unpickle_named_row, (names, tuple(self))
48 return type(
49 "Row",
50 (namedtuple("Row", names),),
51 {"__reduce__": __reduce__, "__slots__": ()},
52 )
55class AltersData:
56 """
57 Make subclasses preserve the alters_data attribute on overridden methods.
58 """
60 def __init_subclass__(cls, **kwargs):
61 for fn_name, fn in vars(cls).items():
62 if callable(fn) and not hasattr(fn, "alters_data"):
63 for base in cls.__bases__:
64 if base_fn := getattr(base, fn_name, None):
65 if hasattr(base_fn, "alters_data"):
66 fn.alters_data = base_fn.alters_data
67 break
69 super().__init_subclass__(**kwargs)