lamindb 0.77.2__py3-none-any.whl → 1.0rc1__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.
- lamindb/__init__.py +39 -32
- lamindb/_artifact.py +95 -64
- lamindb/_can_curate.py +19 -10
- lamindb/_collection.py +51 -49
- lamindb/_feature.py +9 -9
- lamindb/_finish.py +99 -86
- lamindb/_from_values.py +20 -17
- lamindb/_is_versioned.py +2 -1
- lamindb/_parents.py +23 -16
- lamindb/_query_manager.py +3 -3
- lamindb/_query_set.py +85 -18
- lamindb/_record.py +121 -46
- lamindb/_run.py +3 -3
- lamindb/_save.py +14 -8
- lamindb/{_feature_set.py → _schema.py} +34 -31
- lamindb/_storage.py +2 -1
- lamindb/_transform.py +51 -23
- lamindb/_ulabel.py +17 -8
- lamindb/_view.py +15 -14
- lamindb/base/__init__.py +24 -0
- lamindb/base/fields.py +281 -0
- lamindb/base/ids.py +103 -0
- lamindb/base/types.py +51 -0
- lamindb/base/users.py +30 -0
- lamindb/base/validation.py +67 -0
- lamindb/core/__init__.py +19 -14
- lamindb/core/_context.py +297 -228
- lamindb/core/_data.py +44 -49
- lamindb/core/_describe.py +41 -31
- lamindb/core/_django.py +59 -44
- lamindb/core/_feature_manager.py +192 -168
- lamindb/core/_label_manager.py +22 -22
- lamindb/core/_mapped_collection.py +17 -14
- lamindb/core/_settings.py +1 -12
- lamindb/core/_sync_git.py +56 -9
- lamindb/core/_track_environment.py +1 -1
- lamindb/core/datasets/_core.py +5 -6
- lamindb/core/exceptions.py +0 -7
- lamindb/core/fields.py +1 -1
- lamindb/core/loaders.py +18 -2
- lamindb/core/{schema.py → relations.py} +22 -19
- lamindb/core/storage/_anndata_accessor.py +1 -2
- lamindb/core/storage/_backed_access.py +2 -1
- lamindb/core/storage/_tiledbsoma.py +40 -13
- lamindb/core/storage/objects.py +1 -1
- lamindb/core/storage/paths.py +13 -8
- lamindb/core/subsettings/__init__.py +0 -2
- lamindb/core/types.py +2 -23
- lamindb/core/versioning.py +11 -7
- lamindb/{_curate.py → curators/__init__.py} +700 -57
- lamindb/curators/_spatial.py +528 -0
- lamindb/integrations/_vitessce.py +1 -3
- lamindb/migrations/0052_squashed.py +1261 -0
- lamindb/migrations/0053_alter_featureset_hash_alter_paramvalue_created_by_and_more.py +57 -0
- lamindb/migrations/0054_alter_feature_previous_runs_and_more.py +35 -0
- lamindb/migrations/0055_artifact_type_artifactparamvalue_and_more.py +61 -0
- lamindb/migrations/0056_rename_ulabel_ref_is_name_artifactulabel_label_ref_is_name_and_more.py +22 -0
- lamindb/migrations/0057_link_models_latest_report_and_others.py +356 -0
- lamindb/migrations/0058_artifact__actions_collection__actions.py +22 -0
- lamindb/migrations/0059_alter_artifact__accessor_alter_artifact__hash_type_and_more.py +31 -0
- lamindb/migrations/0060_alter_artifact__actions.py +22 -0
- lamindb/migrations/0061_alter_collection_meta_artifact_alter_run_environment_and_more.py +45 -0
- lamindb/migrations/0062_add_is_latest_field.py +32 -0
- lamindb/migrations/0063_populate_latest_field.py +45 -0
- lamindb/migrations/0064_alter_artifact_version_alter_collection_version_and_more.py +33 -0
- lamindb/migrations/0065_remove_collection_feature_sets_and_more.py +22 -0
- lamindb/migrations/0066_alter_artifact__feature_values_and_more.py +352 -0
- lamindb/migrations/0067_alter_featurevalue_unique_together_and_more.py +20 -0
- lamindb/migrations/0068_alter_artifactulabel_unique_together_and_more.py +20 -0
- lamindb/migrations/0069_alter_artifact__accessor_alter_artifact__hash_type_and_more.py +1294 -0
- lamindb/migrations/0069_squashed.py +1770 -0
- lamindb/migrations/0070_lamindbv1_migrate_data.py +78 -0
- lamindb/migrations/0071_lamindbv1_migrate_schema.py +741 -0
- lamindb/migrations/0072_remove_user__branch_code_remove_user_aux_and_more.py +148 -0
- lamindb/migrations/0073_merge_ourprojects.py +945 -0
- lamindb/migrations/0074_lamindbv1_part4.py +374 -0
- lamindb/migrations/0075_lamindbv1_part5.py +276 -0
- lamindb/migrations/0076_lamindbv1_part6.py +621 -0
- lamindb/migrations/0077_lamindbv1_part6b.py +228 -0
- lamindb/migrations/0078_lamindbv1_part6c.py +468 -0
- lamindb/migrations/0079_alter_rundata_value_json_and_more.py +36 -0
- lamindb/migrations/__init__.py +0 -0
- lamindb/models.py +4064 -0
- {lamindb-0.77.2.dist-info → lamindb-1.0rc1.dist-info}/METADATA +15 -20
- lamindb-1.0rc1.dist-info/RECORD +100 -0
- {lamindb-0.77.2.dist-info → lamindb-1.0rc1.dist-info}/WHEEL +1 -1
- lamindb/core/subsettings/_transform_settings.py +0 -21
- lamindb-0.77.2.dist-info/RECORD +0 -63
- {lamindb-0.77.2.dist-info → lamindb-1.0rc1.dist-info}/LICENSE +0 -0
lamindb/_from_values.py
CHANGED
@@ -5,16 +5,16 @@ from typing import TYPE_CHECKING
|
|
5
5
|
import pandas as pd
|
6
6
|
from django.core.exceptions import FieldDoesNotExist
|
7
7
|
from lamin_utils import colors, logger
|
8
|
-
from lnschema_core.models import Record
|
9
8
|
|
10
9
|
from lamindb._query_set import RecordList
|
10
|
+
from lamindb.models import Record
|
11
11
|
|
12
12
|
from .core._settings import settings
|
13
13
|
|
14
14
|
if TYPE_CHECKING:
|
15
15
|
from collections.abc import Iterable
|
16
16
|
|
17
|
-
from
|
17
|
+
from lamindb.base.types import ListLike, StrField
|
18
18
|
|
19
19
|
|
20
20
|
# The base function for `from_values`
|
@@ -52,12 +52,6 @@ def get_or_create_records(
|
|
52
52
|
if from_source:
|
53
53
|
if isinstance(source, Record):
|
54
54
|
source_record = source
|
55
|
-
elif (
|
56
|
-
len(records) > 0
|
57
|
-
and hasattr(records[0], "source_id")
|
58
|
-
and records[0].source_id
|
59
|
-
):
|
60
|
-
source_record = records[0].source
|
61
55
|
if not source_record and hasattr(registry, "public"):
|
62
56
|
if organism is None:
|
63
57
|
organism = _ensembl_prefix(nonexist_values[0], field, organism)
|
@@ -95,7 +89,7 @@ def get_or_create_records(
|
|
95
89
|
if len(msg) > 0 and not mute:
|
96
90
|
logger.success(msg)
|
97
91
|
s = "" if len(unmapped_values) == 1 else "s"
|
98
|
-
print_values = colors.yellow(
|
92
|
+
print_values = colors.yellow(_format_values(unmapped_values))
|
99
93
|
name = registry.__name__
|
100
94
|
n_nonval = colors.yellow(f"{len(unmapped_values)} non-validated")
|
101
95
|
if not mute:
|
@@ -103,7 +97,7 @@ def get_or_create_records(
|
|
103
97
|
f"{colors.red('did not create')} {name} record{s} for "
|
104
98
|
f"{n_nonval} {colors.italic(f'{field.field.name}{s}')}: {print_values}"
|
105
99
|
)
|
106
|
-
# if registry.
|
100
|
+
# if registry.__get_module_name__() == "bionty" or registry == ULabel:
|
107
101
|
# if isinstance(iterable, pd.Series):
|
108
102
|
# feature = iterable.name
|
109
103
|
# feature_name = None
|
@@ -167,7 +161,7 @@ def get_existing_records(
|
|
167
161
|
if not mute:
|
168
162
|
if len(validated) > 0:
|
169
163
|
s = "" if len(validated) == 1 else "s"
|
170
|
-
print_values = colors.green(
|
164
|
+
print_values = colors.green(_format_values(validated))
|
171
165
|
msg = (
|
172
166
|
"loaded"
|
173
167
|
f" {colors.green(f'{len(validated)} {model.__name__} record{s}')}"
|
@@ -176,7 +170,7 @@ def get_existing_records(
|
|
176
170
|
if len(syn_mapper) > 0:
|
177
171
|
s = "" if len(syn_mapper) == 1 else "s"
|
178
172
|
names = list(syn_mapper.keys())
|
179
|
-
print_values = colors.green(
|
173
|
+
print_values = colors.green(_format_values(names))
|
180
174
|
syn_msg = (
|
181
175
|
"loaded"
|
182
176
|
f" {colors.green(f'{len(syn_mapper)} {model.__name__} record{s}')}"
|
@@ -236,14 +230,23 @@ def create_records_from_source(
|
|
236
230
|
bionty_df = filter_bionty_df_columns(model=model, public_ontology=public_ontology)
|
237
231
|
|
238
232
|
# standardize in the bionty reference
|
239
|
-
|
233
|
+
# do not inspect synonyms if the field is not name field
|
234
|
+
inspect_synonyms = True
|
235
|
+
if hasattr(model, "_name_field") and field.field.name != model._name_field:
|
236
|
+
inspect_synonyms = False
|
237
|
+
result = public_ontology.inspect(
|
238
|
+
iterable_idx,
|
239
|
+
field=field.field.name,
|
240
|
+
mute=True,
|
241
|
+
inspect_synonyms=inspect_synonyms,
|
242
|
+
)
|
240
243
|
syn_mapper = result.synonyms_mapper
|
241
244
|
|
242
245
|
msg_syn: str = ""
|
243
246
|
if len(syn_mapper) > 0:
|
244
247
|
s = "" if len(syn_mapper) == 1 else "s"
|
245
248
|
names = list(syn_mapper.keys())
|
246
|
-
print_values = colors.purple(
|
249
|
+
print_values = colors.purple(_format_values(names))
|
247
250
|
msg_syn = (
|
248
251
|
"created"
|
249
252
|
f" {colors.purple(f'{len(syn_mapper)} {model.__name__} record{s} from Bionty')}"
|
@@ -277,7 +280,7 @@ def create_records_from_source(
|
|
277
280
|
validated = result.validated
|
278
281
|
if len(validated) > 0:
|
279
282
|
s = "" if len(validated) == 1 else "s"
|
280
|
-
print_values = colors.purple(
|
283
|
+
print_values = colors.purple(_format_values(validated))
|
281
284
|
# this is the success msg for existing records in the DB
|
282
285
|
if len(msg) > 0 and not mute:
|
283
286
|
logger.success(msg)
|
@@ -307,7 +310,7 @@ def index_iterable(iterable: Iterable) -> pd.Index:
|
|
307
310
|
return idx[(idx != "") & (~idx.isnull())]
|
308
311
|
|
309
312
|
|
310
|
-
def
|
313
|
+
def _format_values(
|
311
314
|
names: Iterable, n: int = 20, quotes: bool = True, sep: str = "'"
|
312
315
|
) -> str:
|
313
316
|
if isinstance(names, dict):
|
@@ -345,7 +348,7 @@ def _bulk_create_dicts_from_df(
|
|
345
348
|
dup = df.index[df.index.duplicated()].unique().tolist()
|
346
349
|
if len(dup) > 0:
|
347
350
|
s = "" if len(dup) == 1 else "s"
|
348
|
-
print_values =
|
351
|
+
print_values = _format_values(dup)
|
349
352
|
multi_msg = (
|
350
353
|
f"ambiguous validation in Bionty for {len(dup)} record{s}:"
|
351
354
|
f" {print_values}"
|
lamindb/_is_versioned.py
CHANGED
@@ -3,7 +3,8 @@ from __future__ import annotations
|
|
3
3
|
import lamindb_setup as ln_setup
|
4
4
|
from lamin_utils import logger
|
5
5
|
from lamindb_setup.core.upath import UPath
|
6
|
-
|
6
|
+
|
7
|
+
from lamindb.models import IsVersioned
|
7
8
|
|
8
9
|
from ._utils import attach_func_to_class_method
|
9
10
|
from .core.versioning import create_uid, get_new_path_from_uid
|
lamindb/_parents.py
CHANGED
@@ -5,15 +5,22 @@ from typing import TYPE_CHECKING, Literal
|
|
5
5
|
|
6
6
|
import lamindb_setup as ln_setup
|
7
7
|
from lamin_utils import logger
|
8
|
-
|
9
|
-
from
|
8
|
+
|
9
|
+
from lamindb.models import (
|
10
|
+
Artifact,
|
11
|
+
Collection,
|
12
|
+
HasParents,
|
13
|
+
Record,
|
14
|
+
Run,
|
15
|
+
Transform,
|
16
|
+
format_field_value,
|
17
|
+
)
|
10
18
|
|
11
19
|
from ._record import get_name_field
|
12
20
|
from ._utils import attach_func_to_class_method
|
13
21
|
|
14
22
|
if TYPE_CHECKING:
|
15
|
-
from
|
16
|
-
|
23
|
+
from lamindb.base.types import StrField
|
17
24
|
from lamindb.core import QuerySet
|
18
25
|
|
19
26
|
LAMIN_GREEN_LIGHTER = "#10b981"
|
@@ -25,7 +32,7 @@ TRANSFORM_EMOJIS = {
|
|
25
32
|
"pipeline": "🧩",
|
26
33
|
"script": "📝",
|
27
34
|
"function": "🔧",
|
28
|
-
"
|
35
|
+
"linker": "🧲",
|
29
36
|
}
|
30
37
|
is_run_from_ipython = getattr(builtins, "__IPYTHON__", False)
|
31
38
|
|
@@ -342,8 +349,8 @@ def _record_label(record: Record, field: str | None = None):
|
|
342
349
|
rf' FACE="Monospace">uid={record.uid}<BR/>version={record.version}</FONT>>'
|
343
350
|
)
|
344
351
|
elif isinstance(record, Run):
|
345
|
-
if record.transform.
|
346
|
-
name = f'{record.transform.
|
352
|
+
if record.transform.description:
|
353
|
+
name = f'{record.transform.description.replace("&", "&")}'
|
347
354
|
elif record.transform.key:
|
348
355
|
name = f'{record.transform.key.replace("&", "&")}'
|
349
356
|
else:
|
@@ -395,22 +402,22 @@ def _get_all_parent_runs(data: Artifact | Collection) -> list:
|
|
395
402
|
inputs_run = (
|
396
403
|
r.__getattribute__(f"input_{name}s")
|
397
404
|
.all()
|
398
|
-
.filter(
|
405
|
+
.filter(_branch_code__in=[0, 1])
|
399
406
|
.list()
|
400
407
|
)
|
401
408
|
if name == "artifact":
|
402
409
|
inputs_run += (
|
403
|
-
r.input_collections.all().filter(
|
410
|
+
r.input_collections.all().filter(_branch_code__in=[0, 1]).list()
|
404
411
|
)
|
405
412
|
outputs_run = (
|
406
413
|
r.__getattribute__(f"output_{name}s")
|
407
414
|
.all()
|
408
|
-
.filter(
|
415
|
+
.filter(_branch_code__in=[0, 1])
|
409
416
|
.list()
|
410
417
|
)
|
411
418
|
if name == "artifact":
|
412
419
|
outputs_run += (
|
413
|
-
r.output_collections.all().filter(
|
420
|
+
r.output_collections.all().filter(_branch_code__in=[0, 1]).list()
|
414
421
|
)
|
415
422
|
# if inputs are outputs artifacts are the same, will result infinite loop
|
416
423
|
# so only show as outputs
|
@@ -444,7 +451,7 @@ def _get_all_child_runs(data: Artifact | Collection) -> list:
|
|
444
451
|
{
|
445
452
|
f.run
|
446
453
|
for f in data.run.output_collections.all()
|
447
|
-
.filter(
|
454
|
+
.filter(_branch_code__in=[0, 1])
|
448
455
|
.all()
|
449
456
|
}
|
450
457
|
)
|
@@ -455,24 +462,24 @@ def _get_all_child_runs(data: Artifact | Collection) -> list:
|
|
455
462
|
inputs_run = (
|
456
463
|
r.__getattribute__(f"input_{name}s")
|
457
464
|
.all()
|
458
|
-
.filter(
|
465
|
+
.filter(_branch_code__in=[0, 1])
|
459
466
|
.list()
|
460
467
|
)
|
461
468
|
if name == "artifact":
|
462
469
|
inputs_run += (
|
463
|
-
r.input_collections.all().filter(
|
470
|
+
r.input_collections.all().filter(_branch_code__in=[0, 1]).list()
|
464
471
|
)
|
465
472
|
run_inputs_outputs += [(inputs_run, r)]
|
466
473
|
|
467
474
|
outputs_run = (
|
468
475
|
r.__getattribute__(f"output_{name}s")
|
469
476
|
.all()
|
470
|
-
.filter(
|
477
|
+
.filter(_branch_code__in=[0, 1])
|
471
478
|
.list()
|
472
479
|
)
|
473
480
|
if name == "artifact":
|
474
481
|
outputs_run += (
|
475
|
-
r.output_collections.all().filter(
|
482
|
+
r.output_collections.all().filter(_branch_code__in=[0, 1]).list()
|
476
483
|
)
|
477
484
|
run_inputs_outputs += [(r, outputs_run)]
|
478
485
|
|
lamindb/_query_manager.py
CHANGED
@@ -5,13 +5,13 @@ from typing import TYPE_CHECKING, NamedTuple
|
|
5
5
|
from django.db import models
|
6
6
|
from lamin_utils import logger
|
7
7
|
from lamindb_setup.core._docs import doc_args
|
8
|
-
from lnschema_core.models import Record
|
9
8
|
|
10
|
-
from .
|
9
|
+
from lamindb.models import Record
|
10
|
+
|
11
11
|
from .core._settings import settings
|
12
12
|
|
13
13
|
if TYPE_CHECKING:
|
14
|
-
from
|
14
|
+
from lamindb.base.types import StrField
|
15
15
|
|
16
16
|
|
17
17
|
class QueryManager(models.Manager):
|
lamindb/_query_set.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import re
|
4
|
+
import warnings
|
4
5
|
from collections import UserList
|
5
6
|
from collections.abc import Iterable
|
6
7
|
from collections.abc import Iterable as IterableType
|
@@ -12,17 +13,17 @@ from django.db.models import F, ForeignKey, ManyToManyField
|
|
12
13
|
from django.db.models.fields.related import ForeignObjectRel
|
13
14
|
from lamin_utils import logger
|
14
15
|
from lamindb_setup.core._docs import doc_args
|
15
|
-
|
16
|
+
|
17
|
+
from lamindb.models import (
|
16
18
|
Artifact,
|
17
19
|
CanCurate,
|
18
20
|
Collection,
|
19
21
|
Feature,
|
20
22
|
IsVersioned,
|
21
23
|
Record,
|
22
|
-
Registry,
|
23
24
|
Run,
|
25
|
+
Schema,
|
24
26
|
Transform,
|
25
|
-
VisibilityChoice,
|
26
27
|
)
|
27
28
|
|
28
29
|
from .core.exceptions import DoesNotExist
|
@@ -32,7 +33,7 @@ T = TypeVar("T")
|
|
32
33
|
if TYPE_CHECKING:
|
33
34
|
from collections.abc import Iterable
|
34
35
|
|
35
|
-
from
|
36
|
+
from lamindb.base.types import ListLike, StrField
|
36
37
|
|
37
38
|
|
38
39
|
class MultipleResultsFound(Exception):
|
@@ -79,6 +80,58 @@ def one_helper(self):
|
|
79
80
|
return self[0]
|
80
81
|
|
81
82
|
|
83
|
+
def get_backward_compat_filter_kwargs(queryset, expressions):
|
84
|
+
if queryset.model in {Collection, Transform}:
|
85
|
+
name_mappings = {
|
86
|
+
"name": "key",
|
87
|
+
"visibility": "_branch_code", # for convenience (and backward compat <1.0)
|
88
|
+
}
|
89
|
+
elif queryset.model == Artifact:
|
90
|
+
name_mappings = {
|
91
|
+
"n_objects": "n_files",
|
92
|
+
"visibility": "_branch_code", # for convenience (and backward compat <1.0)
|
93
|
+
"transform": "run__transform", # for convenience (and backward compat <1.0)
|
94
|
+
"feature_sets": "_schemas_m2m",
|
95
|
+
"type": "kind",
|
96
|
+
"_accessor": "otype",
|
97
|
+
}
|
98
|
+
elif queryset.model == Schema:
|
99
|
+
name_mappings = {
|
100
|
+
"registry": "itype",
|
101
|
+
"artifacts": "_artifacts_m2m", # will raise warning when we start to migrate over
|
102
|
+
}
|
103
|
+
else:
|
104
|
+
return expressions
|
105
|
+
was_list = False
|
106
|
+
if isinstance(expressions, list):
|
107
|
+
# make a dummy dictionary
|
108
|
+
was_list = True
|
109
|
+
expressions = {field: True for field in expressions}
|
110
|
+
mapped = {}
|
111
|
+
for field, value in expressions.items():
|
112
|
+
parts = field.split("__")
|
113
|
+
if parts[0] in name_mappings:
|
114
|
+
if parts[0] not in {
|
115
|
+
"transform",
|
116
|
+
"visibility",
|
117
|
+
"feature_sets",
|
118
|
+
"schemas",
|
119
|
+
"artifacts",
|
120
|
+
}:
|
121
|
+
warnings.warn(
|
122
|
+
f"{name_mappings[parts[0]]} is deprecated, please query for {parts[0]} instead",
|
123
|
+
DeprecationWarning,
|
124
|
+
stacklevel=2,
|
125
|
+
)
|
126
|
+
new_field = name_mappings[parts[0]] + (
|
127
|
+
"__" + "__".join(parts[1:]) if len(parts) > 1 else ""
|
128
|
+
)
|
129
|
+
mapped[new_field] = value
|
130
|
+
else:
|
131
|
+
mapped[field] = value
|
132
|
+
return list(mapped.keys()) if was_list else mapped
|
133
|
+
|
134
|
+
|
82
135
|
def process_expressions(queryset: QuerySet, expressions: dict) -> dict:
|
83
136
|
def _map_databases(value: Any, key: str, target_db: str) -> tuple[str, Any]:
|
84
137
|
if isinstance(value, Record):
|
@@ -105,23 +158,26 @@ def process_expressions(queryset: QuerySet, expressions: dict) -> dict:
|
|
105
158
|
|
106
159
|
return key, value
|
107
160
|
|
108
|
-
|
109
|
-
|
161
|
+
expressions = get_backward_compat_filter_kwargs(
|
162
|
+
queryset,
|
163
|
+
expressions,
|
164
|
+
)
|
165
|
+
|
166
|
+
if issubclass(queryset.model, Record):
|
167
|
+
# _branch_code is set to 0 unless expressions contains id or uid
|
110
168
|
if not (
|
111
169
|
"id" in expressions
|
112
170
|
or "uid" in expressions
|
113
171
|
or "uid__startswith" in expressions
|
114
172
|
):
|
115
|
-
|
116
|
-
if not any(e.startswith(
|
117
|
-
expressions[
|
118
|
-
|
119
|
-
) # default visibility
|
120
|
-
# if visibility is None, do not apply a filter
|
173
|
+
_branch_code = "_branch_code"
|
174
|
+
if not any(e.startswith(_branch_code) for e in expressions):
|
175
|
+
expressions[_branch_code] = 1 # default _branch_code
|
176
|
+
# if _branch_code is None, do not apply a filter
|
121
177
|
# otherwise, it would mean filtering for NULL values, which doesn't make
|
122
178
|
# sense for a non-NULLABLE column
|
123
|
-
elif
|
124
|
-
expressions.pop(
|
179
|
+
elif _branch_code in expressions and expressions[_branch_code] is None:
|
180
|
+
expressions.pop(_branch_code)
|
125
181
|
if queryset._db is not None:
|
126
182
|
# only check for database mismatch if there is a defined database on the
|
127
183
|
# queryset
|
@@ -213,6 +269,8 @@ def get_basic_field_names(
|
|
213
269
|
"created_at",
|
214
270
|
"created_by_id",
|
215
271
|
"updated_at",
|
272
|
+
"_aux",
|
273
|
+
"_branch_code",
|
216
274
|
]:
|
217
275
|
if field_name in field_names:
|
218
276
|
field_names.remove(field_name)
|
@@ -242,17 +300,17 @@ def get_feature_annotate_kwargs(show_features: bool | list[str]) -> dict[str, An
|
|
242
300
|
link_models_on_models = {
|
243
301
|
getattr(
|
244
302
|
Artifact, obj.related_name
|
245
|
-
).through.
|
303
|
+
).through.__get_name_with_module__(): obj.related_model.__get_name_with_module__()
|
246
304
|
for obj in Artifact._meta.related_objects
|
247
|
-
if obj.related_model.
|
305
|
+
if obj.related_model.__get_name_with_module__() in cat_feature_types
|
248
306
|
}
|
249
307
|
link_models_on_models["ArtifactULabel"] = "ULabel"
|
250
308
|
link_attributes_on_models = {
|
251
309
|
obj.related_name: link_models_on_models[
|
252
|
-
obj.related_model.
|
310
|
+
obj.related_model.__get_name_with_module__()
|
253
311
|
]
|
254
312
|
for obj in Artifact._meta.related_objects
|
255
|
-
if obj.related_model.
|
313
|
+
if obj.related_model.__get_name_with_module__() in link_models_on_models
|
256
314
|
}
|
257
315
|
# Prepare Django's annotate for features
|
258
316
|
annotate_kwargs = {}
|
@@ -478,7 +536,9 @@ class QuerySet(models.QuerySet):
|
|
478
536
|
include = []
|
479
537
|
elif isinstance(include, str):
|
480
538
|
include = [include]
|
539
|
+
include = get_backward_compat_filter_kwargs(self, include)
|
481
540
|
field_names = get_basic_field_names(self, include, features)
|
541
|
+
|
482
542
|
annotate_kwargs = {}
|
483
543
|
if features:
|
484
544
|
annotate_kwargs.update(get_feature_annotate_kwargs(features))
|
@@ -490,6 +550,7 @@ class QuerySet(models.QuerySet):
|
|
490
550
|
queryset = self.annotate(**annotate_kwargs)
|
491
551
|
else:
|
492
552
|
queryset = self
|
553
|
+
|
493
554
|
df = pd.DataFrame(queryset.values(*field_names, *list(annotate_kwargs.keys())))
|
494
555
|
if len(df) == 0:
|
495
556
|
df = pd.DataFrame({}, columns=field_names)
|
@@ -500,6 +561,12 @@ class QuerySet(models.QuerySet):
|
|
500
561
|
pk_column_name = pk_name if pk_name in df.columns else f"{pk_name}_id"
|
501
562
|
if pk_column_name in df_reshaped.columns:
|
502
563
|
df_reshaped = df_reshaped.set_index(pk_column_name)
|
564
|
+
|
565
|
+
# Compatibility code
|
566
|
+
df_reshaped.columns = df_reshaped.columns.str.replace(
|
567
|
+
r"_schemas_m2m", "feature_sets", regex=True
|
568
|
+
)
|
569
|
+
|
503
570
|
return df_reshaped
|
504
571
|
|
505
572
|
def delete(self, *args, **kwargs):
|