Conversation
Components, supplemental attributes, and time series metadata now use monotonically-increasing integer IDs as their primary identifier. Legacy UUIDs are preserved as `legacy_uuid` for backward compatibility. Key changes: - InfraSysBaseModelWithIdentifiers: new id field (int), legacy_uuid for BC - IDManager: tracks next available ID, supports advance_past() for serialized data with pre-assigned IDs - SQLite tables use INTEGER foreign keys with referential integrity - ComponentAssociations, SupplementalAttributeAssociations, and TimeSeriesMetadataStore all migrated to integer ID columns - Migration logic for legacy serialized data and existing SQLite schemas - New get_by_id() methods on ComponentManager, SupplementalAttributeManager - SerializedComponentReference uses integer id instead of UUID - Fixed double-negative bug in metadata_store_needs_migration - copy.deepcopy replaces manual model_dump() reconstruction - Backward-compat alias InfraSysBaseModelWithIdentifers preserved
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #156 +/- ##
==========================================
- Coverage 94.82% 94.78% -0.05%
==========================================
Files 61 62 +1
Lines 6072 6802 +730
==========================================
+ Hits 5758 6447 +689
- Misses 314 355 +41 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR migrates InfraSys object identifiers from UUIDs to stable, monotonically-increasing integer IDs across components, supplemental attributes, and time series metadata while retaining legacy UUIDs for backward compatibility.
Changes:
- Introduces integer
idfields (withlegacy_uuidretained for BC) and updates serialization/deserialization to use integer IDs for references. - Migrates SQLite schemas and association tables (components, supplemental attributes, time series metadata) to integer foreign keys and adds migration helpers for legacy UUID-based data.
- Updates public accessors/managers and test suite expectations to use
get_by_id()/owner_id/time_series_idpaths.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_system.py | Updates record and SQL assertions to validate integer IDs and storage-key UUIDs. |
| tests/test_supplemental_attributes.py | Makes assertions resilient to ordering by comparing coordinate sets. |
| tests/test_serialization.py | Switches component lookups to get_component_by_id() and adds explicit ID-serialization coverage. |
| src/infrasys/utils/metadata_utils.py | Updates SQLite table schemas/indexes to integer FK columns and enables foreign keys. |
| src/infrasys/time_series_models.py | Adds time_series_id into metadata models and sets it during from_data(). |
| src/infrasys/time_series_metadata_store.py | Migrates association columns to integer IDs + storage keys and adds legacy table migration/remapping logic. |
| src/infrasys/time_series_manager.py | Assigns integer IDs to time series and exposes metadata schema migration hook. |
| src/infrasys/system.py | Adds legacy upgrade path for serialized references, new get_*_by_id() APIs, and triggers metadata/schema migrations on load. |
| src/infrasys/supplemental_attribute_manager.py | Adds ID-based attribute indexing/lookup and association schema migration call. |
| src/infrasys/supplemental_attribute_associations.py | Converts association storage and queries from UUID columns to integer ID columns. |
| src/infrasys/serialization.py | Updates SerializedComponentReference to store integer IDs with legacy UUID as excluded BC field. |
| src/infrasys/models.py | Replaces UUID base identifier with integer id + legacy_uuid, and extends label parsing to handle ints. |
| src/infrasys/migrations/db_migrations.py | Fixes migration predicate and routes legacy inserts through the updated metadata store insert path. |
| src/infrasys/id_manager.py | Adds advance_past() to support externally-supplied IDs during deserialization/migration. |
| src/infrasys/component.py | Serializes composed component references using integer IDs and errors if ID is missing. |
| src/infrasys/component_manager.py | Adds ID indexing/lookup, updates composed-component association logic to use IDs, and switches deepcopy to copy.deepcopy. |
| src/infrasys/component_associations.py | Converts component association storage/querying from UUIDs to integer IDs with parent-ID insertion. |
| src/infrasys/init.py | Removes duplicate constant definition. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Fix ComponentManager.remove() index cleanup only triggering on empty container (P1 bug) - Fix get_by_label() to try name-based lookup before ID for numeric labels (P1 ambiguity) - Add owner_category to time series unique index to prevent false collisions across owner types - Extract migration functions to src/infrasys/utils/migrations.py - Raise NotImplementedError for deprecated get_component_uuids_with_attribute - Merge duplicate query strings in supplemental attribute associations - Add Field descriptions to SerializedComponentReference - Add cascade warning when removing components with time series - Add migration path tests and remove-index cleanup test
…nent associations Covers: - SerializedComponentReference.uuid property (success + error) - get_class_and_name_from_label with UUID and unknown string labels - ComponentAssociations.clear operation - list_child_components/list_parent_components with type filter - get_by_label with UUID-based labels
|
@daniel-thom, is this what you had in mind? |
- fix duplicate list_time_series_metadata call in remove_component - widen sql() params type from Sequence[str] to Sequence[Any] - guard MAX(*_id) queries with column existence checks for legacy DBs - add 17 tests covering component associations, ID management, migrations, supplemental attribute queries, and time series metadata normalization
| class_name, name = label.split(".", maxsplit=1) | ||
| name_or_uuid: str | UUID = name | ||
| name_or_uuid: str | int | UUID = name | ||
| try: | ||
| name_or_uuid = int(name) | ||
| return class_name, name_or_uuid | ||
| except ValueError: |
| query = f"SELECT 1 FROM {TIME_SERIES_ASSOCIATIONS_TABLE} WHERE time_series_uuid = ?" | ||
| query = f"SELECT 1 FROM {TIME_SERIES_ASSOCIATIONS_TABLE} WHERE time_series_storage_key = ?" | ||
| row = execute(cur, query, params=(str(time_series_uuid),)).fetchone() | ||
| return row |
… type, replace asserts with domain exceptions Agent-Logs-Url: https://github.com/NatLabRockies/infrasys/sessions/070e4fb1-22bd-4d30-8a82-321e1f62f210 Co-authored-by: pesap <2238996+pesap@users.noreply.github.com>
| def raise_if_attached(self, component: Component): | ||
| """Raise an exception if this component is attached to a system.""" | ||
| if component.uuid in self._components_by_uuid: | ||
| if component.id is not None and component.id in self._components_by_id: | ||
| msg = f"{component.label} is already attached to the system" | ||
| raise ISAlreadyAttached(msg) |
| if component.id is None: | ||
| component.id = self._id_manager.get_next_id() | ||
| elif component.id in self._components_by_id: | ||
| msg = f"{component.label} with id={component.id} is already stored" | ||
| raise ISAlreadyAttached(msg) | ||
| else: | ||
| self._id_manager.advance_past(component.id) |
| if not owners: | ||
| msg = "At least one component must be passed." | ||
| raise ISOperationNotAllowed(msg) |
Components, supplemental attributes, and time series metadata now use monotonically-increasing integer IDs as their primary identifier. Legacy UUIDs are preserved as
legacy_uuidfor backward compatibility.Key changes: