From a66fa3db32203fb472bade389f229e236eaa92ab Mon Sep 17 00:00:00 2001 From: 732642856 <732642856@qq.com> Date: Wed, 10 Jun 2026 13:22:17 +0800 Subject: [PATCH] =?UTF-8?q?v6.1.10:=20Package=20for=20PyPI=20=E2=80=94=20a?= =?UTF-8?q?dd=20jyotish=5Fvedic/=20package,=20CLI=20entry=20points,=20fix?= =?UTF-8?q?=20pyproject.toml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jyotish_vedic/__init__.py | 155 ++++++++++++++++++++++++++++++++++++ jyotish_vedic/cli.py | 25 ++++++ jyotish_vedic/engine.py | 24 ++++++ jyotish_vedic/mcp_server.py | 27 +++++++ pyproject.toml | 95 ++++++++++++++++------ 5 files changed, 301 insertions(+), 25 deletions(-) create mode 100644 jyotish_vedic/__init__.py create mode 100644 jyotish_vedic/cli.py create mode 100644 jyotish_vedic/engine.py create mode 100644 jyotish_vedic/mcp_server.py diff --git a/jyotish_vedic/__init__.py b/jyotish_vedic/__init__.py new file mode 100644 index 00000000..81c8be31 --- /dev/null +++ b/jyotish_vedic/__init__.py @@ -0,0 +1,155 @@ +""" +Jyotish Vedic Astrology — Comprehensive calculation engine + +A Python package for Vedic (Jyotish) astrology calculations: +- D1-D60 divisional charts (Varga) +- Vimshottari Dasha (planetary periods) +- Shadbala (six-fold planetary strength) +- Ashtakavarga (eight-fold bindus) +- Yoga detection (planetary combinations) +- Nakshatra analysis +- Transit calculations +- Full-reading synthesis + +License: MIT +""" + +import sys +import os + +# Add scripts dir to path so all engine modules are importable +_pkg_dir = os.path.dirname(os.path.abspath(__file__)) +_repo_root = os.path.dirname(_pkg_dir) +_scripts_dir = os.path.join(_repo_root, "scripts") +if _scripts_dir not in sys.path: + sys.path.insert(0, _scripts_dir) + +__version__ = "6.1.10" +__all__ = [ + "calculate_chart", + "calculate_dasha", + "calculate_shadbala", + "calculate_ashtakavarga", + "calculate_varga", + "calculate_yogas", + "full_reading", +] + +# Lazy imports — only load when called +def _import_engine(): + """Import jyotish_engine module (lazy to avoid heavy init).""" + import jyotish_engine + return jyotish_engine + + +def calculate_chart(year, month, day, hour, minute, lat, lon, tz, node_mode="mean"): + """Calculate D1 Rashi chart.""" + import json + import subprocess + engine = os.path.join(_scripts_dir, "jyotish_engine.py") + cmd = [ + sys.executable, engine, "chart", + "--year", str(year), "--month", str(month), "--day", str(day), + "--hour", str(hour), "--minute", str(minute), + "--lat", str(lat), "--lon", str(lon), "--tz", str(tz), + "--node-mode", node_mode, + ] + result = subprocess.run(cmd, capture_output=True, text=True, timeout=120) + return json.loads(result.stdout) if result.returncode == 0 else {"error": result.stderr} + + +def calculate_dasha(year, month, day, hour, minute, lat, lon, tz, years=10, node_mode="mean"): + """Calculate Vimshottari Dasha timeline.""" + import json + import subprocess + engine = os.path.join(_scripts_dir, "jyotish_engine.py") + cmd = [ + sys.executable, engine, "dasha", + "--year", str(year), "--month", str(month), "--day", str(day), + "--hour", str(hour), "--minute", str(minute), + "--lat", str(lat), "--lon", str(lon), "--tz", str(tz), + "--years", str(years), "--node-mode", node_mode, + ] + result = subprocess.run(cmd, capture_output=True, text=True, timeout=120) + return json.loads(result.stdout) if result.returncode == 0 else {"error": result.stderr} + + +def calculate_shadbala(year, month, day, hour, minute, lat, lon, tz, node_mode="mean"): + """Calculate Shadbala (six-fold strength).""" + import json + import subprocess + engine = os.path.join(_scripts_dir, "jyotish_engine.py") + cmd = [ + sys.executable, engine, "shadbala", + "--year", str(year), "--month", str(month), "--day", str(day), + "--hour", str(hour), "--minute", str(minute), + "--lat", str(lat), "--lon", str(lon), "--tz", str(tz), + "--node-mode", node_mode, + ] + result = subprocess.run(cmd, capture_output=True, text=True, timeout=120) + return json.loads(result.stdout) if result.returncode == 0 else {"error": result.stderr} + + +def calculate_ashtakavarga(year, month, day, hour, minute, lat, lon, tz, node_mode="mean"): + """Calculate Ashtakavarga matrix.""" + import json + import subprocess + engine = os.path.join(_scripts_dir, "jyotish_engine.py") + cmd = [ + sys.executable, engine, "ashtakavarga", + "--year", str(year), "--month", str(month), "--day", str(day), + "--hour", str(hour), "--minute", str(minute), + "--lat", str(lat), "--lon", str(lon), "--tz", str(tz), + "--node-mode", node_mode, + ] + result = subprocess.run(cmd, capture_output=True, text=True, timeout=120) + return json.loads(result.stdout) if result.returncode == 0 else {"error": result.stderr} + + +def calculate_varga(year, month, day, hour, minute, lat, lon, tz, varga="D9", node_mode="mean"): + """Calculate a specific Varga (D9, D10, etc.).""" + import json + import subprocess + engine = os.path.join(_scripts_dir, "jyotish_engine.py") + cmd = [ + sys.executable, engine, "varga", + "--year", str(year), "--month", str(month), "--day", str(day), + "--hour", str(hour), "--minute", str(minute), + "--lat", str(lat), "--lon", str(lon), "--tz", str(tz), + "--varga", varga, "--node-mode", node_mode, + ] + result = subprocess.run(cmd, capture_output=True, text=True, timeout=120) + return json.loads(result.stdout) if result.returncode == 0 else {"error": result.stderr} + + +def calculate_yogas(year, month, day, hour, minute, lat, lon, tz, node_mode="mean"): + """Detect Yogas in the birth chart.""" + import json + import subprocess + engine = os.path.join(_scripts_dir, "jyotish_engine.py") + cmd = [ + sys.executable, engine, "yoga", + "--year", str(year), "--month", str(month), "--day", str(day), + "--hour", str(hour), "--minute", str(minute), + "--lat", str(lat), "--lon", str(lon), "--tz", str(tz), + "--node-mode", node_mode, + ] + result = subprocess.run(cmd, capture_output=True, text=True, timeout=120) + return json.loads(result.stdout) if result.returncode == 0 else {"error": result.stderr} + + +def full_reading(year, month, day, hour, minute, lat, lon, tz, age, transit_date, node_mode="mean"): + """Run the complete full-reading pipeline.""" + import json + import subprocess + engine = os.path.join(_scripts_dir, "jyotish_engine.py") + cmd = [ + sys.executable, engine, "full-reading", + "--year", str(year), "--month", str(month), "--day", str(day), + "--hour", str(hour), "--minute", str(minute), + "--lat", str(lat), "--lon", str(lon), "--tz", str(tz), + "--age", str(age), "--transit-date", transit_date, + "--node-mode", node_mode, + ] + result = subprocess.run(cmd, capture_output=True, text=True, timeout=300) + return json.loads(result.stdout) if result.returncode == 0 else {"error": result.stderr} diff --git a/jyotish_vedic/cli.py b/jyotish_vedic/cli.py new file mode 100644 index 00000000..a238544f --- /dev/null +++ b/jyotish_vedic/cli.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +""" +Jyotish CLI entry point. +Usage: jyotish [args] +""" +import sys +import os + +SCRIPT_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "scripts") + + +def main(): + """Delegate to jyotish_engine.py CLI.""" + engine = os.path.join(SCRIPT_DIR, "jyotish_engine.py") + if not os.path.exists(engine): + print(f"Error: Engine not found at {engine}", file=sys.stderr) + sys.exit(1) + + # Pass all args after 'jyotish' to the engine + cmd = [sys.executable, engine] + sys.argv[1:] + os.execv(sys.executable, cmd) + + +if __name__ == "__main__": + main() diff --git a/jyotish_vedic/engine.py b/jyotish_vedic/engine.py new file mode 100644 index 00000000..c7c22af5 --- /dev/null +++ b/jyotish_vedic/engine.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 +""" +Jyotish Engine CLI wrapper. +Usage: jyotish-engine [args] +""" +import sys +import os + +SCRIPT_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "scripts") + + +def cli_main(): + """Delegate to jyotish_engine.py CLI.""" + engine = os.path.join(SCRIPT_DIR, "jyotish_engine.py") + if not os.path.exists(engine): + print(f"Error: Engine not found at {engine}", file=sys.stderr) + sys.exit(1) + + cmd = [sys.executable, engine] + sys.argv[1:] + os.execv(sys.executable, cmd) + + +if __name__ == "__main__": + cli_main() diff --git a/jyotish_vedic/mcp_server.py b/jyotish_vedic/mcp_server.py new file mode 100644 index 00000000..4b469805 --- /dev/null +++ b/jyotish_vedic/mcp_server.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +""" +Jyotish MCP Server entry point. +Usage: jyotish-mcp +""" +import sys +import os + +# The actual MCP server is at repo root; delegate to it +_repo_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +_mcp_server = os.path.join(_repo_root, "mcp_server.py") + + +def main(): + """Run the MCP server.""" + if not os.path.exists(_mcp_server): + print(f"Error: MCP server not found at {_mcp_server}", file=sys.stderr) + sys.exit(1) + + # Execute the root-level MCP server + with open(_mcp_server, "r", encoding="utf-8") as f: + code = compile(f.read(), _mcp_server, "exec") + exec(code, {"__file__": _mcp_server, "__name__": "__main__"}) + + +if __name__ == "__main__": + main() diff --git a/pyproject.toml b/pyproject.toml index 7cd315b0..1a21e930 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,37 +1,82 @@ +[build-system] +requires = ["setuptools>=61.0", "wheel"] +build-backend = "setuptools.build_meta" + [project] -name = "jyotish-vedic-astrology-skill" -version = "6.0.33" -description = "Jyotish WorkBuddy skill calculation engine and validation suite" +name = "jyotish-vedic-astrology" +version = "6.1.10" +description = "Comprehensive Jyotish (Vedic Astrology) calculation engine with AI-ready APIs" +readme = "README.md" +license = "MIT" requires-python = ">=3.11" +authors = [ + {name = "732642856", email = "dev@yinduzhanxing.local"}, +] +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Topic :: Scientific/Engineering :: Astronomy", + "Topic :: Software Development :: Libraries :: Python Modules", + "Topic :: Religion and Philosophy :: Astrology", +] +keywords = ["jyotish", "vedic", "astrology", "astronomy", "dasha", "varga", "nakshatra", "shadbala", "panchanga", "horoscope", "birth-chart"] dependencies = [ - "pyswisseph", + "pyswisseph>=2.8", ] [project.optional-dependencies] dev = [ - "pytest>=8.0", - "hypothesis>=6.0", - "coverage[toml]>=7.0", - "ruff>=0.6.0", + "pytest>=8.0", + "hypothesis>=6.0", + "coverage[toml]>=7.0", + "ruff>=0.6.0", + "build>=0.9", + "twine>=4.0", ] +[project.scripts] +jyotish = "jyotish_vedic.cli:main" +jyotish-engine = "jyotish_vedic.engine:cli_main" +jyotish-mcp = "jyotish_vedic.mcp_server:main" + +[project.urls] +Homepage = "https://github.com/732642856/yinduzhanxing" +Documentation = "https://github.com/732642856/yinduzhanxing#readme" +Repository = "https://github.com/732642856/yinduzhanxing" +"Bug Reports" = "https://github.com/732642856/yinduzhanxing/issues" +Changelog = "https://github.com/732642856/yinduzhanxing/blob/main/CHANGELOG.md" + +[tool.setuptools.packages.find] +where = ["."] +include = ["jyotish_vedic*"] +exclude = ["tests*", "docs*", "jyotish-app*", "benchmark*", "references*"] + +[tool.setuptools.package-data] +jyotish_vedic = ["*.json", "*.md", "*.csv", "*.db"] + [tool.pytest.ini_options] minversion = "8.0" testpaths = ["tests"] -pythonpath = ["scripts"] +pythonpath = ["jyotish_vedic"] addopts = "-q --strict-markers --strict-config" markers = [ - "slow: long-running validation tests", - "external: tests that depend on optional external datasets or tools", + "slow: long-running validation tests", + "external: tests that depend on optional external datasets or tools", ] [tool.coverage.run] branch = true -source = ["scripts"] +source = ["jyotish_vedic"] omit = [ - "scripts/add_high_confidence_yogas_batch1.py", - "scripts/build_standard_test_charts.py", - "scripts/_compute_one_chart.py", + "jyotish_vedic/add_high_confidence_yogas_batch1.py", + "jyotish_vedic/build_standard_test_charts.py", + "jyotish_vedic/_compute_one_chart.py", ] [tool.coverage.report] @@ -42,22 +87,22 @@ skip_covered = true target-version = "py311" line-length = 140 exclude = [ - ".git", - "__pycache__", - ".pytest_cache", - "jyotish-app", - "benchmark", + ".git", + "__pycache__", + ".pytest_cache", + "jyotish-app", + "benchmark", ] [tool.ruff.lint] select = ["E", "F", "I", "UP", "B", "SIM"] ignore = [ - "E501", - "E701", - "E702", - "E741", + "E501", + "E701", + "E702", + "E741", ] [tool.ruff.lint.per-file-ignores] "tests/**" = ["S101"] -"scripts/validate_bphs_invariants.py" = ["T201"] +"jyotish_vedic/validate_bphs_invariants.py" = ["T201"]