source: flexoentity/tests/conftest.py@ b24d72e

Last change on this file since b24d72e was b24d72e, checked in by Enrico Schwass <ennoausberlin@…>, 8 weeks ago

move DomainManager to FlexoGrader

  • Property mode set to 100644
File size: 3.0 KB
Line 
1# tests/stubs/single_choice_question.py
2import pytest
3from datetime import datetime
4from dataclasses import dataclass, field
5from typing import List
6from flexoentity import FlexOID, FlexoEntity, EntityType, EntityState, Domain
7
8@pytest.fixture
9def fixed_datetime(monkeypatch):
10 class FixedDate(datetime):
11 @classmethod
12 def now(cls, tz=None):
13 return datetime(2025, 11, 1, tzinfo=tz)
14 monkeypatch.setattr("flexoentity.id_factory.datetime", FixedDate)
15 return FixedDate
16
17@dataclass
18class AnswerOption:
19 id: str
20 text: str
21 points: float = 0.0
22
23 def to_dict(self):
24 return {"id": self.id, "text": self.text, "points": self.points}
25
26 @classmethod
27 def from_dict(cls, data):
28 return cls(
29 id=data.get("id", ""),
30 text=data.get("text", ""),
31 points=data.get("points", 0.0)
32 )
33
34
35@dataclass
36class SingleChoiceQuestion(FlexoEntity):
37 """A minimal stub to test FlexoEntity integration."""
38 ENTITY_TYPE = EntityType.ITEM
39
40 text: str = ""
41 options: List[AnswerOption] = field(default_factory=list)
42
43 def __post_init__(self):
44 # If no FlexOID yet, generate a draft ID now.
45 if not getattr(self, "flexo_id", None):
46 self.flexo_id = FlexOID.safe_generate(
47 domain_id=self.domain_id,
48 entity_type=SingleChoiceQuestion.ENTITY_TYPE.value, # 'I'
49 state=EntityState.DRAFT.value, # 'D'
50 text=self.text_seed or self.text,
51 version=1,
52 )
53
54 @classmethod
55 def default(cls):
56 return cls()
57
58 def to_dict(self):
59 base = super().to_dict()
60 base.update({
61 "text": self.text,
62 "options": [opt.to_dict() for opt in self.options],
63 })
64 return base
65
66 @property
67 def text_seed(self) -> str:
68 """Include answer options (and points) for deterministic ID generation."""
69
70 joined = "|".join(
71 f"{opt.text.strip()}:{opt.points}"
72 for opt in sorted(self.options, key=lambda o: o.text.strip().lower())
73 )
74 return f"{self.text}{joined}"
75
76 @classmethod
77 def from_dict(cls, data):
78 obj = cls(text=data.get("text", ""),
79 options=[AnswerOption.from_dict(o) for o in data.get("options", [])],
80 )
81 # restore FlexoEntity core fields
82 if "flexo_id" in data:
83 obj.flexo_id = FlexOID.to_dict(data["flexo_id"])
84 return obj
85
86@pytest.fixture
87def sample_domain():
88 domain_id = "PY_ARITHM"
89 return Domain.with_domain_id(domain_id=domain_id,
90 fullname="PYTHON_ARITHMETIC",
91 description="ALL ABOUT ARITHMETIC IN PYTHON")
92
93@pytest.fixture
94def sample_question(sample_domain):
95 q = SingleChoiceQuestion.with_domain_id(domain_id=sample_domain.domain_id,
96 text="What is 2 + 2?",
97 options=[])
98 q._update_fingerprint()
99 return q
Note: See TracBrowser for help on using the repository browser.