Files
Jyotisha/tests/report_english_fictional.py
T
jesse-uxGrok (agent loop)Cursor
ba1ffeb35f fix(report): keep the English edition when one phrase was untranslated
The English personal report was discarded whenever a Chinese fragment survived the trailing glossary. English sections now render the English fields that were already calculated.

Co-Authored-By: Grok (agent loop)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-22 02:56:00 +08:00

206 lines
8.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Fixed fictional charts for the English-edition sweep (issue #89).
Not collected by pytest. Birth data stays inside the generator; callers report
only the chart index and leftover fragments.
"""
from __future__ import annotations
import builtins
import importlib
import os
import random
import re
import sys
from pathlib import Path
HAN = re.compile(r"[㐀-鿿豈-﫿]")
GLUE = (
"scoreandtimeline",
"marriagequality",
"inperiod start",
"Dashasignpresent",
"aturninperiod",
"atpresent",
"planetsinbetween",
"whetherinunderway",
"withSaturn",
"careerplanetAmK",
"careerdirection",
"supportingstrongdegree",
"beneficfactor count",
"comparativelystrong",
"occupiesplanetcount",
"lordandstrong",
"lordstrongand",
"weakafflicted",
"partialreducedweak",
"debilitatedsign",
"planetenterssign",
"planetsdistributed",
"beneficlocated",
"house 5 level",
"house seven-round",
"condition planets",
"[source text retained",
)
SEED = 20261021
TODAY = "2026-10-21"
CHART_COUNT = 200
def fictional_case(index: int) -> dict:
"""Chart ``index`` from the fixed sequence. Replaying 0..index keeps the seed stable."""
rng = random.Random(SEED)
chosen = None
for i in range(index + 1):
year = rng.randint(1940, 2015)
month = rng.randint(1, 12)
day = rng.randint(1, 28)
hour = rng.randint(0, 23)
minute = rng.randint(0, 59)
lat = round(rng.uniform(-45, 60), 4)
lon = round(rng.uniform(-120, 150), 4)
tz = max(-12.0, min(14.0, round(lon / 7.5) * 0.5))
chosen = {
"name": f"chart-{i:03d}",
"year": year,
"month": month,
"day": day,
"hour": hour,
"minute": minute,
"second": 0,
"lat": lat,
"lon": lon,
"tz": tz,
"node_mode": rng.choice(("mean", "true")),
"ayanamsa": rng.choice(("lahiri", "raman", "kp")),
"today": TODAY,
"transit_date": TODAY,
"target_year": 2026,
"age": 2026 - year,
"birth_time_accuracy": "confirmed",
}
return chosen
def block_jhora() -> None:
"""Fail closed if this process imports PyJHora. Call once per process."""
real_import = builtins.__import__
def guarded(name, globals=None, locals=None, fromlist=(), level=0):
if str(name).split(".", 1)[0] == "jhora":
raise ImportError("jhora blocked")
return real_import(name, globals, locals, fromlist, level)
builtins.__import__ = guarded
real_import_module = importlib.import_module
def guarded_module(name, package=None):
if str(name).split(".", 1)[0] == "jhora":
raise ImportError("jhora blocked")
return real_import_module(name, package)
importlib.import_module = guarded_module
for key in list(sys.modules):
if key == "jhora" or key.startswith("jhora."):
del sys.modules[key]
def _prepare_process() -> None:
root = Path(__file__).resolve().parents[1]
for entry in (str(root), str(root / "scripts")):
if entry not in sys.path:
sys.path.insert(0, entry)
block_jhora()
def _residue(text: str) -> dict:
found = HAN.findall(text or "")
glue = [word for word in GLUE if word in (text or "")]
return {"han": len(found), "han_chars": "".join(sorted(set(found)))[:40], "glue": glue}
def render_english(index: int) -> dict:
"""Build one fictional packet and run ``_english_edition``. No birth data in the result."""
_prepare_process()
from scripts.jyotish_engine import build_professional_report_reference_packet, cmd_full_reading
from scripts.professional_report_reference import _english_edition, _export_args
birth = fictional_case(index)
reading = cmd_full_reading(type("Args", (), dict(birth))())
packet = dict(build_professional_report_reference_packet(reading, _export_args(dict(birth)), []))
packet["report_version"] = "pl9_personal_long_report.v3"
edition = _english_edition(packet, True)
markdown = edition.get("markdown_en") or ""
flags = _flags_from_packet(packet)
applicability = edition.get("reader_dasha_applicability_en") or ""
body = _residue(markdown)
extra = _residue(applicability)
dump_dir = os.environ.get("REPORT_ENGLISH_SWEEP_DUMP")
if dump_dir and markdown:
path = Path(dump_dir)
path.mkdir(parents=True, exist_ok=True)
(path / f"chart-{index:03d}.md").write_text(markdown, encoding="utf-8")
return {
"i": index,
"status": "ok" if markdown and not edition.get("english_unavailable") else edition.get("english_unavailable") or "empty",
"han": body["han"] + extra["han"],
"han_chars": (body["han_chars"] + extra["han_chars"])[:40],
"glue": sorted(set(body["glue"] + extra["glue"])),
**flags,
}
def _flags_from_packet(packet: dict) -> dict:
rath = (((packet.get("worksheets") or {}).get("timing_and_predictive_systems") or {}).get("narayana_dasha") or {}).get("rath") or {}
rule = rath.get("current_md_antardasha_rule") or {}
direction = rule.get("direction") if isinstance(rule, dict) else {}
advanced = (packet.get("worksheets") or {}).get("advanced_systems") or {}
doshas = advanced.get("yogas_doshas") or {}
kaal = doshas.get("kaal_sarp_dosha") or {}
birth_sheet = (packet.get("worksheets") or {}).get("birth_and_parameters") or {}
pack = birth_sheet.get("panchanga") or {}
panchanga = pack.get("raw") if isinstance(pack, dict) and isinstance(pack.get("raw"), dict) else pack
yoga = advanced.get("yoga") if isinstance(advanced.get("yoga"), dict) else {}
rows = [row for row in (yoga.get("detected_yogas") or []) if isinstance(row, dict)]
return {
"level": rath.get("strength_level_decided"),
"direction": rath.get("direction"),
"ad_rule": direction.get("rule") if isinstance(direction, dict) else None,
"overall": panchanga.get("overall_quality") if isinstance(panchanga, dict) else None,
"kaal": kaal.get("type") if isinstance(kaal, dict) else None,
"punarphoo": any(str(row.get("strength") or "") == "观察" or "Punarphoo" in str(row.get("name") or "") for row in rows),
}
def chart_flags(index: int) -> dict:
"""Class flags used to prove the smoke set covers L1–L6. No birth data."""
_prepare_process()
from scripts.jyotish_engine import build_professional_report_reference_packet, cmd_full_reading
from scripts.professional_report_reference import _export_args
birth = fictional_case(index)
reading = cmd_full_reading(type("Args", (), dict(birth))())
packet = dict(build_professional_report_reference_packet(reading, _export_args(dict(birth)), []))
rath = (((packet.get("worksheets") or {}).get("timing_and_predictive_systems") or {}).get("narayana_dasha") or {}).get("rath") or {}
rule = rath.get("current_md_antardasha_rule") or {}
direction = rule.get("direction") if isinstance(rule, dict) else {}
advanced = (packet.get("worksheets") or {}).get("advanced_systems") or {}
doshas = advanced.get("yogas_doshas") or {}
kaal = doshas.get("kaal_sarp_dosha") or {}
birth_sheet = (packet.get("worksheets") or {}).get("birth_and_parameters") or {}
pack = birth_sheet.get("panchanga") or {}
panchanga = pack.get("raw") if isinstance(pack, dict) and isinstance(pack.get("raw"), dict) else pack
yoga = advanced.get("yoga") if isinstance(advanced.get("yoga"), dict) else {}
names = [str(row.get("name") or "") for row in (yoga.get("detected_yogas") or []) if isinstance(row, dict)]
strengths = [str(row.get("strength") or "") for row in (yoga.get("detected_yogas") or []) if isinstance(row, dict)]
return {
"i": index,
"level": rath.get("strength_level_decided"),
"direction": rath.get("direction"),
"ad_rule": direction.get("rule") if isinstance(direction, dict) else None,
"overall": panchanga.get("overall_quality") if isinstance(panchanga, dict) else None,
"kaal": kaal.get("type") if isinstance(kaal, dict) else None,
"punarphoo": "观察" in strengths or any("Punarphoo" in name for name in names),
}