ic-python-db 0.7.5__tar.gz → 0.7.6__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.
- {ic_python_db-0.7.5/ic_python_db.egg-info → ic_python_db-0.7.6}/PKG-INFO +1 -1
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/ic_python_db/__init__.py +1 -1
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/ic_python_db/entity.py +72 -27
- {ic_python_db-0.7.5 → ic_python_db-0.7.6/ic_python_db.egg-info}/PKG-INFO +1 -1
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/pyproject.toml +1 -1
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/setup.py +1 -1
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/LICENSE +0 -0
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/MANIFEST.in +0 -0
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/README.md +0 -0
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/ic_python_db/_cdk.py +0 -0
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/ic_python_db/constants.py +0 -0
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/ic_python_db/context.py +0 -0
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/ic_python_db/db_engine.py +0 -0
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/ic_python_db/hooks.py +0 -0
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/ic_python_db/mixins.py +0 -0
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/ic_python_db/properties.py +0 -0
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/ic_python_db/py.typed +0 -0
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/ic_python_db/storage.py +0 -0
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/ic_python_db/system_time.py +0 -0
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/ic_python_db.egg-info/SOURCES.txt +0 -0
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/ic_python_db.egg-info/dependency_links.txt +0 -0
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/ic_python_db.egg-info/top_level.txt +0 -0
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/requirements-dev.txt +0 -0
- {ic_python_db-0.7.5 → ic_python_db-0.7.6}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ic_python_db
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.6
|
|
4
4
|
Summary: A lightweight key-value database written in Python, intended for use on the Internet Computer (IC)
|
|
5
5
|
Home-page: https://github.com/smart-social-contracts/ic-python-db
|
|
6
6
|
Author: Smart Social Contracts
|
|
@@ -264,8 +264,8 @@ class Entity:
|
|
|
264
264
|
)
|
|
265
265
|
self._update_timestamps(caller_id)
|
|
266
266
|
|
|
267
|
-
# Save to database
|
|
268
|
-
data = self.
|
|
267
|
+
# Save to database (full serialization preserves all relations)
|
|
268
|
+
data = self._serialize_full()
|
|
269
269
|
|
|
270
270
|
if not self._do_not_save:
|
|
271
271
|
logger.debug(f"Saving entity {self._type}@{self._id} to database")
|
|
@@ -511,9 +511,14 @@ class Entity:
|
|
|
511
511
|
|
|
512
512
|
while len(ret) < count and from_id <= cls.max_id():
|
|
513
513
|
logger.info(f"Loading entity {from_id}")
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
514
|
+
try:
|
|
515
|
+
entity = cls.load(str(from_id))
|
|
516
|
+
if entity:
|
|
517
|
+
ret.append(entity)
|
|
518
|
+
except (ValueError, AttributeError) as e:
|
|
519
|
+
# Skip entities with broken/dangling relation references
|
|
520
|
+
# (full fix: issue #4 — lazy relation resolution)
|
|
521
|
+
logger.warning(f"Skipping {cls.__name__}@{from_id}: {e}")
|
|
517
522
|
from_id += 1
|
|
518
523
|
|
|
519
524
|
return ret
|
|
@@ -559,19 +564,15 @@ class Entity:
|
|
|
559
564
|
# Remove from context
|
|
560
565
|
self.__class__._context.discard(self)
|
|
561
566
|
|
|
562
|
-
def
|
|
563
|
-
"""
|
|
564
|
-
|
|
565
|
-
Returns:
|
|
566
|
-
Dict containing the entity's serializable data
|
|
567
|
-
"""
|
|
567
|
+
def _serialize_base(self) -> Dict[str, Any]:
|
|
568
|
+
"""Shared serialization logic: core data, properties, and instance attributes."""
|
|
568
569
|
# Get mixin data first if available
|
|
569
570
|
data = super().serialize() if hasattr(super(), "serialize") else {}
|
|
570
571
|
|
|
571
572
|
# Add core entity data
|
|
572
573
|
data.update(
|
|
573
574
|
{
|
|
574
|
-
"_type": self._type,
|
|
575
|
+
"_type": self._type,
|
|
575
576
|
"_id": self._id,
|
|
576
577
|
}
|
|
577
578
|
)
|
|
@@ -589,30 +590,74 @@ class Entity:
|
|
|
589
590
|
if not k.startswith("_"):
|
|
590
591
|
data[k] = v
|
|
591
592
|
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
593
|
+
return data
|
|
594
|
+
|
|
595
|
+
@staticmethod
|
|
596
|
+
def _get_entity_reference(entity):
|
|
597
|
+
"""Get the best reference for an entity: alias value if available, otherwise _id."""
|
|
598
|
+
if hasattr(entity.__class__, "__alias__") and entity.__class__.__alias__:
|
|
599
|
+
alias_field = entity.__class__.__alias__
|
|
600
|
+
alias_value = getattr(entity, alias_field, None)
|
|
601
|
+
if alias_value is not None:
|
|
602
|
+
return alias_value
|
|
603
|
+
return entity._id
|
|
604
|
+
|
|
605
|
+
def _serialize_full(self) -> Dict[str, Any]:
|
|
606
|
+
"""Full serialization including all relations. Used by _save() for persistence."""
|
|
607
|
+
data = self._serialize_base()
|
|
608
|
+
|
|
609
|
+
from ic_python_db.properties import ManyToMany, OneToMany
|
|
601
610
|
|
|
602
611
|
for rel_name, rel_entities in self._relations.items():
|
|
603
612
|
if rel_entities:
|
|
604
|
-
# Check if this is a *ToMany relation that should always be a list
|
|
605
613
|
rel_prop = getattr(self.__class__, rel_name, None)
|
|
606
|
-
|
|
614
|
+
is_to_many = isinstance(rel_prop, (OneToMany, ManyToMany))
|
|
615
|
+
|
|
616
|
+
if len(rel_entities) == 1 and not is_to_many:
|
|
617
|
+
data[rel_name] = self._get_entity_reference(rel_entities[0])
|
|
618
|
+
else:
|
|
619
|
+
data[rel_name] = [
|
|
620
|
+
self._get_entity_reference(e) for e in rel_entities
|
|
621
|
+
]
|
|
622
|
+
|
|
623
|
+
return data
|
|
624
|
+
|
|
625
|
+
def serialize(self) -> Dict[str, Any]:
|
|
626
|
+
"""Convert the entity to a portable serializable dictionary.
|
|
627
|
+
|
|
628
|
+
OneToMany relations are skipped (reconstructed from reverse ManyToOne).
|
|
629
|
+
For bilateral OneToOne relations, only the alphabetically-earlier entity
|
|
630
|
+
type serializes the reference, avoiding circular dependencies.
|
|
631
|
+
|
|
632
|
+
Returns:
|
|
633
|
+
Dict containing the entity's serializable data
|
|
634
|
+
"""
|
|
635
|
+
data = self._serialize_base()
|
|
636
|
+
|
|
637
|
+
from ic_python_db.properties import ManyToMany, OneToMany, OneToOne
|
|
638
|
+
|
|
639
|
+
for rel_name, rel_entities in self._relations.items():
|
|
640
|
+
if rel_entities:
|
|
641
|
+
rel_prop = getattr(self.__class__, rel_name, None)
|
|
642
|
+
|
|
643
|
+
# Skip OneToMany — always reconstructed from reverse ManyToOne
|
|
644
|
+
if isinstance(rel_prop, OneToMany):
|
|
645
|
+
continue
|
|
646
|
+
# For OneToOne bilateral, only serialize on one deterministic side:
|
|
647
|
+
# the entity whose type name is alphabetically <= the target type.
|
|
648
|
+
if isinstance(rel_prop, OneToOne):
|
|
649
|
+
target_type = rel_entities[0]._type if rel_entities else None
|
|
650
|
+
if target_type and self._type > target_type:
|
|
651
|
+
continue
|
|
607
652
|
|
|
608
653
|
is_to_many = isinstance(rel_prop, (OneToMany, ManyToMany))
|
|
609
654
|
|
|
610
655
|
if len(rel_entities) == 1 and not is_to_many:
|
|
611
|
-
|
|
612
|
-
data[rel_name] = get_entity_reference(rel_entities[0])
|
|
656
|
+
data[rel_name] = self._get_entity_reference(rel_entities[0])
|
|
613
657
|
else:
|
|
614
|
-
|
|
615
|
-
|
|
658
|
+
data[rel_name] = [
|
|
659
|
+
self._get_entity_reference(e) for e in rel_entities
|
|
660
|
+
]
|
|
616
661
|
|
|
617
662
|
return data
|
|
618
663
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ic_python_db
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.6
|
|
4
4
|
Summary: A lightweight key-value database written in Python, intended for use on the Internet Computer (IC)
|
|
5
5
|
Home-page: https://github.com/smart-social-contracts/ic-python-db
|
|
6
6
|
Author: Smart Social Contracts
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ic_python_db"
|
|
7
|
-
version = "0.7.
|
|
7
|
+
version = "0.7.6"
|
|
8
8
|
description = "A lightweight key-value database written in Python, intended for use on the Internet Computer (IC)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [
|
|
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name="ic_python_db",
|
|
8
|
-
version="0.7.
|
|
8
|
+
version="0.7.6",
|
|
9
9
|
author="Smart Social Contracts",
|
|
10
10
|
author_email="smartsocialcontracts@gmail.com",
|
|
11
11
|
description="A lightweight key-value database with entity relationships and audit logging",
|
|
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
|
|
File without changes
|
|
File without changes
|