Changeset ca39274 in flexoentity


Ignore:
Timestamp:
10/28/25 12:16:31 (3 months ago)
Author:
Enrico Schwass <ennoausberlin@…>
Branches:
master
Children:
8aa20c7
Parents:
52ccac6
Message:

minor cleanups

Files:
4 edited

Legend:

Unmodified
Added
Removed
  • flexoentity/flexo_entity.py

    r52ccac6 rca39274  
    77from enum import Enum, auto
    88from dataclasses import dataclass, field
    9 from datetime import datetime
    109from typing import Optional
    1110from abc import ABC, abstractmethod
     
    2928    CERTIFICATE = auto()
    3029    DOMAIN = auto()
    31    
     30
    3231    def short(self) -> str:
    3332        mapping = {
     
    9796    fingerprint: str = field(default_factory=str)
    9897    origin: Optional[str] = field(default=None)
    99    
     98
    10099    OID_PATTERN = re.compile(
    101100        r"^(?P<domain>[A-Z0-9]+)-(?P<etype>[A-Z]+)"
    102101        r"(?P<date>\d{6,8})-(?P<hash>[0-9A-F]+)@(?P<version>\d{3})(?P<state>[A-Z])$"
    103102    )
    104 
    105     def __str__(self) -> str:
    106         return f"{self.domain_code()}-{self.etype}{self.date}-{self.unique_hash}@{self.version:03d}{self.state}"
    107103
    108104    @classmethod
     
    145141        class itself to avoid circular initialization.
    146142        """
    147        
     143
    148144        self.flexo_id = FlexOID.safe_generate(self.domain_code(),
    149145                                         self.etype.short(),
     
    159155            f"fingerprint={self.fingerprint}..., v{self.version})"
    160156        )
     157
    161158    def to_dict(self):
    162159        return {
     
    168165            "origin": self.origin,
    169166        }
    170    
     167
    171168    @classmethod
    172169    def from_dict(cls, data):
     
    175172        abbrev, fullname = (lambda p: (p[0], p[1] if len(p) > 1 else ""))(domain.split("_", 1))
    176173        domain_obj = Domain(
    177             abbrev,
     174            domain=abbrev,
    178175            etype=EntityType.DOMAIN,
    179176            state=EntityState.DRAFT,  # default when reconstructing context
     
    365362            canonical_seed(entity.text_seed).encode("utf-8"), digest_size=8
    366363        ).hexdigest().upper()
     364        print(entity.fingerprint)
     365        print(expected_fp)
    367366        return expected_fp == entity.fingerprint
    368367
  • flexoentity/id_factory.py

    r52ccac6 rca39274  
    4747    WARN_THRESHOLD = 900
    4848
     49
    4950    # keep in-memory registry for same-session collisions (optional)
     51    # NOTE: We might remove this soon
    5052    _seen_hashes = set()
    5153
     
    7476            raise ValueError("Cannot order FlexOIDs from different prefixes")
    7577        return self.version < other.version
    76        
     78
    7779    def __hash__(self):
    7880        return hash(self.flexo_id)
     
    8183    def _blake_hash(text: str) -> str:
    8284        """Return a 12-hex BLAKE2s digest."""
    83         return hashlib.blake2s(text.encode("utf-8"), digest_size=6).hexdigest().upper()  # 6 bytes → 12 hex
     85        return hashlib.blake2s(text.encode("utf-8"),
     86                               digest_size=6).hexdigest().upper()  # 6 bytes → 12 hex
    8487
    8588    @staticmethod
     
    134137
    135138        return oid
    136    
     139
    137140    @staticmethod
    138141    def generate(domain: str, etype: str, estate: str, text: str,
     
    159162        return FlexOID(flexo_id_str)
    160163
    161     # ──────────────────────────────────────────────────────────────────────────
    162 
    163164    @property
    164165    def state_code(self):
     
    168169            raise ValueError(f"Invalid Flex-O ID format: {self.flexo_id}")
    169170        return part[-1]
    170 
    171     # ──────────────────────────────────────────────────────────────────────────
    172     #  Parsed Accessors
    173     # ──────────────────────────────────────────────────────────────────────────
    174171
    175172    @property
     
    250247            "state": self.state_code,
    251248        }
    252     # ──────────────────────────────────────────────────────────────────────────
    253249
    254250    @classmethod
     
    290286        return cls(new_id)
    291287
    292     # ──────────────────────────────────────────────────────────────────────────
    293288    @staticmethod
    294289    def clone_new_base(domain: str, etype: str, estate: str, text: str):
  • tests/test_id_lifecycle.py

    r52ccac6 rca39274  
    9999    q.sign()
    100100    q.publish()
     101    q.obsolete()
    101102    old_id = str(q.flexo_id)
    102     q.obsolete()
    103103    q.clone_new_base()
    104104    assert q.origin == old_id
  • tests/test_persistance_integrity.py

    r52ccac6 rca39274  
    66import pytest
    77
    8 from flexoentity import EntityState
    98from builder.questions import RadioQuestion, AnswerOption
     9from flexoentity import EntityState, EntityType, Domain
    1010
    11 
    12 # ──────────────────────────────────────────────────────────────────────────────
    1311@pytest.fixture
    14 def approved_question(domain):
     12def approved_question():
    1513    """Provide a fully approved and published RadioQuestion for persistence tests."""
    1614    q = RadioQuestion(
    17         domain=domain,
     15        domain=Domain(domain="GEN", etype=EntityType.DOMAIN, state=EntityState.DRAFT),
    1816        etype=None,  # RadioQuestion sets this internally to EntityType.QUESTION
    1917        state=EntityState.DRAFT,
    2018        text="What is Ohm’s law?",
    2119        options=[
    22             AnswerOption(text="U = R × I", points=1),
    23             AnswerOption(text="U = I / R", points=0),
    24             AnswerOption(text="R = U × I", points=0),
     20            AnswerOption(id="OP1", text="U = R × I", points=1),
     21            AnswerOption(id="OP2", text="U = I / R", points=0),
     22            AnswerOption(id="OP3", text="R = U × I", points=0),
    2523        ],
    2624    )
     
    3735    """
    3836    json_str = approved_question.to_json()
     37    print("JSON", json_str)
    3938    loaded = RadioQuestion.from_json(json_str)
    4039
     40    print("Approved", approved_question.text_seed)
     41    print("Loaded", loaded.text_seed)
    4142    # Fingerprint and state should match — integrity must pass
    4243    assert RadioQuestion.verify_integrity(loaded)
     
    4647    assert approved_question.flexo_id == loaded.flexo_id
    4748    assert loaded.state == approved_question.state
    48 
    49 
    50 # ──────────────────────────────────────────────────────────────────────────────
    5149
    5250@pytest.mark.skip(reason="FlexOIDs regenerated on import; tampering detection not yet implemented")
     
    6058    loaded = RadioQuestion.from_json(tampered_json)
    6159    assert not RadioQuestion.verify_integrity(loaded)
    62 
    63 
    64 # ──────────────────────────────────────────────────────────────────────────────
    6560
    6661@pytest.mark.skip(reason="FlexOIDs regenerated on import; corruption detection not yet applicable")
Note: See TracChangeset for help on using the changeset viewer.