Changeset 2f650ac in flexoentity
- Timestamp:
- 10/22/25 14:22:21 (3 months ago)
- Branches:
- master
- Children:
- 3d16c35
- Parents:
- 859e2b1
- Files:
-
- 5 edited
-
flexoentity/__init__.py (modified) (2 diffs)
-
flexoentity/domain.py (modified) (2 diffs)
-
flexoentity/flexo_entity.py (modified) (6 diffs)
-
tests/conftest.py (modified) (2 diffs)
-
tests/test_id_stress.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
flexoentity/__init__.py
r859e2b1 r2f650ac 9 9 from .id_factory import FlexOID, canonical_seed 10 10 from .flexo_entity import FlexoEntity, EntityType, EntityState 11 from .domain import Domain 11 12 12 13 __all__ = [ … … 15 16 "FlexoEntity", 16 17 "EntityType", 18 "Domain", 17 19 "EntityState", 18 20 ] -
flexoentity/domain.py
r859e2b1 r2f650ac 1 from dataclasses import dataclass 2 from flexoentity.flexo_entity import FlexoEntity, EntityType, EntityState 3 1 4 @dataclass 2 5 class Domain(FlexoEntity): 3 abbrev: str 4 fullname: str 6 fullname: str = "" 5 7 description: str = "" 6 8 classification: str = "UNCLASSIFIED" 7 9 owner: str = "unknown" 8 10 11 def __post_init__(self): 12 self.etype = EntityType.DOMAIN 13 super().__post_init__() 14 9 15 @property 10 def qtype(self): # or entity_type 11 return EntityType.DOMAIN 16 def text_seed(self) -> str: 17 """Deterministic text seed for ID generation.""" 18 return f"{self.domain}|{self.fullname}|{self.classification}|{self.owner}" 12 19 13 20 def to_dict(self): 14 21 base = super().to_dict() 15 22 base.update({ 16 "abbrev": self.abbrev,17 23 "fullname": self.fullname, 18 24 "description": self.description, … … 21 27 }) 22 28 return base 29 30 @classmethod 31 def from_dict(cls, data): 32 return cls( 33 fullname=data.get("fullname", ""), 34 description=data.get("description", ""), 35 classification=data.get("classification", "UNCLASSIFIED"), 36 owner=data.get("owner", "unknown"), 37 state=EntityState[data.get("state", "DRAFT")], 38 ) -
flexoentity/flexo_entity.py
r859e2b1 r2f650ac 4 4 """ 5 5 import json 6 import re 6 7 from enum import Enum, auto 7 8 from dataclasses import dataclass, field … … 14 15 from flexoentity.id_factory import FlexOID 15 16 from flexoentity import canonical_seed 16 17 17 18 18 # ────────────────────────────────────────────────────────────────────────────── … … 28 28 DATABASE = auto() 29 29 CERTIFICATE = auto() 30 30 DOMAIN = auto() 31 31 32 def short(self) -> str: 32 33 mapping = { 33 34 EntityType.QUESTION: "Q", 35 EntityType.MEDIA: "M", 36 EntityType.DOMAIN: "DOM", 34 37 EntityType.CATALOG: "CAT", 35 38 EntityType.EXAM: "EX", … … 89 92 class FlexoEntity(ABC): 90 93 domain: str 91 etype: EntityType 92 state: EntityState = EntityState.DRAFT 93 flexo_id: FlexOID = field(init=False) 94 created_at: datetime = field(default_factory=lambda: datetime.now(UTC)) 95 updated_at: Optional[datetime] = None 96 97 # ─────────────────────────────────────────────────────────────── 98 94 etype: EntityType 95 state: EntityState 96 97 OID_PATTERN = re.compile( 98 r"^(?P<domain>[A-Z0-9]+)-(?P<etype>[A-Z]+)" 99 r"(?P<date>\d{6,8})-(?P<hash>[0-9A-F]+)@(?P<version>\d{3})(?P<state>[A-Z])$" 100 ) 101 102 def __str__(self) -> str: 103 return f"{self.domain}-{self.etype}{self.date}-{self.unique_hash}@{self.version:03d}{self.state}" 104 105 @classmethod 106 def from_string(cls, s: str) -> "FlexOID": 107 """Rehydrate a FlexOID from its canonical string form.""" 108 m = cls.OID_PATTERN.match(s.strip()) 109 if not m: 110 raise ValueError(f"Invalid FlexOID string: {s}") 111 gd = m.groupdict() 112 return cls( 113 domain=gd["domain"], 114 etype=gd["etype"], 115 state=gd["state"], 116 ) 99 117 @property 100 118 @abstractmethod … … 121 139 "domain": self.domain, 122 140 "etype": self.etype.name, 123 "text_seed": self.text_seed,124 141 "state": self.state.name, 125 "version": self.version,126 142 "flexo_id": str(self.flexo_id), 127 "signature": self.flexo_id.signature,128 "created_at": self.created_at.isoformat(),129 "updated_at": self.updated_at.isoformat() if self.updated_at else None,130 143 } 131 144 … … 139 152 ) 140 153 obj.flexo_id = FlexOID(data["flexo_id"], data.get("signature", "")) 141 if data.get("updated_at"):142 obj.updated_at = datetime.fromisoformat(data["updated_at"])143 154 return obj 144 155 -
tests/conftest.py
r859e2b1 r2f650ac 3 3 import pytest 4 4 import json 5 from flexoentity import FlexoEntity, EntityType, EntityState 5 from flexoentity import FlexoEntity, EntityType, EntityState, Domain 6 6 7 7 … … 34 34 """Generic FlexoEntity-like instance in draft state.""" 35 35 return DummyEntity( 36 domain= "AF",36 domain=Domain(domain="SIG", etype=EntityType.DOMAIN, state=EntityState.DRAFT, fullname="Signal Corps", classification="RESTRICTED"), 37 37 etype=EntityType.CATALOG, 38 38 state=EntityState.DRAFT, -
tests/test_id_stress.py
r859e2b1 r2f650ac 6 6 import random 7 7 8 from flexoentity import FlexOID, EntityType, EntityState 8 from flexoentity import FlexOID, EntityType, EntityState, Domain 9 9 10 10 from tests.conftest import DummyEntity … … 13 13 def test_bulk_generation_uniqueness(): 14 14 """Generate 10,000 IDs and assert uniqueness (statistical test).""" 15 domain = "AF" 15 domain = Domain(domain="SIG", etype=EntityType.DOMAIN, state=EntityState.DRAFT, 16 fullname="Signal Corps", classification="RESTRICTED", owner="MESE") 17 16 18 etype = EntityType.QUESTION 17 19 estate = EntityState.DRAFT … … 44 46 should yield the same base ID (without suffix). 45 47 """ 46 domain = "AF" 48 domain = Domain(domain="SIG", etype=EntityType.DOMAIN, state=EntityState.DRAFT, 49 fullname="Signal Corps", classification="RESTRICTED") 47 50 etype = EntityType.CATALOG 48 51 estate = EntityState.DRAFT
Note:
See TracChangeset
for help on using the changeset viewer.
