Core API¶
The tradition-agnostic core: value types, the engine contract, randomness, serialisation, and
errors. These symbols are re-exported from the top-level fortune_telling_core package.
Natal vs. timed readings¶
A reading has two distinct moments. birth_datetime (a per-tradition querent attribute) fixes the
natal chart and never changes. ReadingRequest.as_of is the moment you want time-varying fortunes
computed for — the luck/annual pillars (大運/流年), flying-star charts, almanac days, and similar
period results are derived from it. When as_of is unset, ReadingRequest.effective_at falls back
to requested_at, so existing callers are unaffected.
from datetime import UTC, datetime
# Same person, two different points in time — only `as_of` changes.
request = ReadingRequest(
deck_id=deck_id,
spread_id=spread_id,
querent=querent, # carries birth_datetime, location, etc.
as_of=datetime(2030, 1, 1, tzinfo=UTC),
)
as_of is the unified successor to the older per-tradition target_year / target_datetime
options. Those options still work and take precedence over as_of when supplied, so they remain
available for callers that only need to override a single year or date.
fortune_telling_core ¶
Draw
dataclass
¶
Draw(
deck_id: str,
spread_id: str,
selections: Sequence[Selection],
extras: Sequence[Selection] = (),
)
Recorded, replayable outcome of selecting symbols for a spread.
A Draw is authoritative for replay. Engines can interpret a recorded draw
without consulting an RNG or, for computed traditions, an ephemeris.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
deck_id
|
str
|
Identifier of the deck used for all selections. |
required |
spread_id
|
str
|
Identifier of the spread whose positions were filled. |
required |
selections
|
Sequence[Selection]
|
Ordered selections, one per spread position. |
required |
extras
|
Sequence[Selection]
|
Optional structured selections that are not bound to a spread
position — variable-count, computed facts an engine wants to expose
for interpretation (e.g. astrology aspects). Unlike |
()
|
Raises:
| Type | Description |
|---|---|
ValidationError
|
If identifiers are empty, there are no selections, or a position appears more than once. |
to_dict ¶
Serialize the draw to the stable JSON-compatible schema.
Returns:
| Type | Description |
|---|---|
JsonObject
|
A dictionary containing deck, spread, and selection data, plus |
JsonObject
|
|
Source code in src/fortune_telling_core/draw.py
from_dict
classmethod
¶
Deserialize a draw from the stable schema.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
JsonMapping
|
JSON-compatible mapping produced by |
required |
Returns:
| Type | Description |
|---|---|
Draw
|
The decoded draw. |
Raises:
| Type | Description |
|---|---|
ValidationError
|
If required fields are missing or malformed. |
Source code in src/fortune_telling_core/draw.py
Selection
dataclass
¶
A single chosen symbol for one spread position.
Selection is the smallest replay unit in the core model. Engines may
attach tradition-specific state in modifiers, but the core treats every
modifier as an opaque string.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
position_id
|
str
|
Identifier of the spread position this selection fills. |
required |
symbol_id
|
str
|
Identifier of the selected symbol in the active deck. |
required |
modifiers
|
Mapping[str, str] | None
|
Optional per-selection string metadata, such as tarot orientation or computed astrology longitude. |
None
|
Raises:
| Type | Description |
|---|---|
ValidationError
|
If |
to_dict ¶
Serialize the selection to the stable JSON-compatible schema.
Returns:
| Type | Description |
|---|---|
JsonObject
|
A dictionary containing |
JsonObject
|
|
Source code in src/fortune_telling_core/draw.py
from_dict
classmethod
¶
Deserialize a selection from the stable schema.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
JsonMapping
|
JSON-compatible mapping produced by |
required |
Returns:
| Type | Description |
|---|---|
Selection
|
The decoded selection. |
Raises:
| Type | Description |
|---|---|
ValidationError
|
If required fields are missing or malformed. |
Source code in src/fortune_telling_core/draw.py
Engine ¶
ExhaustedRngError ¶
Bases: FortuneTellingError
Raised when a replay RNG has no remaining values.
FortuneTellingError ¶
Bases: Exception
Base error for this package.
SchemaVersionError ¶
Bases: FortuneTellingError
Raised when serialized data uses an unsupported schema version.
UnknownSymbolError ¶
Bases: FortuneTellingError, LookupError
Raised when a recorded draw references symbols outside the active deck.
ValidationError ¶
Bases: FortuneTellingError, ValueError
Raised when a value object is internally inconsistent.
Provenance
dataclass
¶
Provenance(
engine_id: str,
engine_version: str,
library_version: str,
deck_id: str,
spread_id: str,
rng_kind: str | None = None,
rng_seed: str | None = None,
created_at: datetime = utc_now(),
notes: Sequence[str] = (),
)
Audit metadata attached to a reading.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
engine_id
|
str
|
Engine identifier. |
required |
engine_version
|
str
|
Engine version string. |
required |
library_version
|
str
|
|
required |
deck_id
|
str
|
Deck used by the reading. |
required |
spread_id
|
str
|
Spread used by the reading. |
required |
rng_kind
|
str | None
|
Optional RNG kind for random traditions. |
None
|
rng_seed
|
str | None
|
Optional RNG seed serialized as text. |
None
|
created_at
|
datetime
|
Timezone-aware creation timestamp. |
utc_now()
|
notes
|
Sequence[str]
|
Additional key-value style audit notes. |
()
|
Raises:
| Type | Description |
|---|---|
ValidationError
|
If |
created_at
class-attribute
instance-attribute
¶
to_dict ¶
Serialize provenance to a JSON-compatible dictionary.
Source code in src/fortune_telling_core/provenance.py
from_dict
classmethod
¶
Deserialize provenance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
JsonMapping
|
JSON-compatible provenance mapping. |
required |
Returns:
| Type | Description |
|---|---|
Provenance
|
The decoded provenance. |
Raises:
| Type | Description |
|---|---|
ValidationError
|
If required fields are missing or malformed. |
Source code in src/fortune_telling_core/provenance.py
PositionReading
dataclass
¶
Resolved result for one spread position.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
position
|
Position
|
Spread position metadata. |
required |
symbol
|
Symbol
|
Selected symbol metadata. |
required |
selection
|
Selection
|
Recorded selection that links the position and symbol. |
required |
to_dict ¶
Serialize the position reading to a JSON-compatible dictionary.
from_dict
classmethod
¶
Deserialize a position reading.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
JsonMapping
|
JSON-compatible position reading mapping. |
required |
Returns:
| Type | Description |
|---|---|
PositionReading
|
The decoded position reading. |
Raises:
| Type | Description |
|---|---|
ValidationError
|
If required fields are missing or malformed. |
Source code in src/fortune_telling_core/reading.py
Reading
dataclass
¶
Reading(
request: ReadingRequest,
spread: Spread,
draw: Draw,
positions: Sequence[PositionReading],
summary: str | None,
provenance: Provenance,
schema_version: int,
)
Complete self-contained reading.
A reading embeds its request, spread, draw, resolved position readings, and provenance so it can be serialized, audited, and replayed later.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
request
|
ReadingRequest
|
Original request. |
required |
spread
|
Spread
|
Spread used to resolve positions. |
required |
draw
|
Draw
|
Recorded draw. |
required |
positions
|
Sequence[PositionReading]
|
Resolved position readings. |
required |
summary
|
str | None
|
Optional engine-generated summary text. When present, this text is always plain American English. |
required |
provenance
|
Provenance
|
Audit metadata. |
required |
schema_version
|
int
|
Serialized schema version. |
required |
to_dict ¶
Serialize the reading to a JSON-compatible dictionary.
Source code in src/fortune_telling_core/reading.py
from_dict
classmethod
¶
Deserialize a reading.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
JsonMapping
|
JSON-compatible reading mapping. |
required |
Returns:
| Type | Description |
|---|---|
Reading
|
The decoded reading. |
Raises:
| Type | Description |
|---|---|
ValidationError
|
If required fields are missing or malformed. |
Source code in src/fortune_telling_core/reading.py
Querent
dataclass
¶
Person or subject for whom a reading is made.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
id
|
str
|
Stable application-level identifier. |
required |
display_name
|
str
|
Human-readable name for display. |
required |
attributes
|
Mapping[str, str] | None
|
Optional string metadata. Computed traditions use these fields for birth data when supplied. |
None
|
Raises:
| Type | Description |
|---|---|
ValidationError
|
If identifiers or attributes are invalid. |
to_dict ¶
Serialize the querent to a JSON-compatible dictionary.
from_dict
classmethod
¶
Deserialize a querent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
JsonMapping
|
JSON-compatible querent mapping. |
required |
Returns:
| Type | Description |
|---|---|
Querent
|
The decoded querent. |
Raises:
| Type | Description |
|---|---|
ValidationError
|
If required fields are missing or malformed. |
Source code in src/fortune_telling_core/request.py
ReadingRequest
dataclass
¶
ReadingRequest(
spread_id: str,
deck_id: str,
querent: Querent | None = None,
options: Mapping[str, str] | None = None,
requested_at: datetime = utc_now(),
as_of: datetime | None = None,
)
Input used by an engine to produce or replay a reading.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spread_id
|
str
|
Identifier of the requested spread. |
required |
deck_id
|
str
|
Identifier of the requested deck. |
required |
querent
|
Querent | None
|
Optional querent metadata. |
None
|
options
|
Mapping[str, str] | None
|
Engine-specific string options. |
None
|
requested_at
|
datetime
|
Timezone-aware request timestamp. |
utc_now()
|
as_of
|
datetime | None
|
Optional timezone-aware moment the reading should be computed
for. Traditions that report time-varying fortunes (luck/annual
pillars, flying-star charts, almanac days, transits) read this as
the reference point, falling back to |
None
|
Raises:
| Type | Description |
|---|---|
ValidationError
|
If identifiers, options, or timestamps are invalid. |
requested_at
class-attribute
instance-attribute
¶
effective_at
property
¶
Reference moment for time-varying fortunes.
Returns as_of when set, otherwise requested_at. This is the
single source of truth a tradition should consult when it needs the
"as of" moment but has no explicit per-tradition override.
to_dict ¶
Serialize the request to a JSON-compatible dictionary.
Source code in src/fortune_telling_core/request.py
from_dict
classmethod
¶
Deserialize a reading request.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
JsonMapping
|
JSON-compatible request mapping. |
required |
Returns:
| Type | Description |
|---|---|
ReadingRequest
|
The decoded request. |
Raises:
| Type | Description |
|---|---|
ValidationError
|
If required fields are missing or malformed. |
Source code in src/fortune_telling_core/request.py
RandomRng ¶
Seeded RNG with an explicit Fisher-Yates implementation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
seed
|
int | str | bytes | bytearray | None
|
Seed passed to |
None
|
Source code in src/fortune_telling_core/rng.py
randint ¶
Return an inclusive random integer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
low
|
int
|
Inclusive lower bound. |
required |
high
|
int
|
Inclusive upper bound. |
required |
Returns:
| Type | Description |
|---|---|
int
|
A random integer in the requested range. |
Raises:
| Type | Description |
|---|---|
ValidationError
|
If |
Source code in src/fortune_telling_core/rng.py
shuffle ¶
Return a deterministic Fisher-Yates permutation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Number of indices to permute. |
required |
Returns:
| Type | Description |
|---|---|
list[int]
|
A permutation of |
Raises:
| Type | Description |
|---|---|
ValidationError
|
If |
Source code in src/fortune_telling_core/rng.py
Rng ¶
Bases: Protocol
Narrow RNG protocol used by engines.
Engines depend on this small protocol rather than random.Random directly
so tests can inject deterministic replay streams.
randint ¶
Return an integer in the inclusive range [low, high].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
low
|
int
|
Inclusive lower bound. |
required |
high
|
int
|
Inclusive upper bound. |
required |
Returns:
| Type | Description |
|---|---|
int
|
An integer within the requested range. |
shuffle ¶
Return a permutation of range(n).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Number of indices to permute. |
required |
Returns:
| Type | Description |
|---|---|
list[int]
|
A list containing each integer from |
SequenceRng ¶
Replay/test RNG backed by fixed integer and float sequences.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ints
|
Iterable[int]
|
Integer values consumed by |
()
|
floats
|
Iterable[float]
|
Float values consumed by |
()
|
Example
Source code in src/fortune_telling_core/rng.py
randint ¶
Return the next integer from the replay sequence.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
low
|
int
|
Inclusive lower bound. |
required |
high
|
int
|
Inclusive upper bound. |
required |
Returns:
| Type | Description |
|---|---|
int
|
The next integer. |
Raises:
| Type | Description |
|---|---|
ExhaustedRngError
|
If no integer values remain. |
ValidationError
|
If bounds are invalid or the next value is outside the requested range. |
Source code in src/fortune_telling_core/rng.py
shuffle ¶
Consume n integers as an explicit permutation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
int
|
Number of indices to consume. |
required |
Returns:
| Type | Description |
|---|---|
list[int]
|
The next |
Raises:
| Type | Description |
|---|---|
ExhaustedRngError
|
If fewer than |
ValidationError
|
If |
Source code in src/fortune_telling_core/rng.py
random ¶
Return the next float from the replay sequence.
Returns:
| Type | Description |
|---|---|
float
|
The next float. |
Raises:
| Type | Description |
|---|---|
ExhaustedRngError
|
If no float values remain. |
ValidationError
|
If the next value is outside |
Source code in src/fortune_telling_core/rng.py
Position
dataclass
¶
One named slot in a spread.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
id
|
str
|
Stable position identifier. |
required |
name
|
str
|
Human-readable position name. |
required |
description
|
str
|
Optional explanation of the position's role. |
''
|
Raises:
| Type | Description |
|---|---|
ValidationError
|
If |
to_dict ¶
from_dict
classmethod
¶
Deserialize a position.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
JsonMapping
|
JSON-compatible position mapping. |
required |
Returns:
| Type | Description |
|---|---|
Position
|
The decoded position. |
Raises:
| Type | Description |
|---|---|
ValidationError
|
If required fields are missing or malformed. |
Source code in src/fortune_telling_core/spread.py
Spread
dataclass
¶
Ordered set of positions filled by a draw.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
id
|
str
|
Stable spread identifier. |
required |
name
|
str
|
Human-readable spread name. |
required |
positions
|
Sequence[Position]
|
Ordered positions in the spread. |
required |
Raises:
| Type | Description |
|---|---|
ValidationError
|
If the spread is empty or contains duplicate position ids. |
to_dict ¶
Serialize the spread to a JSON-compatible dictionary.
from_dict
classmethod
¶
Deserialize a spread.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
JsonMapping
|
JSON-compatible spread mapping. |
required |
Returns:
| Type | Description |
|---|---|
Spread
|
The decoded spread. |
Raises:
| Type | Description |
|---|---|
ValidationError
|
If required fields are missing or malformed. |
Source code in src/fortune_telling_core/spread.py
Deck
dataclass
¶
Ordered pool of symbols used by an engine.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
id
|
str
|
Stable deck identifier. |
required |
symbols
|
Sequence[Symbol]
|
Ordered symbols available to the engine. |
required |
weights
|
Sequence[int] | None
|
Optional positive integer weights matching |
None
|
Raises:
| Type | Description |
|---|---|
ValidationError
|
If the deck is empty, has duplicate symbol ids, or has invalid weights. |
symbol_by_id ¶
Return a symbol by id.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
symbol_id
|
str
|
Identifier to look up. |
required |
Returns:
| Type | Description |
|---|---|
Symbol | None
|
The matching symbol, or |
Source code in src/fortune_telling_core/symbols.py
to_dict ¶
Serialize the deck to a JSON-compatible dictionary.
Returns:
| Type | Description |
|---|---|
JsonObject
|
The stable deck representation. |
Source code in src/fortune_telling_core/symbols.py
from_dict
classmethod
¶
Deserialize a deck.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
JsonMapping
|
JSON-compatible deck mapping. |
required |
Returns:
| Type | Description |
|---|---|
Deck
|
The decoded deck. |
Raises:
| Type | Description |
|---|---|
ValidationError
|
If required fields are missing or malformed. |
Source code in src/fortune_telling_core/symbols.py
Symbol
dataclass
¶
Tradition-neutral symbol that can appear in a deck.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
id
|
str
|
Stable symbol identifier, unique inside its deck. |
required |
name
|
str
|
Human-readable symbol name. |
required |
attributes
|
Mapping[str, str]
|
Optional string metadata. Traditions use this for details such as tarot suit, zodiac element, or stem polarity. |
dict()
|
Raises:
| Type | Description |
|---|---|
ValidationError
|
If |
attributes
class-attribute
instance-attribute
¶
to_dict ¶
Serialize the symbol to a JSON-compatible dictionary.
Returns:
| Type | Description |
|---|---|
JsonObject
|
The stable symbol representation. |
from_dict
classmethod
¶
Deserialize a symbol.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
JsonMapping
|
JSON-compatible symbol mapping. |
required |
Returns:
| Type | Description |
|---|---|
Symbol
|
The decoded symbol. |
Raises:
| Type | Description |
|---|---|
ValidationError
|
If required fields are missing or malformed. |
Source code in src/fortune_telling_core/symbols.py
reading_from_json ¶
Deserialize a reading from JSON.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
str
|
JSON string produced by |
required |
Returns:
| Type | Description |
|---|---|
Reading
|
The decoded reading. |
Raises:
| Type | Description |
|---|---|
SchemaVersionError
|
If the payload declares a future schema version. |
ValidationError
|
If |
JSONDecodeError
|
If |