plexus-python-common 1.0.68__py3-none-any.whl → 1.0.69__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.
@@ -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
- query = db.query(model).order_by(*db_make_order_by_clause(model, order_by))
1095
+ query_stmt = db.query(model).order_by(*db_make_order_by_clause(model, order_by))
1096
1096
  if skip is not None:
1097
- query = query.offset(skip)
1097
+ query_stmt = query_stmt.offset(skip)
1098
1098
  if limit is not None:
1099
- query = query.limit(limit)
1100
- return query.all()
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
- subquery = (
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
- query = (
1296
+ query_stmt = (
1297
1297
  db
1298
1298
  .query(model)
1299
- .join(subquery,
1300
- sa.and_(model.record_sqn == subquery.c.record_sqn, model.created_at == subquery.c.max_created_at))
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
- query = query.offset(skip)
1305
+ query_stmt = query_stmt.offset(skip)
1305
1306
  if limit is not None:
1306
- query = query.limit(limit)
1307
- return query.all()
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
- query = db.query(model).where(model.expired_at.is_(None)).order_by(*db_make_order_by_clause(model, order_by))
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
- query = query.offset(skip)
1320
+ query_stmt = query_stmt.offset(skip)
1320
1321
  if limit is not None:
1321
- query = query.limit(limit)
1322
- return query.all()
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
- subquery = (
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
- query = (
1524
+ query_stmt = (
1524
1525
  db
1525
1526
  .query(model)
1526
- .join(subquery,
1527
- sa.and_(model.record_sqn == subquery.c.record_sqn, model.revision == subquery.c.max_revision))
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
- query = query.offset(skip)
1533
+ query_stmt = query_stmt.offset(skip)
1532
1534
  if limit is not None:
1533
- query = query.limit(limit)
1534
- return query.all()
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
- query = db.query(model).where(model.expired_at.is_(None)).order_by(*db_make_order_by_clause(model, order_by))
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
- query = query.offset(skip)
1548
+ query_stmt = query_stmt.offset(skip)
1547
1549
  if limit is not None:
1548
- query = query.limit(limit)
1549
- return query.all()
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](
@@ -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
- query = session.query(TagTargetTable)
648
+ query_stmt = session.query(TagTargetTable)
649
649
  if identifier:
650
- query = query.filter(TagTargetTable.identifier == identifier)
650
+ query_stmt = query_stmt.filter(TagTargetTable.identifier == identifier)
651
651
  if tagger_name:
652
- query = query.filter(TagTargetTable.tagger_name == tagger_name)
652
+ query_stmt = query_stmt.filter(TagTargetTable.tagger_name == tagger_name)
653
653
  if tagger_version:
654
- query = query.filter(TagTargetTable.tagger_version == tagger_version)
654
+ query_stmt = query_stmt.filter(TagTargetTable.tagger_version == tagger_version)
655
655
  if vehicle_name:
656
- query = query.filter(TagTargetTable.vehicle_name == vehicle_name)
656
+ query_stmt = query_stmt.filter(TagTargetTable.vehicle_name == vehicle_name)
657
657
  if begin_dt:
658
- query = query.filter(TagTargetTable.end_dt >= begin_dt)
658
+ query_stmt = query_stmt.filter(TagTargetTable.end_dt >= begin_dt)
659
659
  if end_dt:
660
- query = query.filter(TagTargetTable.begin_dt <= end_dt)
660
+ query_stmt = query_stmt.filter(TagTargetTable.begin_dt <= end_dt)
661
661
 
662
- return query.all()
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
- target_info = TagTarget(
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
- db_target_info = clone_sequence_model_instance(TagTargetTable, target_info)
683
- session.add(db_target_info)
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
- query = session.query(TagTargetTable)
698
+ query_stmt = session.query(TagTargetTable)
699
699
  if identifier:
700
- query = query.filter(TagTargetTable.identifier == identifier)
700
+ query_stmt = query_stmt.filter(TagTargetTable.identifier == identifier)
701
701
  if tagger_name:
702
- query = query.filter(TagTargetTable.tagger_name == tagger_name)
702
+ query_stmt = query_stmt.filter(TagTargetTable.tagger_name == tagger_name)
703
703
  if tagger_version:
704
- query = query.filter(TagTargetTable.tagger_version == tagger_version)
704
+ query_stmt = query_stmt.filter(TagTargetTable.tagger_version == tagger_version)
705
705
  if vehicle_name:
706
- query = query.filter(TagTargetTable.vehicle_name == vehicle_name)
706
+ query_stmt = query_stmt.filter(TagTargetTable.vehicle_name == vehicle_name)
707
707
  if begin_dt:
708
- query = query.filter(TagTargetTable.end_dt >= begin_dt)
708
+ query_stmt = query_stmt.filter(TagTargetTable.end_dt >= begin_dt)
709
709
  if end_dt:
710
- query = query.filter(TagTargetTable.begin_dt <= end_dt)
710
+ query_stmt = query_stmt.filter(TagTargetTable.begin_dt <= end_dt)
711
711
 
712
- query.delete()
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
- target_info = self.get_target(target)
725
- if target_info is None:
726
- raise ValueError(f"target '{target}' not found in cache")
727
- return TargetedTagCache(cache=self, target_info=target_info)
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 iter_tags(
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
- query = session.query(TagRecordTable)
764
+ query_stmt = session.query(TagRecordTable)
757
765
  if begin_dt:
758
- query = query.filter(TagRecordTable.end_dt >= begin_dt)
766
+ query_stmt = query_stmt.filter(TagRecordTable.end_dt >= begin_dt)
759
767
  if end_dt:
760
- query = query.filter(TagRecordTable.begin_dt <= end_dt)
768
+ query_stmt = query_stmt.filter(TagRecordTable.begin_dt <= end_dt)
761
769
  if tagset_namespace:
762
- query = query.filter(TagRecordTable.tagset_namespace == tagset_namespace)
770
+ query_stmt = query_stmt.filter(TagRecordTable.tagset_namespace == tagset_namespace)
763
771
  if tagset_version:
764
- query = query.filter(TagRecordTable.tagset_version == tagset_version)
772
+ query_stmt = query_stmt.filter(TagRecordTable.tagset_version == tagset_version)
765
773
  if tag_prefix:
766
- query = query.filter(TagRecordTable.tag.like(f"{escape_sql_like(tag_prefix)}%", escape="\\"))
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
- query = query.filter(
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
- query = query.filter(
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
- for result in query.yield_per(batch_size):
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 iter_tag_and_targets(
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 info in the cache with optional filters.
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
- query = (
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
- query = query.filter(TagRecordTable.end_dt >= begin_dt)
841
+ query_stmt = query_stmt.filter(TagRecordTable.end_dt >= begin_dt)
824
842
  if end_dt:
825
- query = query.filter(TagRecordTable.begin_dt <= end_dt)
843
+ query_stmt = query_stmt.filter(TagRecordTable.begin_dt <= end_dt)
826
844
  if tagset_namespace:
827
- query = query.filter(TagRecordTable.tagset_namespace == tagset_namespace)
845
+ query_stmt = query_stmt.filter(TagRecordTable.tagset_namespace == tagset_namespace)
828
846
  if tagset_version:
829
- query = query.filter(TagRecordTable.tagset_version == tagset_version)
847
+ query_stmt = query_stmt.filter(TagRecordTable.tagset_version == tagset_version)
830
848
  if tag_prefix:
831
- query = query.filter(TagRecordTable.tag.like(f"{escape_sql_like(tag_prefix)}%", escape="\\"))
849
+ query_stmt = query_stmt.filter(TagRecordTable.tag.like(f"{escape_sql_like(tag_prefix)}%", escape="\\"))
832
850
  if target_identifier:
833
- query = query.filter(TagTargetTable.identifier == target_identifier)
851
+ query_stmt = query_stmt.filter(TagTargetTable.identifier == target_identifier)
834
852
  if target_tagger_name:
835
- query = query.filter(TagTargetTable.tagger_name == target_tagger_name)
853
+ query_stmt = query_stmt.filter(TagTargetTable.tagger_name == target_tagger_name)
836
854
  if target_tagger_version:
837
- query = query.filter(TagTargetTable.tagger_version == target_tagger_version)
855
+ query_stmt = query_stmt.filter(TagTargetTable.tagger_version == target_tagger_version)
838
856
  if target_vehicle_name:
839
- query = query.filter(TagTargetTable.vehicle_name == target_vehicle_name)
857
+ query_stmt = query_stmt.filter(TagTargetTable.vehicle_name == target_vehicle_name)
840
858
  if target_begin_dt:
841
- query = query.filter(TagTargetTable.end_dt >= target_begin_dt)
859
+ query_stmt = query_stmt.filter(TagTargetTable.end_dt >= target_begin_dt)
842
860
  if target_end_dt:
843
- query = query.filter(TagTargetTable.begin_dt <= target_end_dt)
861
+ query_stmt = query_stmt.filter(TagTargetTable.begin_dt <= target_end_dt)
844
862
  if tagsets:
845
863
  if tagset_inverted:
846
- query = query.filter(
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
- query = query.filter(
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
- for result in query.yield_per(batch_size):
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 remove_tags(
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
- query = session.query(TagRecordTable)
903
+ query_stmt = session.query(TagRecordTable)
880
904
  if begin_dt:
881
- query = query.filter(TagRecordTable.end_dt >= begin_dt)
905
+ query_stmt = query_stmt.filter(TagRecordTable.end_dt >= begin_dt)
882
906
  if end_dt:
883
- query = query.filter(TagRecordTable.begin_dt <= end_dt)
907
+ query_stmt = query_stmt.filter(TagRecordTable.begin_dt <= end_dt)
884
908
  if tagset_namespace:
885
- query = query.filter(TagRecordTable.tagset_namespace == tagset_namespace)
909
+ query_stmt = query_stmt.filter(TagRecordTable.tagset_namespace == tagset_namespace)
886
910
  if tagset_version:
887
- query = query.filter(TagRecordTable.tagset_version == tagset_version)
911
+ query_stmt = query_stmt.filter(TagRecordTable.tagset_version == tagset_version)
888
912
  if tag_prefix:
889
- query = query.filter(TagRecordTable.tag.like(f"{escape_sql_like(tag_prefix)}%", escape="\\"))
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
- query = query.filter(
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
- query = query.filter(
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
- query.delete()
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
- src_targets = src_session.query(TagTargetTable).all()
928
- dst_targets = [
929
- clone_sequence_model_instance(TagTargetTable, db_tag_target_info, clear_meta_fields=True)
930
- for db_tag_target_info in src_targets
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(dst_targets)
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 = {src_target.sqn: dst_target.sqn for src_target, dst_target in zip(src_targets, dst_targets)}
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 results in batched(src_session.query(TagRecordTable).yield_per(1000), 1000):
938
- clones = []
939
- for db_tag_record in results:
940
- cloned = clone_sequence_model_instance(TagRecordTable, db_tag_record, clear_meta_fields=True)
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
- cloned.target_sqn = sqn_map[db_tag_record.target_sqn]
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
- clones.append(cloned)
946
- dst_session.add_all(clones)
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, target_info: TagTargetTable):
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.target_info.sqn).first():
959
- raise ValueError(f"target info with sqn '{self.target_info.sqn}' is no longer present in cache")
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 iter_tags(
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
- query = session.query(TagRecordTable).filter(TagRecordTable.target_sqn == self.target_info.sqn)
1035
+ query_stmt = session.query(TagRecordTable).filter(TagRecordTable.target_sqn == self.tag_target.sqn)
991
1036
  if begin_dt:
992
- query = query.filter(TagRecordTable.end_dt >= begin_dt)
1037
+ query_stmt = query_stmt.filter(TagRecordTable.end_dt >= begin_dt)
993
1038
  if end_dt:
994
- query = query.filter(TagRecordTable.begin_dt <= end_dt)
1039
+ query_stmt = query_stmt.filter(TagRecordTable.begin_dt <= end_dt)
995
1040
  if tagset_namespace:
996
- query = query.filter(TagRecordTable.tagset_namespace == tagset_namespace)
1041
+ query_stmt = query_stmt.filter(TagRecordTable.tagset_namespace == tagset_namespace)
997
1042
  if tagset_version:
998
- query = query.filter(TagRecordTable.tagset_version == tagset_version)
1043
+ query_stmt = query_stmt.filter(TagRecordTable.tagset_version == tagset_version)
999
1044
  if tag_prefix:
1000
- query = query.filter(TagRecordTable.tag.like(f"{escape_sql_like(tag_prefix)}%", escape="\\"))
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
- query = query.filter(
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
- query = query.filter(
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
- for result in query.yield_per(batch_size):
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 add_ranged_tag(
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.target_info.sqn,
1040
- begin_dt=begin_dt or self.target_info.begin_dt,
1041
- end_dt=end_dt or self.target_info.end_dt,
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 add_tag(
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.add_ranged_tag(
1075
- begin_dt=self.target_info.begin_dt,
1076
- end_dt=self.target_info.end_dt,
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 update_tag(
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 remove_tags(
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
- query = session.query(TagRecordTable).filter(TagRecordTable.target_sqn == self.target_info.sqn)
1213
+ query_stmt = session.query(TagRecordTable).filter(TagRecordTable.target_sqn == self.tag_target.sqn)
1163
1214
  if begin_dt:
1164
- query = query.filter(TagRecordTable.end_dt >= begin_dt)
1215
+ query_stmt = query_stmt.filter(TagRecordTable.end_dt >= begin_dt)
1165
1216
  if end_dt:
1166
- query = query.filter(TagRecordTable.begin_dt <= end_dt)
1217
+ query_stmt = query_stmt.filter(TagRecordTable.begin_dt <= end_dt)
1167
1218
  if tagset_namespace:
1168
- query = query.filter(TagRecordTable.tagset_namespace == tagset_namespace)
1219
+ query_stmt = query_stmt.filter(TagRecordTable.tagset_namespace == tagset_namespace)
1169
1220
  if tagset_version:
1170
- query = query.filter(TagRecordTable.tagset_version == tagset_version)
1221
+ query_stmt = query_stmt.filter(TagRecordTable.tagset_version == tagset_version)
1171
1222
  if tag_prefix:
1172
- query = query.filter(TagRecordTable.tag.like(f"{escape_sql_like(tag_prefix)}%", escape="\\"))
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
- query = query.filter(
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
- query = query.filter(
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
- query.delete()
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:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plexus-python-common
3
- Version: 1.0.68
3
+ Version: 1.0.69
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3.12
6
6
  Classifier: Programming Language :: Python :: 3.13
@@ -16,14 +16,14 @@ plexus/common/utils/datautils.py,sha256=mgnr-dcHpw-Pk3qBud0lC3JX_pv-iKzI8llsPW9Q
16
16
  plexus/common/utils/dockerutils.py,sha256=WPxQuabRWyyM8wpSSYhb_HZaOw5yZ2TbU2dEQ2xRIlQ,5787
17
17
  plexus/common/utils/gisutils.py,sha256=UR3uVoD1nAy0SWJ1AYWCUy94Lo8zNb4nv_JdpcANBDE,11462
18
18
  plexus/common/utils/jsonutils.py,sha256=-_uKlQMLMgmVO9pB99S45Y_Vufx5dFSq43DIwGz1a54,3328
19
- plexus/common/utils/ormutils.py,sha256=CHrp6l5shRL2qa8GzRLqeVbtC-eZZkfWCOpBy32JDok,60433
19
+ plexus/common/utils/ormutils.py,sha256=bAJDSp-53406E5iySueh09yQUs0OuCshygRSzU9aaW0,60667
20
20
  plexus/common/utils/pathutils.py,sha256=hGJqSLj08tuOeZ7WeC5d4BtjnPI732BuntVQBQsqOaI,9581
21
21
  plexus/common/utils/s3utils.py,sha256=zlO4kGs-c2gUeOfPfiKIE5liQZsbYxqAZYCwA8kL0Lo,36017
22
22
  plexus/common/utils/sqlutils.py,sha256=D6kTBjhO5YlNRt3uFlPt6z3uH61m9ajEzPYmsI6NoFc,231
23
23
  plexus/common/utils/strutils.py,sha256=O9Inv4ffUTf6Xjc5ftoZwbIua1NeG7itCT9S3zjZxBc,16436
24
- plexus/common/utils/tagutils.py,sha256=n4yd4KIq8Ub4sGN8wYFom1Ea4IJ19s9UEW-rTl30NDs,52104
24
+ plexus/common/utils/tagutils.py,sha256=OaJ_iXbYPRRqq1-GwkqnZ-6UUj4jhhd8Myfu92VKg8Y,55419
25
25
  plexus/common/utils/testutils.py,sha256=N8ijLu7X-hlQlHzvv0TtSsQpIF4T1hbr-AjkILoV2Ac,6152
26
- plexus_python_common-1.0.68.dist-info/METADATA,sha256=qUVFVvm5czJv0ATp6QvMPfAjPfoJGn0CCcD_ckNNfVA,1481
27
- plexus_python_common-1.0.68.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
28
- plexus_python_common-1.0.68.dist-info/top_level.txt,sha256=ug_g7CVwaMQuas5UzAXbHUrQvKGCn8ezc6ZNvvRlJOE,7
29
- plexus_python_common-1.0.68.dist-info/RECORD,,
26
+ plexus_python_common-1.0.69.dist-info/METADATA,sha256=kiAxXNij0yyE_PgMAVoCDuXjD_FPGgxA1abUHMLaB44,1481
27
+ plexus_python_common-1.0.69.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
28
+ plexus_python_common-1.0.69.dist-info/top_level.txt,sha256=ug_g7CVwaMQuas5UzAXbHUrQvKGCn8ezc6ZNvvRlJOE,7
29
+ plexus_python_common-1.0.69.dist-info/RECORD,,