Source code for stellium.presentation.sections._utils

"""
Utility functions for report sections.

These helper functions are shared across multiple section implementations
for consistent formatting and display.
"""

from stellium.core.models import ObjectType
from stellium.core.registry import (
    ASPECT_REGISTRY,
    CELESTIAL_REGISTRY,
    get_aspect_by_alias,
    get_aspect_info,
)
from stellium.engines.dignities import DIGNITIES


[docs] def get_object_display(name: str) -> tuple[str, str]: """ Get display name and glyph for a celestial object. Args: name: Internal object name (e.g., "Sun", "True Node") Returns: Tuple of (display_name, glyph) """ if name in CELESTIAL_REGISTRY: info = CELESTIAL_REGISTRY[name] return info.display_name, info.glyph return name, ""
[docs] def get_sign_glyph(sign_name: str) -> str: """Get the zodiac glyph for a sign name.""" if sign_name in DIGNITIES: return DIGNITIES[sign_name]["symbol"] return ""
[docs] def get_aspect_display(aspect_name: str) -> tuple[str, str]: """ Get display name and glyph for an aspect. Args: aspect_name: Aspect name (e.g., "Conjunction", "Trine") Returns: Tuple of (name, glyph) """ if aspect_name in ASPECT_REGISTRY: info = ASPECT_REGISTRY[aspect_name] return info.name, info.glyph return aspect_name, ""
[docs] def get_object_sort_key(position): """ Generate sort key for consistent object ordering in reports. Sorting hierarchy: 1. Object type (Planet < Node < Point < Asteroid < Angle < Midpoint) 2. Registry insertion order (for registered objects) 3. Swiss Ephemeris ID (for unregistered known objects) 4. Alphabetical name (for custom objects) Args: position: A celestial object position from CalculatedChart Returns: Tuple sort key for use with sorted() Example: positions = sorted(chart.positions, key=get_object_sort_key) """ # Define type ordering type_order = { ObjectType.PLANET: 0, ObjectType.NODE: 1, ObjectType.POINT: 2, ObjectType.ASTEROID: 3, ObjectType.ANGLE: 4, ObjectType.MIDPOINT: 5, } type_rank = type_order.get(position.object_type, 999) # Try registry order (using insertion order of dict keys) registry_keys = list(CELESTIAL_REGISTRY.keys()) if position.name in registry_keys: registry_index = registry_keys.index(position.name) return (type_rank, registry_index) # Fallback to Swiss Ephemeris ID if ( hasattr(position, "swiss_ephemeris_id") and position.swiss_ephemeris_id is not None ): return (type_rank, 10000 + position.swiss_ephemeris_id) # Final fallback: alphabetical by name return (type_rank, 20000, position.name)
[docs] def get_aspect_sort_key(aspect_name: str) -> tuple: """ Generate sort key for consistent aspect ordering in reports. Sorting hierarchy: 1. Registry insertion order (aspects ordered by angle: 0°, 60°, 90°, etc.) 2. Angle value (for aspects not in registry) 3. Alphabetical name (final fallback) Args: aspect_name: Name of the aspect (e.g., "Conjunction", "Trine") Returns: Tuple sort key for use with sorted() Example: aspects = sorted(aspects, key=lambda a: get_aspect_sort_key(a.aspect_name)) """ # Try registry order (insertion order = angle order) registry_keys = list(ASPECT_REGISTRY.keys()) if aspect_name in registry_keys: registry_index = registry_keys.index(aspect_name) return (registry_index,) # Try to find by alias aspect_info = get_aspect_by_alias(aspect_name) if aspect_info and aspect_info.name in registry_keys: registry_index = registry_keys.index(aspect_info.name) return (registry_index,) # Fallback: try to get angle from registry aspect_info = get_aspect_info(aspect_name) if aspect_info: return (1000 + aspect_info.angle,) # Final fallback: alphabetical return (2000, aspect_name)
[docs] def abbreviate_house_system(system_name: str) -> str: """ Generate 2-4 character abbreviation for house system names. Args: system_name: Full house system name (e.g., "Placidus", "Whole Sign") Returns: Short abbreviation (e.g., "Pl", "WS") Example: >>> abbreviate_house_system("Placidus") 'Pl' >>> abbreviate_house_system("Whole Sign") 'WS' """ abbreviations = { "Placidus": "Pl", "Whole Sign": "WS", "Koch": "Ko", "Equal": "Eq", "Porphyry": "Po", "Regiomontanus": "Re", "Campanus": "Ca", "Morinus": "Mo", "Meridian": "Me", "Alcabitius": "Al", } return abbreviations.get(system_name, system_name[:4])