fix(aspects): pass planet speed into the three production callers (BUG-1479, upstream e628118d)
aspects.py itself is in d226b0e53 because it was already staged. Ketu and applying/separating behavior are covered by the geometry test. Callers pass numeric speeds, or None when speed is absent. calc_house_aspects does not take speed.
Co-Authored-By: Grok (agent loop)
This commit is contained in:
co-authored by
Grok (agent loop)
parent
bd09485243
commit
8aed605a43
@@ -7674,11 +7674,18 @@ class JyotishComputeService(VedastroEvidenceMixin, SynastryMixin):
|
||||
return {}
|
||||
|
||||
def _compute_aspects(self, body):
|
||||
_, planet_lons = self._planet_lons_from_body(body)
|
||||
planets, planet_lons = self._planet_lons_from_body(body)
|
||||
if len(planet_lons) < 2:
|
||||
raise BadRequest('planets must include at least two longitude values')
|
||||
asc_lon = self._asc_lon_from_body(body)
|
||||
result = _load_local_module('aspects').calc_all_aspects(planet_lons, asc_lon)
|
||||
planet_speeds = {
|
||||
name: float(row['speed'])
|
||||
for name, row in (planets or {}).items()
|
||||
if isinstance(row, dict) and isinstance(row.get('speed'), (int, float))
|
||||
}
|
||||
result = _load_local_module('aspects').calc_all_aspects(
|
||||
planet_lons, asc_lon, planet_speeds=planet_speeds or None,
|
||||
)
|
||||
return {
|
||||
'success': True,
|
||||
'endpoint': 'aspects',
|
||||
|
||||
@@ -14376,11 +14376,19 @@ def cmd_aspects(args):
|
||||
return {"error": f"aspects模块导入失败: {e}"}
|
||||
planets = chart.get('planets', {})
|
||||
planet_lons = {}
|
||||
planet_speeds = {}
|
||||
for pn, pd in planets.items():
|
||||
if isinstance(pd, dict) and 'degree' in pd:
|
||||
planet_lons[pn] = pd['degree']
|
||||
if isinstance(pd, dict) and isinstance(pd.get('speed'), (int, float)):
|
||||
planet_speeds[pn] = float(pd['speed'])
|
||||
asc_deg = chart.get('ascendant', {}).get('lon', chart.get('ascendant', {}).get('degree', 0))
|
||||
return _build_response_envelope('aspects', calc_all_aspects(planet_lons, asc_deg), args=args, execution_status='executed')
|
||||
return _build_response_envelope(
|
||||
'aspects',
|
||||
calc_all_aspects(planet_lons, asc_deg, planet_speeds=planet_speeds or None),
|
||||
args=args,
|
||||
execution_status='executed',
|
||||
)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
@@ -16235,7 +16243,12 @@ def cmd_full_reading(args):
|
||||
stage_started = time.perf_counter()
|
||||
try:
|
||||
from aspects import calc_all_aspects, calc_house_aspects
|
||||
aspects_result = calc_all_aspects(planet_lons, asc_deg)
|
||||
aspect_speeds = {
|
||||
name: float(row['speed'])
|
||||
for name, row in (chart.get('planets') or {}).items()
|
||||
if isinstance(row, dict) and isinstance(row.get('speed'), (int, float))
|
||||
}
|
||||
aspects_result = calc_all_aspects(planet_lons, asc_deg, planet_speeds=aspect_speeds or None)
|
||||
aspects_result['house_aspects'] = [
|
||||
calc_house_aspects(float(planet_lons[planet]), planet, asc_deg)
|
||||
for planet in ('Sun', 'Moon', 'Mars', 'Mercury', 'Jupiter', 'Venus', 'Saturn')
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
"""Directed drishti geometry and actual relative-motion regressions."""
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import pytest
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / 'scripts'))
|
||||
from aspects import calc_all_aspects
|
||||
|
||||
|
||||
@pytest.mark.parametrize('planet,house,angle', [
|
||||
('Mars', 4, 90), ('Mars', 8, 210), ('Jupiter', 5, 120),
|
||||
('Jupiter', 9, 240), ('Saturn', 3, 60), ('Saturn', 10, 270),
|
||||
])
|
||||
def test_directed_special_aspect_survives_pair_order(planet, house, angle):
|
||||
for positions in ({planet: 350, 'Venus': (350 + angle) % 360},
|
||||
{'Venus': (350 + angle) % 360, planet: 350}):
|
||||
rows = calc_all_aspects(positions, 150)['aspects']
|
||||
row = next(r for r in rows if r['type'] == f'{planet}_aspect_{house}')
|
||||
assert (row['planet1'], row['planet2'], row['aspect_degree'], row['orb']) == (planet, 'Venus', angle, 0)
|
||||
|
||||
|
||||
def test_mars_reverse_fourth_is_not_fourth():
|
||||
rows = calc_all_aspects({'Mars': 0, 'Venus': 270}, 150)['aspects']
|
||||
assert not any(r['type'] == 'Mars_aspect_4' for r in rows)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('speed,expected', [(1, False), (-1, True)])
|
||||
def test_phase_uses_relative_velocity(speed, expected):
|
||||
row = calc_all_aspects({'Sun': 359, 'Mercury': 1}, 180,
|
||||
planet_speeds={'Sun': 0, 'Mercury': speed})['aspects'][0]
|
||||
assert row['applying'] is expected
|
||||
|
||||
|
||||
def test_missing_speed_is_unknown_not_a_direction_guess():
|
||||
assert calc_all_aspects({'Sun': 10, 'Moon': 11}, 180)['aspects'][0]['applying'] is None
|
||||
|
||||
|
||||
def test_explicit_ketu_without_rahu_is_retained():
|
||||
rows = calc_all_aspects({'Sun': 10, 'Ketu': 190}, 100)['aspects']
|
||||
assert len(rows) == 1 and rows[0]['type'] == 'opposition'
|
||||
|
||||
|
||||
def test_exact_node_opposition_has_no_applying_direction():
|
||||
row = calc_all_aspects({'Rahu': 10}, 100, planet_speeds={'Rahu': -.05})['aspects'][0]
|
||||
assert row['phase'] == 'exact' and row['applying'] is None
|
||||
Reference in New Issue
Block a user