plexus-python-common 1.0.67__tar.gz → 1.0.69__tar.gz
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.
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/.github/workflows/pr.yml +2 -2
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/.github/workflows/push.yml +3 -3
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/PKG-INFO +1 -1
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/ormutils.py +28 -26
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/tagutils.py +168 -110
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus_python_common.egg-info/PKG-INFO +1 -1
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/test/plexus_tests/common/utils/tagutils_test.py +51 -30
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/.editorconfig +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/.gitignore +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/MANIFEST.in +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/README.md +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/VERSION +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/pyproject.toml +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/jsonutils/dummy.0.jsonl +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/jsonutils/dummy.1.jsonl +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/jsonutils/dummy.2.jsonl +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/0-dummy +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/1-dummy +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/2-dummy +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/dummy.0.0.jsonl +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/dummy.0.0.vol-0.jsonl +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/dummy.0.jsonl +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/dummy.1.1.jsonl +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/dummy.1.1.vol-1.jsonl +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/dummy.1.jsonl +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/dummy.2.2.jsonl +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/dummy.2.2.vol-2.jsonl +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/dummy.2.jsonl +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/dummy.csv.part0 +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/dummy.csv.part1 +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/dummy.csv.part2 +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/dummy.txt +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/s3utils/dir.baz/file.bar.baz +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/s3utils/dir.baz/file.foo.bar +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/s3utils/dir.baz/file.foo.baz +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/s3utils/dir.foo/dir.foo.bar/dir.foo.bar.baz/file.foo.bar.baz +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/s3utils/dir.foo/dir.foo.bar/file.bar.baz +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/s3utils/dir.foo/dir.foo.bar/file.foo.bar +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/s3utils/dir.foo/dir.foo.bar/file.foo.baz +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/s3utils/dir.foo/file.bar +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/s3utils/dir.foo/file.baz +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/s3utils/dir.foo/file.foo +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/s3utils_archive/archive.compressed.zip +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/s3utils_archive/archive.uncompressed.zip +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/setup.cfg +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/setup.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/__init__.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/carto/OSMFile.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/carto/OSMNode.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/carto/OSMTags.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/carto/OSMWay.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/carto/__init__.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/resources/__init__.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/resources/tags/__init__.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/resources/tags/unittest-1.0.0.tagset.yaml +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/resources/tags/universal-1.0.0.tagset.yaml +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/__init__.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/apiutils.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/bagutils.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/config.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/datautils.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/dockerutils.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/gisutils.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/jsonutils.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/pathutils.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/s3utils.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/sqlutils.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/strutils.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/testutils.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus_python_common.egg-info/SOURCES.txt +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus_python_common.egg-info/dependency_links.txt +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus_python_common.egg-info/not-zip-safe +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus_python_common.egg-info/requires.txt +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus_python_common.egg-info/top_level.txt +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/test/plexus_tests/__init__.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/test/plexus_tests/common/__init__.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/test/plexus_tests/common/carto/__init__.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/test/plexus_tests/common/carto/osm_file_test.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/test/plexus_tests/common/carto/osm_tags_test.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/test/plexus_tests/common/utils/__init__.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/test/plexus_tests/common/utils/bagutils_test.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/test/plexus_tests/common/utils/datautils_test.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/test/plexus_tests/common/utils/dockerutils_test.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/test/plexus_tests/common/utils/gisutils_test.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/test/plexus_tests/common/utils/jsonutils_test.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/test/plexus_tests/common/utils/ormutils_test.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/test/plexus_tests/common/utils/pathutils_test.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/test/plexus_tests/common/utils/s3utils_test.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/test/plexus_tests/common/utils/strutils_test.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/test/plexus_tests/common/utils/testutils_test.py +0 -0
- {plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/test/testenv.py +0 -0
|
@@ -18,10 +18,10 @@ jobs:
|
|
|
18
18
|
python-version: [ "3.12", "3.13", "3.14" ]
|
|
19
19
|
steps:
|
|
20
20
|
- name: Checkout
|
|
21
|
-
uses: actions/checkout@
|
|
21
|
+
uses: actions/checkout@v6
|
|
22
22
|
|
|
23
23
|
- name: Setup Python
|
|
24
|
-
uses: actions/setup-python@
|
|
24
|
+
uses: actions/setup-python@v6
|
|
25
25
|
with:
|
|
26
26
|
python-version: "${{ matrix.python-version }}"
|
|
27
27
|
|
|
@@ -15,10 +15,10 @@ jobs:
|
|
|
15
15
|
options: --user github
|
|
16
16
|
steps:
|
|
17
17
|
- name: Checkout
|
|
18
|
-
uses: actions/checkout@
|
|
18
|
+
uses: actions/checkout@v6
|
|
19
19
|
|
|
20
20
|
- name: Setup Python
|
|
21
|
-
uses: actions/setup-python@
|
|
21
|
+
uses: actions/setup-python@v6
|
|
22
22
|
with:
|
|
23
23
|
python-version: "3.14"
|
|
24
24
|
|
|
@@ -31,7 +31,7 @@ jobs:
|
|
|
31
31
|
python -m twine upload --username __token__ --password ${{ secrets.PYPI_TOKEN }} dist/*
|
|
32
32
|
|
|
33
33
|
- name: Upload Coverage Report
|
|
34
|
-
uses: codecov/codecov-action@
|
|
34
|
+
uses: codecov/codecov-action@v6
|
|
35
35
|
with:
|
|
36
36
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
37
37
|
slug: ${{ github.repository }}
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/ormutils.py
RENAMED
|
@@ -1092,12 +1092,12 @@ def db_read_sequence_models[SequenceModelT: SequenceModelMixin](
|
|
|
1092
1092
|
limit: int | None = None,
|
|
1093
1093
|
order_by: list[str] | None = None,
|
|
1094
1094
|
) -> list[SequenceModelT]:
|
|
1095
|
-
|
|
1095
|
+
query_stmt = db.query(model).order_by(*db_make_order_by_clause(model, order_by))
|
|
1096
1096
|
if skip is not None:
|
|
1097
|
-
|
|
1097
|
+
query_stmt = query_stmt.offset(skip)
|
|
1098
1098
|
if limit is not None:
|
|
1099
|
-
|
|
1100
|
-
return
|
|
1099
|
+
query_stmt = query_stmt.limit(limit)
|
|
1100
|
+
return query_stmt.all()
|
|
1101
1101
|
|
|
1102
1102
|
|
|
1103
1103
|
def db_update_sequence_model[SequenceModelT: SequenceModelMixin](
|
|
@@ -1285,7 +1285,7 @@ def db_read_latest_snapshot_models[SnapshotModelT: SnapshotModelMixin](
|
|
|
1285
1285
|
limit: int | None = None,
|
|
1286
1286
|
order_by: list[str] | None = None,
|
|
1287
1287
|
) -> list[SnapshotModelT]:
|
|
1288
|
-
|
|
1288
|
+
subquery_stmt = (
|
|
1289
1289
|
db
|
|
1290
1290
|
.query(model.record_sqn,
|
|
1291
1291
|
sa.func.max(model.created_at).label("max_created_at"))
|
|
@@ -1293,18 +1293,19 @@ def db_read_latest_snapshot_models[SnapshotModelT: SnapshotModelMixin](
|
|
|
1293
1293
|
.subquery()
|
|
1294
1294
|
)
|
|
1295
1295
|
|
|
1296
|
-
|
|
1296
|
+
query_stmt = (
|
|
1297
1297
|
db
|
|
1298
1298
|
.query(model)
|
|
1299
|
-
.join(
|
|
1300
|
-
sa.and_(model.record_sqn ==
|
|
1299
|
+
.join(subquery_stmt,
|
|
1300
|
+
sa.and_(model.record_sqn == subquery_stmt.c.record_sqn,
|
|
1301
|
+
model.created_at == subquery_stmt.c.max_created_at))
|
|
1301
1302
|
.order_by(*db_make_order_by_clause(model, order_by))
|
|
1302
1303
|
)
|
|
1303
1304
|
if skip is not None:
|
|
1304
|
-
|
|
1305
|
+
query_stmt = query_stmt.offset(skip)
|
|
1305
1306
|
if limit is not None:
|
|
1306
|
-
|
|
1307
|
-
return
|
|
1307
|
+
query_stmt = query_stmt.limit(limit)
|
|
1308
|
+
return query_stmt.all()
|
|
1308
1309
|
|
|
1309
1310
|
|
|
1310
1311
|
def db_read_active_snapshot_models[SnapshotModelT: SnapshotModelMixin](
|
|
@@ -1314,12 +1315,12 @@ def db_read_active_snapshot_models[SnapshotModelT: SnapshotModelMixin](
|
|
|
1314
1315
|
limit: int | None = None,
|
|
1315
1316
|
order_by: list[str] | None = None,
|
|
1316
1317
|
) -> list[SnapshotModelT]:
|
|
1317
|
-
|
|
1318
|
+
query_stmt = db.query(model).where(model.expired_at.is_(None)).order_by(*db_make_order_by_clause(model, order_by))
|
|
1318
1319
|
if skip is not None:
|
|
1319
|
-
|
|
1320
|
+
query_stmt = query_stmt.offset(skip)
|
|
1320
1321
|
if limit is not None:
|
|
1321
|
-
|
|
1322
|
-
return
|
|
1322
|
+
query_stmt = query_stmt.limit(limit)
|
|
1323
|
+
return query_stmt.all()
|
|
1323
1324
|
|
|
1324
1325
|
|
|
1325
1326
|
def db_update_snapshot_model[SnapshotModelT: SnapshotModelMixin](
|
|
@@ -1512,7 +1513,7 @@ def db_read_latest_revision_models[RevisionModelT: RevisionModelMixin](
|
|
|
1512
1513
|
limit: int | None = None,
|
|
1513
1514
|
order_by: list[str] | None = None,
|
|
1514
1515
|
) -> list[RevisionModelT]:
|
|
1515
|
-
|
|
1516
|
+
subquery_stmt = (
|
|
1516
1517
|
db
|
|
1517
1518
|
.query(model.record_sqn,
|
|
1518
1519
|
sa.func.max(model.revision).label("max_revision"))
|
|
@@ -1520,18 +1521,19 @@ def db_read_latest_revision_models[RevisionModelT: RevisionModelMixin](
|
|
|
1520
1521
|
.subquery()
|
|
1521
1522
|
)
|
|
1522
1523
|
|
|
1523
|
-
|
|
1524
|
+
query_stmt = (
|
|
1524
1525
|
db
|
|
1525
1526
|
.query(model)
|
|
1526
|
-
.join(
|
|
1527
|
-
sa.and_(model.record_sqn ==
|
|
1527
|
+
.join(subquery_stmt,
|
|
1528
|
+
sa.and_(model.record_sqn == subquery_stmt.c.record_sqn,
|
|
1529
|
+
model.revision == subquery_stmt.c.max_revision))
|
|
1528
1530
|
.order_by(*db_make_order_by_clause(model, order_by))
|
|
1529
1531
|
)
|
|
1530
1532
|
if skip is not None:
|
|
1531
|
-
|
|
1533
|
+
query_stmt = query_stmt.offset(skip)
|
|
1532
1534
|
if limit is not None:
|
|
1533
|
-
|
|
1534
|
-
return
|
|
1535
|
+
query_stmt = query_stmt.limit(limit)
|
|
1536
|
+
return query_stmt.all()
|
|
1535
1537
|
|
|
1536
1538
|
|
|
1537
1539
|
def db_read_active_revision_models[RevisionModelT: RevisionModelMixin](
|
|
@@ -1541,12 +1543,12 @@ def db_read_active_revision_models[RevisionModelT: RevisionModelMixin](
|
|
|
1541
1543
|
limit: int | None = None,
|
|
1542
1544
|
order_by: list[str] | None = None,
|
|
1543
1545
|
) -> list[RevisionModelT]:
|
|
1544
|
-
|
|
1546
|
+
query_stmt = db.query(model).where(model.expired_at.is_(None)).order_by(*db_make_order_by_clause(model, order_by))
|
|
1545
1547
|
if skip is not None:
|
|
1546
|
-
|
|
1548
|
+
query_stmt = query_stmt.offset(skip)
|
|
1547
1549
|
if limit is not None:
|
|
1548
|
-
|
|
1549
|
-
return
|
|
1550
|
+
query_stmt = query_stmt.limit(limit)
|
|
1551
|
+
return query_stmt.all()
|
|
1550
1552
|
|
|
1551
1553
|
|
|
1552
1554
|
def db_update_revision_model[RevisionModelT: RevisionModelMixin](
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/tagutils.py
RENAMED
|
@@ -645,21 +645,21 @@ class TagCache(object):
|
|
|
645
645
|
end_dt: datetime.datetime | None = None,
|
|
646
646
|
) -> list[TagTargetTable]:
|
|
647
647
|
with self.make_session() as session:
|
|
648
|
-
|
|
648
|
+
query_stmt = session.query(TagTargetTable)
|
|
649
649
|
if identifier:
|
|
650
|
-
|
|
650
|
+
query_stmt = query_stmt.filter(TagTargetTable.identifier == identifier)
|
|
651
651
|
if tagger_name:
|
|
652
|
-
|
|
652
|
+
query_stmt = query_stmt.filter(TagTargetTable.tagger_name == tagger_name)
|
|
653
653
|
if tagger_version:
|
|
654
|
-
|
|
654
|
+
query_stmt = query_stmt.filter(TagTargetTable.tagger_version == tagger_version)
|
|
655
655
|
if vehicle_name:
|
|
656
|
-
|
|
656
|
+
query_stmt = query_stmt.filter(TagTargetTable.vehicle_name == vehicle_name)
|
|
657
657
|
if begin_dt:
|
|
658
|
-
|
|
658
|
+
query_stmt = query_stmt.filter(TagTargetTable.end_dt >= begin_dt)
|
|
659
659
|
if end_dt:
|
|
660
|
-
|
|
660
|
+
query_stmt = query_stmt.filter(TagTargetTable.begin_dt <= end_dt)
|
|
661
661
|
|
|
662
|
-
return
|
|
662
|
+
return query_stmt.all()
|
|
663
663
|
|
|
664
664
|
def add_target(
|
|
665
665
|
self,
|
|
@@ -671,7 +671,7 @@ class TagCache(object):
|
|
|
671
671
|
end_dt: datetime.datetime,
|
|
672
672
|
) -> TagTargetTable:
|
|
673
673
|
with self.make_session() as session:
|
|
674
|
-
|
|
674
|
+
tag_target = TagTarget(
|
|
675
675
|
identifier=identifier,
|
|
676
676
|
tagger_name=tagger_name,
|
|
677
677
|
tagger_version=tagger_version,
|
|
@@ -679,8 +679,8 @@ class TagCache(object):
|
|
|
679
679
|
begin_dt=begin_dt,
|
|
680
680
|
end_dt=end_dt,
|
|
681
681
|
)
|
|
682
|
-
|
|
683
|
-
session.add(
|
|
682
|
+
db_tag_target = clone_sequence_model_instance(TagTargetTable, tag_target)
|
|
683
|
+
session.add(db_tag_target)
|
|
684
684
|
session.commit()
|
|
685
685
|
|
|
686
686
|
return self.get_target(identifier)
|
|
@@ -695,21 +695,21 @@ class TagCache(object):
|
|
|
695
695
|
end_dt: datetime.datetime | None = None,
|
|
696
696
|
):
|
|
697
697
|
with self.make_session() as session:
|
|
698
|
-
|
|
698
|
+
query_stmt = session.query(TagTargetTable)
|
|
699
699
|
if identifier:
|
|
700
|
-
|
|
700
|
+
query_stmt = query_stmt.filter(TagTargetTable.identifier == identifier)
|
|
701
701
|
if tagger_name:
|
|
702
|
-
|
|
702
|
+
query_stmt = query_stmt.filter(TagTargetTable.tagger_name == tagger_name)
|
|
703
703
|
if tagger_version:
|
|
704
|
-
|
|
704
|
+
query_stmt = query_stmt.filter(TagTargetTable.tagger_version == tagger_version)
|
|
705
705
|
if vehicle_name:
|
|
706
|
-
|
|
706
|
+
query_stmt = query_stmt.filter(TagTargetTable.vehicle_name == vehicle_name)
|
|
707
707
|
if begin_dt:
|
|
708
|
-
|
|
708
|
+
query_stmt = query_stmt.filter(TagTargetTable.end_dt >= begin_dt)
|
|
709
709
|
if end_dt:
|
|
710
|
-
|
|
710
|
+
query_stmt = query_stmt.filter(TagTargetTable.begin_dt <= end_dt)
|
|
711
711
|
|
|
712
|
-
|
|
712
|
+
query_stmt.delete()
|
|
713
713
|
session.commit()
|
|
714
714
|
|
|
715
715
|
(
|
|
@@ -721,12 +721,16 @@ class TagCache(object):
|
|
|
721
721
|
session.commit()
|
|
722
722
|
|
|
723
723
|
def with_target(self, target: int | str) -> "TargetedTagCache":
|
|
724
|
-
|
|
725
|
-
if
|
|
726
|
-
raise ValueError(f"target '{target}' not found in cache")
|
|
727
|
-
return TargetedTagCache(cache=self,
|
|
724
|
+
db_tag_target = self.get_target(target)
|
|
725
|
+
if db_tag_target is None:
|
|
726
|
+
raise ValueError(f"tag target '{target}' not found in cache")
|
|
727
|
+
return TargetedTagCache(cache=self, tag_target=db_tag_target)
|
|
728
728
|
|
|
729
|
-
def
|
|
729
|
+
def count_records(self) -> int:
|
|
730
|
+
with self.make_session() as session:
|
|
731
|
+
return session.query(sa.func.count(TagRecordTable.sqn)).scalar()
|
|
732
|
+
|
|
733
|
+
def iter_records(
|
|
730
734
|
self,
|
|
731
735
|
begin_dt: datetime.datetime | None = None,
|
|
732
736
|
end_dt: datetime.datetime | None = None,
|
|
@@ -736,6 +740,8 @@ class TagCache(object):
|
|
|
736
740
|
*,
|
|
737
741
|
tagsets: Sequence[Tagset] | None = None,
|
|
738
742
|
tagset_inverted: bool = False,
|
|
743
|
+
skip: int | None = None,
|
|
744
|
+
limit: int | None = None,
|
|
739
745
|
batch_size: int = 1000,
|
|
740
746
|
) -> Generator[TagRecordTable, None, None]:
|
|
741
747
|
"""
|
|
@@ -749,33 +755,41 @@ class TagCache(object):
|
|
|
749
755
|
:param tagsets: Filter by tagsets (match tags that are in any of the specified tagsets)
|
|
750
756
|
:param tagset_inverted: Whether to invert the tagset filter (match tags that are NOT in any of the specified
|
|
751
757
|
tagsets)
|
|
758
|
+
:param skip: Number of records to skip (for pagination)
|
|
759
|
+
:param limit: Maximum number of records to return (for pagination)
|
|
752
760
|
:param batch_size: Number of records to fetch per batch from the database (for memory efficiency)
|
|
753
761
|
:return: Generator of ``TagRecordTable`` instances that match the filters
|
|
754
762
|
"""
|
|
755
763
|
with self.make_session() as session:
|
|
756
|
-
|
|
764
|
+
query_stmt = session.query(TagRecordTable)
|
|
757
765
|
if begin_dt:
|
|
758
|
-
|
|
766
|
+
query_stmt = query_stmt.filter(TagRecordTable.end_dt >= begin_dt)
|
|
759
767
|
if end_dt:
|
|
760
|
-
|
|
768
|
+
query_stmt = query_stmt.filter(TagRecordTable.begin_dt <= end_dt)
|
|
761
769
|
if tagset_namespace:
|
|
762
|
-
|
|
770
|
+
query_stmt = query_stmt.filter(TagRecordTable.tagset_namespace == tagset_namespace)
|
|
763
771
|
if tagset_version:
|
|
764
|
-
|
|
772
|
+
query_stmt = query_stmt.filter(TagRecordTable.tagset_version == tagset_version)
|
|
765
773
|
if tag_prefix:
|
|
766
|
-
|
|
774
|
+
query_stmt = query_stmt.filter(TagRecordTable.tag.like(f"{escape_sql_like(tag_prefix)}%", escape="\\"))
|
|
767
775
|
if tagsets:
|
|
768
776
|
if tagset_inverted:
|
|
769
|
-
|
|
777
|
+
query_stmt = query_stmt.filter(
|
|
770
778
|
TagRecordTable.tag.notin_([tag_name for tagset in tagsets for tag_name in tagset.tag_names]))
|
|
771
779
|
else:
|
|
772
|
-
|
|
780
|
+
query_stmt = query_stmt.filter(
|
|
773
781
|
TagRecordTable.tag.in_([tag_name for tagset in tagsets for tag_name in tagset.tag_names]))
|
|
774
|
-
|
|
775
|
-
|
|
782
|
+
if skip is not None or limit is not None:
|
|
783
|
+
query_stmt = query_stmt.order_by(TagRecordTable.sqn.desc())
|
|
784
|
+
if skip is not None:
|
|
785
|
+
query_stmt = query_stmt.offset(skip)
|
|
786
|
+
if limit is not None:
|
|
787
|
+
query_stmt = query_stmt.limit(limit)
|
|
788
|
+
|
|
789
|
+
for result in query_stmt.yield_per(batch_size):
|
|
776
790
|
yield result
|
|
777
791
|
|
|
778
|
-
def
|
|
792
|
+
def iter_record_and_targets(
|
|
779
793
|
self,
|
|
780
794
|
begin_dt: datetime.datetime | None = None,
|
|
781
795
|
end_dt: datetime.datetime | None = None,
|
|
@@ -791,10 +805,12 @@ class TagCache(object):
|
|
|
791
805
|
target_end_dt: datetime.datetime | None = None,
|
|
792
806
|
tagsets: Sequence[Tagset] | None = None,
|
|
793
807
|
tagset_inverted: bool = False,
|
|
808
|
+
skip: int | None = None,
|
|
809
|
+
limit: int | None = None,
|
|
794
810
|
batch_size: int = 1000,
|
|
795
811
|
) -> Generator[tuple[TagRecordTable, TagTargetTable], None, None]:
|
|
796
812
|
"""
|
|
797
|
-
Query tag records along with their target
|
|
813
|
+
Query tag records along with their target in the cache with optional filters.
|
|
798
814
|
|
|
799
815
|
:param begin_dt: Filter by begin time (inclusive)
|
|
800
816
|
:param end_dt: Filter by end time (inclusive)
|
|
@@ -810,49 +826,57 @@ class TagCache(object):
|
|
|
810
826
|
:param tagsets: Filter by tagsets (match tags that are in any of the specified tagsets)
|
|
811
827
|
:param tagset_inverted: Whether to invert the tagset filter (match tags that are NOT in any of the specified
|
|
812
828
|
tagsets)
|
|
829
|
+
:param skip: Number of records to skip (for pagination)
|
|
830
|
+
:param limit: Maximum number of records to return (for pagination)
|
|
813
831
|
:param batch_size: Number of records to fetch per batch from the database (for memory efficiency)
|
|
814
832
|
:return: Generator of ``TagRecordTable`` instances that match the filters
|
|
815
833
|
"""
|
|
816
834
|
with self.make_session() as session:
|
|
817
|
-
|
|
835
|
+
query_stmt = (
|
|
818
836
|
session
|
|
819
837
|
.query(TagRecordTable, TagTargetTable)
|
|
820
838
|
.join(TagTargetTable, TagRecordTable.target_sqn == TagTargetTable.sqn)
|
|
821
839
|
)
|
|
822
840
|
if begin_dt:
|
|
823
|
-
|
|
841
|
+
query_stmt = query_stmt.filter(TagRecordTable.end_dt >= begin_dt)
|
|
824
842
|
if end_dt:
|
|
825
|
-
|
|
843
|
+
query_stmt = query_stmt.filter(TagRecordTable.begin_dt <= end_dt)
|
|
826
844
|
if tagset_namespace:
|
|
827
|
-
|
|
845
|
+
query_stmt = query_stmt.filter(TagRecordTable.tagset_namespace == tagset_namespace)
|
|
828
846
|
if tagset_version:
|
|
829
|
-
|
|
847
|
+
query_stmt = query_stmt.filter(TagRecordTable.tagset_version == tagset_version)
|
|
830
848
|
if tag_prefix:
|
|
831
|
-
|
|
849
|
+
query_stmt = query_stmt.filter(TagRecordTable.tag.like(f"{escape_sql_like(tag_prefix)}%", escape="\\"))
|
|
832
850
|
if target_identifier:
|
|
833
|
-
|
|
851
|
+
query_stmt = query_stmt.filter(TagTargetTable.identifier == target_identifier)
|
|
834
852
|
if target_tagger_name:
|
|
835
|
-
|
|
853
|
+
query_stmt = query_stmt.filter(TagTargetTable.tagger_name == target_tagger_name)
|
|
836
854
|
if target_tagger_version:
|
|
837
|
-
|
|
855
|
+
query_stmt = query_stmt.filter(TagTargetTable.tagger_version == target_tagger_version)
|
|
838
856
|
if target_vehicle_name:
|
|
839
|
-
|
|
857
|
+
query_stmt = query_stmt.filter(TagTargetTable.vehicle_name == target_vehicle_name)
|
|
840
858
|
if target_begin_dt:
|
|
841
|
-
|
|
859
|
+
query_stmt = query_stmt.filter(TagTargetTable.end_dt >= target_begin_dt)
|
|
842
860
|
if target_end_dt:
|
|
843
|
-
|
|
861
|
+
query_stmt = query_stmt.filter(TagTargetTable.begin_dt <= target_end_dt)
|
|
844
862
|
if tagsets:
|
|
845
863
|
if tagset_inverted:
|
|
846
|
-
|
|
864
|
+
query_stmt = query_stmt.filter(
|
|
847
865
|
TagRecordTable.tag.notin_([tag_name for tagset in tagsets for tag_name in tagset.tag_names]))
|
|
848
866
|
else:
|
|
849
|
-
|
|
867
|
+
query_stmt = query_stmt.filter(
|
|
850
868
|
TagRecordTable.tag.in_([tag_name for tagset in tagsets for tag_name in tagset.tag_names]))
|
|
851
|
-
|
|
852
|
-
|
|
869
|
+
if skip is not None or limit is not None:
|
|
870
|
+
query_stmt = query_stmt.order_by(TagRecordTable.sqn.desc())
|
|
871
|
+
if skip is not None:
|
|
872
|
+
query_stmt = query_stmt.offset(skip)
|
|
873
|
+
if limit is not None:
|
|
874
|
+
query_stmt = query_stmt.limit(limit)
|
|
875
|
+
|
|
876
|
+
for result in query_stmt.yield_per(batch_size):
|
|
853
877
|
yield result
|
|
854
878
|
|
|
855
|
-
def
|
|
879
|
+
def remove_records(
|
|
856
880
|
self,
|
|
857
881
|
begin_dt: datetime.datetime | None = None,
|
|
858
882
|
end_dt: datetime.datetime | None = None,
|
|
@@ -876,26 +900,26 @@ class TagCache(object):
|
|
|
876
900
|
tagsets)
|
|
877
901
|
"""
|
|
878
902
|
with self.make_session() as session:
|
|
879
|
-
|
|
903
|
+
query_stmt = session.query(TagRecordTable)
|
|
880
904
|
if begin_dt:
|
|
881
|
-
|
|
905
|
+
query_stmt = query_stmt.filter(TagRecordTable.end_dt >= begin_dt)
|
|
882
906
|
if end_dt:
|
|
883
|
-
|
|
907
|
+
query_stmt = query_stmt.filter(TagRecordTable.begin_dt <= end_dt)
|
|
884
908
|
if tagset_namespace:
|
|
885
|
-
|
|
909
|
+
query_stmt = query_stmt.filter(TagRecordTable.tagset_namespace == tagset_namespace)
|
|
886
910
|
if tagset_version:
|
|
887
|
-
|
|
911
|
+
query_stmt = query_stmt.filter(TagRecordTable.tagset_version == tagset_version)
|
|
888
912
|
if tag_prefix:
|
|
889
|
-
|
|
913
|
+
query_stmt = query_stmt.filter(TagRecordTable.tag.like(f"{escape_sql_like(tag_prefix)}%", escape="\\"))
|
|
890
914
|
if tagsets:
|
|
891
915
|
if tagset_inverted:
|
|
892
|
-
|
|
916
|
+
query_stmt = query_stmt.filter(
|
|
893
917
|
TagRecordTable.tag.notin_([tag_name for tagset in tagsets for tag_name in tagset.tag_names]))
|
|
894
918
|
else:
|
|
895
|
-
|
|
919
|
+
query_stmt = query_stmt.filter(
|
|
896
920
|
TagRecordTable.tag.in_([tag_name for tagset in tagsets for tag_name in tagset.tag_names]))
|
|
897
921
|
|
|
898
|
-
|
|
922
|
+
query_stmt.delete()
|
|
899
923
|
session.commit()
|
|
900
924
|
|
|
901
925
|
def clear(self):
|
|
@@ -924,42 +948,59 @@ class TagCache(object):
|
|
|
924
948
|
return
|
|
925
949
|
|
|
926
950
|
with src.make_session() as src_session, dst.make_session() as dst_session:
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
clone_sequence_model_instance(TagTargetTable,
|
|
930
|
-
for
|
|
951
|
+
src_db_tag_targets = src_session.query(TagTargetTable).all()
|
|
952
|
+
dst_db_tag_targets = [
|
|
953
|
+
clone_sequence_model_instance(TagTargetTable, db_tag_target, clear_meta_fields=True)
|
|
954
|
+
for db_tag_target in src_db_tag_targets
|
|
931
955
|
]
|
|
932
|
-
dst_session.add_all(
|
|
956
|
+
dst_session.add_all(dst_db_tag_targets)
|
|
933
957
|
dst_session.flush() # ensure new sqn values are assigned
|
|
934
958
|
|
|
935
|
-
sqn_map = {
|
|
959
|
+
sqn_map = {src_db_tag_target.sqn: dst_db_tag_target.sqn
|
|
960
|
+
for src_db_tag_target, dst_db_tag_target in zip(src_db_tag_targets, dst_db_tag_targets)}
|
|
936
961
|
|
|
937
|
-
for
|
|
938
|
-
|
|
939
|
-
for db_tag_record in
|
|
940
|
-
|
|
962
|
+
for db_tag_records in batched(src_session.query(TagRecordTable).yield_per(1000), 1000):
|
|
963
|
+
cloned_db_tag_records = []
|
|
964
|
+
for db_tag_record in db_tag_records:
|
|
965
|
+
cloned_db_tag_record = clone_sequence_model_instance(TagRecordTable,
|
|
966
|
+
db_tag_record,
|
|
967
|
+
clear_meta_fields=True)
|
|
941
968
|
try:
|
|
942
|
-
|
|
969
|
+
cloned_db_tag_record.target_sqn = sqn_map[db_tag_record.target_sqn]
|
|
943
970
|
except KeyError as e:
|
|
944
|
-
raise ValueError(f"no cloned target for target_sqn '{db_tag_record.target_sqn}'") from e
|
|
945
|
-
|
|
946
|
-
dst_session.add_all(
|
|
971
|
+
raise ValueError(f"no cloned tag target for target_sqn '{db_tag_record.target_sqn}'") from e
|
|
972
|
+
cloned_db_tag_records.append(cloned_db_tag_record)
|
|
973
|
+
dst_session.add_all(cloned_db_tag_records)
|
|
947
974
|
dst_session.commit()
|
|
948
975
|
|
|
976
|
+
count_tags = count_records
|
|
977
|
+
iter_tags = iter_records
|
|
978
|
+
iter_tag_and_targets = iter_record_and_targets
|
|
979
|
+
remove_tags = remove_records
|
|
980
|
+
|
|
949
981
|
|
|
950
982
|
class TargetedTagCache(object):
|
|
951
|
-
def __init__(self, cache: TagCache,
|
|
952
|
-
self.target_info = target_info
|
|
983
|
+
def __init__(self, cache: TagCache, tag_target: TagTargetTable):
|
|
953
984
|
self.cache = cache
|
|
985
|
+
self.tag_target = tag_target
|
|
954
986
|
|
|
955
987
|
@contextlib.contextmanager
|
|
956
988
|
def make_session(self) -> Generator[sa_orm.Session, None, None]:
|
|
957
989
|
with self.cache.make_session() as session:
|
|
958
|
-
if not session.query(TagTargetTable).filter(TagTargetTable.sqn == self.
|
|
959
|
-
raise ValueError(f"target
|
|
990
|
+
if not session.query(TagTargetTable).filter(TagTargetTable.sqn == self.tag_target.sqn).first():
|
|
991
|
+
raise ValueError(f"tag target with sqn '{self.tag_target.sqn}' is no longer present in cache")
|
|
960
992
|
yield session
|
|
961
993
|
|
|
962
|
-
def
|
|
994
|
+
def count_records(self) -> int:
|
|
995
|
+
with self.make_session() as session:
|
|
996
|
+
return (
|
|
997
|
+
session
|
|
998
|
+
.query(sa.func.count(TagRecordTable.sqn))
|
|
999
|
+
.filter(TagRecordTable.target_sqn == self.tag_target.sqn)
|
|
1000
|
+
.scalar()
|
|
1001
|
+
)
|
|
1002
|
+
|
|
1003
|
+
def iter_records(
|
|
963
1004
|
self,
|
|
964
1005
|
begin_dt: datetime.datetime | None = None,
|
|
965
1006
|
end_dt: datetime.datetime | None = None,
|
|
@@ -969,6 +1010,8 @@ class TargetedTagCache(object):
|
|
|
969
1010
|
*,
|
|
970
1011
|
tagsets: Sequence[Tagset] | None = None,
|
|
971
1012
|
tagset_inverted: bool = False,
|
|
1013
|
+
skip: int | None = None,
|
|
1014
|
+
limit: int | None = None,
|
|
972
1015
|
batch_size: int = 1000,
|
|
973
1016
|
) -> Generator[TagRecordTable, None, None]:
|
|
974
1017
|
"""
|
|
@@ -982,34 +1025,42 @@ class TargetedTagCache(object):
|
|
|
982
1025
|
:param tagsets: Filter by tagsets (match tags that are in any of the specified tagsets)
|
|
983
1026
|
:param tagset_inverted: Whether to invert the tagset filter (match tags that are NOT in any of the specified
|
|
984
1027
|
tagsets)
|
|
1028
|
+
:param skip: Number of records to skip (for pagination)
|
|
1029
|
+
:param limit: Maximum number of records to return (for pagination)
|
|
985
1030
|
:param batch_size: Number of records to fetch per batch from the database (for memory efficiency)
|
|
986
1031
|
:return: Generator of ``TagRecordTable`` instances that match the filters
|
|
987
1032
|
"""
|
|
988
1033
|
|
|
989
1034
|
with self.make_session() as session:
|
|
990
|
-
|
|
1035
|
+
query_stmt = session.query(TagRecordTable).filter(TagRecordTable.target_sqn == self.tag_target.sqn)
|
|
991
1036
|
if begin_dt:
|
|
992
|
-
|
|
1037
|
+
query_stmt = query_stmt.filter(TagRecordTable.end_dt >= begin_dt)
|
|
993
1038
|
if end_dt:
|
|
994
|
-
|
|
1039
|
+
query_stmt = query_stmt.filter(TagRecordTable.begin_dt <= end_dt)
|
|
995
1040
|
if tagset_namespace:
|
|
996
|
-
|
|
1041
|
+
query_stmt = query_stmt.filter(TagRecordTable.tagset_namespace == tagset_namespace)
|
|
997
1042
|
if tagset_version:
|
|
998
|
-
|
|
1043
|
+
query_stmt = query_stmt.filter(TagRecordTable.tagset_version == tagset_version)
|
|
999
1044
|
if tag_prefix:
|
|
1000
|
-
|
|
1045
|
+
query_stmt = query_stmt.filter(TagRecordTable.tag.like(f"{escape_sql_like(tag_prefix)}%", escape="\\"))
|
|
1001
1046
|
if tagsets:
|
|
1002
1047
|
if tagset_inverted:
|
|
1003
|
-
|
|
1048
|
+
query_stmt = query_stmt.filter(
|
|
1004
1049
|
TagRecordTable.tag.notin_([tag_name for tagset in tagsets for tag_name in tagset.tag_names]))
|
|
1005
1050
|
else:
|
|
1006
|
-
|
|
1051
|
+
query_stmt = query_stmt.filter(
|
|
1007
1052
|
TagRecordTable.tag.in_([tag_name for tagset in tagsets for tag_name in tagset.tag_names]))
|
|
1008
|
-
|
|
1009
|
-
|
|
1053
|
+
if skip is not None or limit is not None:
|
|
1054
|
+
query_stmt = query_stmt.order_by(TagRecordTable.sqn.desc())
|
|
1055
|
+
if skip is not None:
|
|
1056
|
+
query_stmt = query_stmt.offset(skip)
|
|
1057
|
+
if limit is not None:
|
|
1058
|
+
query_stmt = query_stmt.limit(limit)
|
|
1059
|
+
|
|
1060
|
+
for result in query_stmt.yield_per(batch_size):
|
|
1010
1061
|
yield result
|
|
1011
1062
|
|
|
1012
|
-
def
|
|
1063
|
+
def add_ranged_record(
|
|
1013
1064
|
self,
|
|
1014
1065
|
begin_dt: datetime.datetime | None,
|
|
1015
1066
|
end_dt: datetime.datetime | None,
|
|
@@ -1036,9 +1087,9 @@ class TargetedTagCache(object):
|
|
|
1036
1087
|
"""
|
|
1037
1088
|
with self.make_session() as session:
|
|
1038
1089
|
tag_record = TagRecord(
|
|
1039
|
-
target_sqn=self.
|
|
1040
|
-
begin_dt=begin_dt or self.
|
|
1041
|
-
end_dt=end_dt or self.
|
|
1090
|
+
target_sqn=self.tag_target.sqn,
|
|
1091
|
+
begin_dt=begin_dt or self.tag_target.begin_dt,
|
|
1092
|
+
end_dt=end_dt or self.tag_target.end_dt,
|
|
1042
1093
|
tagset_namespace=tag.namespace if isinstance(tag, BoundTag) else tagset_namespace,
|
|
1043
1094
|
tagset_version=tag.version if isinstance(tag, BoundTag) else tagset_version,
|
|
1044
1095
|
tag=tag.name if isinstance(tag, Tag) else tag,
|
|
@@ -1050,7 +1101,7 @@ class TargetedTagCache(object):
|
|
|
1050
1101
|
|
|
1051
1102
|
return chainable(self, db_tag_record)
|
|
1052
1103
|
|
|
1053
|
-
def
|
|
1104
|
+
def add_record(
|
|
1054
1105
|
self,
|
|
1055
1106
|
tag: str | Tag | BoundTag,
|
|
1056
1107
|
props: JsonType | None = None,
|
|
@@ -1071,16 +1122,16 @@ class TargetedTagCache(object):
|
|
|
1071
1122
|
will be used.
|
|
1072
1123
|
:return: Self instance for chaining
|
|
1073
1124
|
"""
|
|
1074
|
-
return self.
|
|
1075
|
-
begin_dt=self.
|
|
1076
|
-
end_dt=self.
|
|
1125
|
+
return self.add_ranged_record(
|
|
1126
|
+
begin_dt=self.tag_target.begin_dt,
|
|
1127
|
+
end_dt=self.tag_target.end_dt,
|
|
1077
1128
|
tag=tag,
|
|
1078
1129
|
tagset_namespace=tagset_namespace,
|
|
1079
1130
|
tagset_version=tagset_version,
|
|
1080
1131
|
props=props,
|
|
1081
1132
|
)
|
|
1082
1133
|
|
|
1083
|
-
def
|
|
1134
|
+
def update_record(
|
|
1084
1135
|
self,
|
|
1085
1136
|
sqn: int,
|
|
1086
1137
|
*,
|
|
@@ -1134,7 +1185,7 @@ class TargetedTagCache(object):
|
|
|
1134
1185
|
|
|
1135
1186
|
return chainable(self, db_tag_record)
|
|
1136
1187
|
|
|
1137
|
-
def
|
|
1188
|
+
def remove_records(
|
|
1138
1189
|
self,
|
|
1139
1190
|
begin_dt: datetime.datetime | None = None,
|
|
1140
1191
|
end_dt: datetime.datetime | None = None,
|
|
@@ -1159,30 +1210,37 @@ class TargetedTagCache(object):
|
|
|
1159
1210
|
:return: Self instance for chaining
|
|
1160
1211
|
"""
|
|
1161
1212
|
with self.make_session() as session:
|
|
1162
|
-
|
|
1213
|
+
query_stmt = session.query(TagRecordTable).filter(TagRecordTable.target_sqn == self.tag_target.sqn)
|
|
1163
1214
|
if begin_dt:
|
|
1164
|
-
|
|
1215
|
+
query_stmt = query_stmt.filter(TagRecordTable.end_dt >= begin_dt)
|
|
1165
1216
|
if end_dt:
|
|
1166
|
-
|
|
1217
|
+
query_stmt = query_stmt.filter(TagRecordTable.begin_dt <= end_dt)
|
|
1167
1218
|
if tagset_namespace:
|
|
1168
|
-
|
|
1219
|
+
query_stmt = query_stmt.filter(TagRecordTable.tagset_namespace == tagset_namespace)
|
|
1169
1220
|
if tagset_version:
|
|
1170
|
-
|
|
1221
|
+
query_stmt = query_stmt.filter(TagRecordTable.tagset_version == tagset_version)
|
|
1171
1222
|
if tag_prefix:
|
|
1172
|
-
|
|
1223
|
+
query_stmt = query_stmt.filter(TagRecordTable.tag.like(f"{escape_sql_like(tag_prefix)}%", escape="\\"))
|
|
1173
1224
|
if tagsets:
|
|
1174
1225
|
if tagset_inverted:
|
|
1175
|
-
|
|
1226
|
+
query_stmt = query_stmt.filter(
|
|
1176
1227
|
TagRecordTable.tag.notin_([tag_name for tagset in tagsets for tag_name in tagset.tag_names]))
|
|
1177
1228
|
else:
|
|
1178
|
-
|
|
1229
|
+
query_stmt = query_stmt.filter(
|
|
1179
1230
|
TagRecordTable.tag.in_([tag_name for tagset in tagsets for tag_name in tagset.tag_names]))
|
|
1180
1231
|
|
|
1181
|
-
|
|
1232
|
+
query_stmt.delete()
|
|
1182
1233
|
session.commit()
|
|
1183
1234
|
|
|
1184
1235
|
return self
|
|
1185
1236
|
|
|
1237
|
+
count_tags = count_records
|
|
1238
|
+
iter_tags = iter_records
|
|
1239
|
+
add_ranged_tag = add_ranged_record
|
|
1240
|
+
add_tag = add_record
|
|
1241
|
+
update_tag = update_record
|
|
1242
|
+
remove_tags = remove_records
|
|
1243
|
+
|
|
1186
1244
|
|
|
1187
1245
|
@memorized
|
|
1188
1246
|
def tag_cache(*, identifier: str | None = None, file_path: str | os.PathLike[str] | None = None) -> TagCache:
|
|
@@ -149,6 +149,7 @@ class TagUtilsTest(unittest.TestCase):
|
|
|
149
149
|
},
|
|
150
150
|
)
|
|
151
151
|
|
|
152
|
+
self.assertEqual(target_cache.count_tags(), tag_records_count)
|
|
152
153
|
self.assertEqual(len(list(target_cache.iter_tags())), tag_records_count)
|
|
153
154
|
self.assertEqual(len(list(target_cache.iter_tags(tagsets=[tagset]))),
|
|
154
155
|
tag_records_count * tagset_tags_count // tags_count)
|
|
@@ -204,15 +205,25 @@ class TagUtilsTest(unittest.TestCase):
|
|
|
204
205
|
|
|
205
206
|
target_cache.remove_tags(dt_parse_iso("2020-01-01T00:00:00+00:00"), dt_parse_iso("2020-01-01T00:01:00+00:00"))
|
|
206
207
|
|
|
208
|
+
self.assertEqual(target_cache.count_tags(), tag_records_count - (60 + 1))
|
|
207
209
|
self.assertEqual(len(list(target_cache.iter_tags())), tag_records_count - (60 + 1))
|
|
210
|
+
self.assertEqual(cache.count_tags(), tag_records_count - (60 + 1))
|
|
208
211
|
self.assertEqual(len(list(cache.iter_tags())), tag_records_count - (60 + 1))
|
|
209
212
|
|
|
210
213
|
target_cache.remove_tags(tagsets=[tagset], tagset_inverted=True)
|
|
211
214
|
|
|
215
|
+
self.assertEqual(
|
|
216
|
+
target_cache.count_tags(),
|
|
217
|
+
tag_records_count * tagset_tags_count // tags_count - (60 * tagset_tags_count // tags_count + 1),
|
|
218
|
+
)
|
|
212
219
|
self.assertEqual(
|
|
213
220
|
len(list(target_cache.iter_tags())),
|
|
214
221
|
tag_records_count * tagset_tags_count // tags_count - (60 * tagset_tags_count // tags_count + 1),
|
|
215
222
|
)
|
|
223
|
+
self.assertEqual(
|
|
224
|
+
cache.count_tags(),
|
|
225
|
+
tag_records_count * tagset_tags_count // tags_count - (60 * tagset_tags_count // tags_count + 1),
|
|
226
|
+
)
|
|
216
227
|
self.assertEqual(
|
|
217
228
|
len(list(cache.iter_tags())),
|
|
218
229
|
tag_records_count * tagset_tags_count // tags_count - (60 * tagset_tags_count // tags_count + 1),
|
|
@@ -220,7 +231,9 @@ class TagUtilsTest(unittest.TestCase):
|
|
|
220
231
|
|
|
221
232
|
target_cache.remove_tags()
|
|
222
233
|
|
|
234
|
+
self.assertEqual(target_cache.count_tags(), 0)
|
|
223
235
|
self.assertEqual(len(list(target_cache.iter_tags())), 0)
|
|
236
|
+
self.assertEqual(cache.count_tags(), 0)
|
|
224
237
|
self.assertEqual(len(list(cache.iter_tags())), 0)
|
|
225
238
|
|
|
226
239
|
def test_tag_cache__multithread(self):
|
|
@@ -307,6 +320,7 @@ class TagUtilsTest(unittest.TestCase):
|
|
|
307
320
|
thread.join()
|
|
308
321
|
|
|
309
322
|
for target_cache in target_caches:
|
|
323
|
+
self.assertEqual(target_cache.count_tags(), tasks_count_per_target_cache)
|
|
310
324
|
self.assertEqual(len(list(target_cache.iter_tags())), tasks_count_per_target_cache)
|
|
311
325
|
self.assertEqual(len(list(target_cache.iter_tags(tag_prefix="dummy:bar"))),
|
|
312
326
|
tasks_count_per_target_cache // tags_count)
|
|
@@ -315,6 +329,7 @@ class TagUtilsTest(unittest.TestCase):
|
|
|
315
329
|
self.assertEqual(len(list(target_cache.iter_tags(tagset_namespace="tagset", tagset_version="1.0.0"))),
|
|
316
330
|
tasks_count_per_target_cache * old_tagset_tags_count // tags_count)
|
|
317
331
|
|
|
332
|
+
self.assertEqual(cache.count_tags(), total_tasks_count)
|
|
318
333
|
self.assertEqual(len(list(cache.iter_tag_and_targets())), total_tasks_count)
|
|
319
334
|
self.assertEqual(len(list(cache.iter_tag_and_targets(tag_prefix="dummy:bar"))),
|
|
320
335
|
total_tasks_count // tags_count)
|
|
@@ -357,7 +372,7 @@ class TagUtilsTest(unittest.TestCase):
|
|
|
357
372
|
for i in range(tag_records_count):
|
|
358
373
|
tag_name = tag_names[i % len(tag_names)]
|
|
359
374
|
tag = tagset.get_bound(tag_name) or tag_name
|
|
360
|
-
src_target_cache.
|
|
375
|
+
src_target_cache.add_record(tag)
|
|
361
376
|
|
|
362
377
|
dst_cache = TagCache(file_path=temp_directory / "dst_tag_cache.db")
|
|
363
378
|
|
|
@@ -366,24 +381,26 @@ class TagUtilsTest(unittest.TestCase):
|
|
|
366
381
|
for i in range(tag_records_count):
|
|
367
382
|
tag_name = tag_names[i % len(tag_names)]
|
|
368
383
|
tag = tagset.get_bound(tag_name) or tag_name
|
|
369
|
-
src_target_cache.
|
|
384
|
+
src_target_cache.add_record(tag)
|
|
370
385
|
|
|
371
386
|
dst_target_cache = dst_cache.with_target("awesome_tagger/20200101_000000/dummy_vehicle/0")
|
|
372
387
|
|
|
373
|
-
self.assertEqual(
|
|
374
|
-
self.assertEqual(len(list(src_target_cache.
|
|
388
|
+
self.assertEqual(src_target_cache.count_records(), tag_records_count * 2)
|
|
389
|
+
self.assertEqual(len(list(src_target_cache.iter_records())), tag_records_count * 2)
|
|
390
|
+
self.assertEqual(len(list(src_target_cache.iter_records(tagsets=[tagset]))),
|
|
375
391
|
tag_records_count * 2 * tagset_tags_count // tags_count)
|
|
376
|
-
self.assertEqual(len(list(src_target_cache.
|
|
392
|
+
self.assertEqual(len(list(src_target_cache.iter_records(tagsets=[tagset], tagset_inverted=True))),
|
|
377
393
|
tag_records_count * 2 * (tags_count - tagset_tags_count) // tags_count)
|
|
378
|
-
self.assertEqual(len(list(src_target_cache.
|
|
394
|
+
self.assertEqual(len(list(src_target_cache.iter_records(tagsets=[tagset], tagset_inverted=False))),
|
|
379
395
|
tag_records_count * 2 * tagset_tags_count // tags_count)
|
|
380
396
|
|
|
381
|
-
self.assertEqual(
|
|
382
|
-
self.assertEqual(len(list(dst_target_cache.
|
|
397
|
+
self.assertEqual(dst_target_cache.count_records(), tag_records_count)
|
|
398
|
+
self.assertEqual(len(list(dst_target_cache.iter_records())), tag_records_count)
|
|
399
|
+
self.assertEqual(len(list(dst_target_cache.iter_records(tagsets=[tagset]))),
|
|
383
400
|
tag_records_count * tagset_tags_count // tags_count)
|
|
384
|
-
self.assertEqual(len(list(dst_target_cache.
|
|
401
|
+
self.assertEqual(len(list(dst_target_cache.iter_records(tagsets=[tagset], tagset_inverted=True))),
|
|
385
402
|
tag_records_count * (tags_count - tagset_tags_count) // tags_count)
|
|
386
|
-
self.assertEqual(len(list(dst_target_cache.
|
|
403
|
+
self.assertEqual(len(list(dst_target_cache.iter_records(tagsets=[tagset], tagset_inverted=False))),
|
|
387
404
|
tag_records_count * tagset_tags_count // tags_count)
|
|
388
405
|
|
|
389
406
|
def test_tag_cache__clone_same_file(self):
|
|
@@ -422,7 +439,7 @@ class TagUtilsTest(unittest.TestCase):
|
|
|
422
439
|
for i in range(tag_records_count):
|
|
423
440
|
tag_name = tag_names[i % len(tag_names)]
|
|
424
441
|
tag = tagset.get_bound(tag_name) or tag_name
|
|
425
|
-
src_target_cache.
|
|
442
|
+
src_target_cache.add_record(tag)
|
|
426
443
|
|
|
427
444
|
dst_cache = TagCache(file_path=temp_directory / "tag_cache.db")
|
|
428
445
|
|
|
@@ -431,24 +448,26 @@ class TagUtilsTest(unittest.TestCase):
|
|
|
431
448
|
for i in range(tag_records_count):
|
|
432
449
|
tag_name = tag_names[i % len(tag_names)]
|
|
433
450
|
tag = tagset.get_bound(tag_name) or tag_name
|
|
434
|
-
src_target_cache.
|
|
451
|
+
src_target_cache.add_record(tag)
|
|
435
452
|
|
|
436
453
|
dst_target_cache = dst_cache.with_target("awesome_tagger/20200101_000000/dummy_vehicle/0")
|
|
437
454
|
|
|
438
|
-
self.assertEqual(
|
|
439
|
-
self.assertEqual(len(list(src_target_cache.
|
|
455
|
+
self.assertEqual(src_target_cache.count_records(), tag_records_count * 2)
|
|
456
|
+
self.assertEqual(len(list(src_target_cache.iter_records())), tag_records_count * 2)
|
|
457
|
+
self.assertEqual(len(list(src_target_cache.iter_records(tagsets=[tagset]))),
|
|
440
458
|
tag_records_count * 2 * tagset_tags_count // tags_count)
|
|
441
|
-
self.assertEqual(len(list(src_target_cache.
|
|
459
|
+
self.assertEqual(len(list(src_target_cache.iter_records(tagsets=[tagset], tagset_inverted=True))),
|
|
442
460
|
tag_records_count * 2 * (tags_count - tagset_tags_count) // tags_count)
|
|
443
|
-
self.assertEqual(len(list(src_target_cache.
|
|
461
|
+
self.assertEqual(len(list(src_target_cache.iter_records(tagsets=[tagset], tagset_inverted=False))),
|
|
444
462
|
tag_records_count * 2 * tagset_tags_count // tags_count)
|
|
445
463
|
|
|
446
|
-
self.assertEqual(
|
|
447
|
-
self.assertEqual(len(list(dst_target_cache.
|
|
464
|
+
self.assertEqual(dst_target_cache.count_records(), tag_records_count * 2)
|
|
465
|
+
self.assertEqual(len(list(dst_target_cache.iter_records())), tag_records_count * 2)
|
|
466
|
+
self.assertEqual(len(list(dst_target_cache.iter_records(tagsets=[tagset]))),
|
|
448
467
|
tag_records_count * 2 * tagset_tags_count // tags_count)
|
|
449
|
-
self.assertEqual(len(list(dst_target_cache.
|
|
468
|
+
self.assertEqual(len(list(dst_target_cache.iter_records(tagsets=[tagset], tagset_inverted=True))),
|
|
450
469
|
tag_records_count * 2 * (tags_count - tagset_tags_count) // tags_count)
|
|
451
|
-
self.assertEqual(len(list(dst_target_cache.
|
|
470
|
+
self.assertEqual(len(list(dst_target_cache.iter_records(tagsets=[tagset], tagset_inverted=False))),
|
|
452
471
|
tag_records_count * 2 * tagset_tags_count // tags_count)
|
|
453
472
|
|
|
454
473
|
with tempfile.TemporaryDirectory() as temp_directory:
|
|
@@ -470,7 +489,7 @@ class TagUtilsTest(unittest.TestCase):
|
|
|
470
489
|
for i in range(tag_records_count):
|
|
471
490
|
tag_name = tag_names[i % len(tag_names)]
|
|
472
491
|
tag = tagset.get_bound(tag_name) or tag_name
|
|
473
|
-
src_target_cache.
|
|
492
|
+
src_target_cache.add_record(tag)
|
|
474
493
|
|
|
475
494
|
dst_cache = src_cache
|
|
476
495
|
|
|
@@ -479,24 +498,26 @@ class TagUtilsTest(unittest.TestCase):
|
|
|
479
498
|
for i in range(tag_records_count):
|
|
480
499
|
tag_name = tag_names[i % len(tag_names)]
|
|
481
500
|
tag = tagset.get_bound(tag_name) or tag_name
|
|
482
|
-
src_target_cache.
|
|
501
|
+
src_target_cache.add_record(tag)
|
|
483
502
|
|
|
484
503
|
dst_target_cache = dst_cache.with_target("awesome_tagger/20200101_000000/dummy_vehicle/0")
|
|
485
504
|
|
|
486
|
-
self.assertEqual(
|
|
487
|
-
self.assertEqual(len(list(src_target_cache.
|
|
505
|
+
self.assertEqual(src_target_cache.count_records(), tag_records_count * 2)
|
|
506
|
+
self.assertEqual(len(list(src_target_cache.iter_records())), tag_records_count * 2)
|
|
507
|
+
self.assertEqual(len(list(src_target_cache.iter_records(tagsets=[tagset]))),
|
|
488
508
|
tag_records_count * 2 * tagset_tags_count // tags_count)
|
|
489
|
-
self.assertEqual(len(list(src_target_cache.
|
|
509
|
+
self.assertEqual(len(list(src_target_cache.iter_records(tagsets=[tagset], tagset_inverted=True))),
|
|
490
510
|
tag_records_count * 2 * (tags_count - tagset_tags_count) // tags_count)
|
|
491
|
-
self.assertEqual(len(list(src_target_cache.
|
|
511
|
+
self.assertEqual(len(list(src_target_cache.iter_records(tagsets=[tagset], tagset_inverted=False))),
|
|
492
512
|
tag_records_count * 2 * tagset_tags_count // tags_count)
|
|
493
513
|
|
|
494
|
-
self.assertEqual(
|
|
495
|
-
self.assertEqual(len(list(dst_target_cache.
|
|
514
|
+
self.assertEqual(dst_target_cache.count_records(), tag_records_count * 2)
|
|
515
|
+
self.assertEqual(len(list(dst_target_cache.iter_records())), tag_records_count * 2)
|
|
516
|
+
self.assertEqual(len(list(dst_target_cache.iter_records(tagsets=[tagset]))),
|
|
496
517
|
tag_records_count * 2 * tagset_tags_count // tags_count)
|
|
497
|
-
self.assertEqual(len(list(dst_target_cache.
|
|
518
|
+
self.assertEqual(len(list(dst_target_cache.iter_records(tagsets=[tagset], tagset_inverted=True))),
|
|
498
519
|
tag_records_count * 2 * (tags_count - tagset_tags_count) // tags_count)
|
|
499
|
-
self.assertEqual(len(list(dst_target_cache.
|
|
520
|
+
self.assertEqual(len(list(dst_target_cache.iter_records(tagsets=[tagset], tagset_inverted=False))),
|
|
500
521
|
tag_records_count * 2 * tagset_tags_count // tags_count)
|
|
501
522
|
|
|
502
523
|
data_populate_clip_ranges = [
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/0-dummy
RENAMED
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/1-dummy
RENAMED
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/2-dummy
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/resources/unittest/pathutils/dummy.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/carto/OSMFile.py
RENAMED
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/carto/OSMNode.py
RENAMED
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/carto/OSMTags.py
RENAMED
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/carto/OSMWay.py
RENAMED
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/carto/__init__.py
RENAMED
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/resources/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/__init__.py
RENAMED
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/apiutils.py
RENAMED
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/bagutils.py
RENAMED
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/config.py
RENAMED
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/datautils.py
RENAMED
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/dockerutils.py
RENAMED
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/gisutils.py
RENAMED
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/jsonutils.py
RENAMED
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/pathutils.py
RENAMED
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/s3utils.py
RENAMED
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/sqlutils.py
RENAMED
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/strutils.py
RENAMED
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/src/plexus/common/utils/testutils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{plexus_python_common-1.0.67 → plexus_python_common-1.0.69}/test/plexus_tests/common/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|