Skip to content

Commit aa3532b

Browse files
committed
feat: refactor CI/CD workflows and enhance synthwave UI for astronomical data display
1 parent e1f0db4 commit aa3532b

8 files changed

Lines changed: 127 additions & 140 deletions

File tree

.github/workflows/cache-uv-build.yaml

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,28 @@
1-
name: Build uv cache
1+
name: Build uv cache (Reusable)
22

33
on:
4-
push:
5-
branches:
6-
- '**'
7-
paths:
8-
- 'uv.lock'
9-
- 'pyproject.toml'
10-
workflow_dispatch:
4+
workflow_call:
115

126
jobs:
137
build-cache:
148
runs-on: ubuntu-latest
159
env:
1610
UV_VERSION: '0.10.2'
1711
PYTHON_VERSION: '3.13'
18-
1912
steps:
2013
- name: Checkout repository
2114
uses: actions/checkout@v6
22-
2315
- name: Install uv
2416
uses: astral-sh/setup-uv@v7
2517
with:
2618
version: ${{ env.UV_VERSION }}
2719
python-version: ${{ env.PYTHON_VERSION }}
2820
enable-cache: false
29-
3021
- name: Install dependencies and populate cache
3122
run: |
3223
echo "Building global UV cache..."
3324
uv sync
3425
echo "Cache populated successfully"
35-
3626
- name: Save uv caches
3727
uses: actions/cache/save@v5
3828
with:

.github/workflows/ci-cd.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ on:
1212
workflow_dispatch:
1313

1414
jobs:
15+
cache:
16+
uses: ./.github/workflows/cache-uv-build.yaml
17+
1518
lint:
1619
uses: ./.github/workflows/ruff.yaml
1720

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
"""Export core modules for use in other modules."""
22

3-
from sample_python_app.core.config import settings, weather_settings
3+
4+
from sample_python_app.core.config import Settings, settings, weather_settings
45
from sample_python_app.core.data_loader import fetch_astronomical_data_from_api
5-
from sample_python_app.core.display import display_astronomical_data
66
from sample_python_app.core.logging import setup_logger
7+
from sample_python_app.core.display import display_astronomical_data
78

89
__all__ = [
910
"settings",
1011
"weather_settings",
1112
"setup_logger",
12-
"display_astronomical_data",
1313
"fetch_astronomical_data_from_api",
14+
"Settings",
15+
"display_astronomical_data",
1416
]

src/sample_python_app/core/data_loader.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
from pydantic import ValidationError
55

66
from sample_python_app.core.logging import setup_logger
7-
from sample_python_app.models import WeatherGovFeature
7+
from sample_python_app.models import AstronomicalData, WeatherGovFeature
88

99

10-
def fetch_astronomical_data_from_api(lat: float, lon: float):
10+
def fetch_astronomical_data_from_api(lat: float, lon: float) -> AstronomicalData:
1111
"""Fetch and validate astronomical data from weather.gov API for given coordinates.
1212
1313
Args:
Lines changed: 3 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1,129 +1,11 @@
11
"""Handles formatting and displaying astronomical data using rich and pyfiglet."""
22

3-
from datetime import datetime
4-
5-
from pyfiglet import Figlet
6-
from rich.align import Align
7-
from rich.console import Console
8-
from rich.panel import Panel
9-
from rich.table import Table
10-
from rich.text import Text
11-
123
from sample_python_app.core.config import settings
134
from sample_python_app.core.logging import setup_logger
145

156

167
def display_astronomical_data(astro):
17-
"""Format and display astronomical data using rich and pyfiglet.
18-
19-
Args:
20-
astro: AstronomicalData object containing sunrise, sunset, and formatted values.
21-
22-
Returns:
23-
None
24-
25-
"""
26-
logger = setup_logger(mode="silent")
27-
console = Console()
28-
# Synthwave color palette (no longer used)
29-
30-
header = Figlet(font="slant", width=120).renderText("SYNTHWAVE SUNRISE 🌅")
31-
logger.info("Displaying Synthwave Sunrise header.")
32-
header_text = Text(header)
33-
header_text.stylize("bold magenta")
34-
35-
sunrise_local = astro.sunrise.astimezone(settings.tz)
36-
sunset_local = astro.sunset.astimezone(settings.tz)
37-
date_art = Figlet(font="mini", width=150).renderText(
38-
sunrise_local.strftime("%A, %B %d, %Y")
39-
)
40-
logger.info(f'Displaying date: {sunrise_local.strftime("%A, %B %d, %Y")})')
41-
date_text = Text(date_art)
42-
date_text.stylize("bold cyan")
43-
44-
# Stylized sunrise/sunset
45-
sun_art = Figlet(font="starwars", width=120).renderText("SUNRISE")
46-
sun_set_art = Figlet(font="starwars", width=120).renderText("SUNSET")
47-
sun_text = Text(sun_art)
48-
sun_text.stylize("bold yellow")
49-
# Sunrise time as figlet
50-
sunrise_time_art = Figlet(font="big", width=100).renderText(
51-
sunrise_local.strftime("%H:%M:%S")
52-
)
53-
sunrise_time_text = Text(sunrise_time_art)
54-
sunrise_time_text.stylize("bold yellow")
55-
56-
sun_set_text = Text(sun_set_art)
57-
sun_set_text.stylize("bold blue")
58-
# Sunrise time as figlet with AM/PM
59-
sunrise_time_str = sunrise_local.strftime("%I:%M:%S %p")
60-
sunrise_time_art = Figlet(font="big", width=100).renderText(sunrise_time_str)
61-
sunrise_time_text = Text(sunrise_time_art)
62-
sunrise_time_text.stylize("bold yellow")
63-
64-
sun_set_text = Text(sun_set_art)
65-
sun_set_text.stylize("bold blue")
66-
# Sunset time as figlet with AM/PM
67-
sunset_time_str = sunset_local.strftime("%I:%M:%S %p")
68-
sunset_time_art = Figlet(font="big", width=100).renderText(sunset_time_str)
69-
sunset_time_text = Text(sunset_time_art)
70-
sunset_time_text.stylize("bold blue")
71-
72-
astro_table = Table(show_header=True, header_style="bold magenta", box=None)
73-
astro_table.add_column("Event", style="bold #ff00cc")
74-
astro_table.add_column("Local Time", style="bold #00eaff")
75-
tz = settings.tz
76-
time_fmt = "%I:%M:%S %p %Z"
77-
# Color mapping for event types
78-
event_colors = {
79-
"sunrise": "#ffe066", # yellow
80-
"sunset": "#5dade2", # blue
81-
"transit": "#ffb347", # orange
82-
"civil twilight begin": "#f7cac9", # pink
83-
"civil twilight end": "#92a8d1", # light blue
84-
"nautical twilight begin": "#f9d423", # gold
85-
"nautical twilight end": "#6a89cc", # purple-blue
86-
"astronomical twilight begin": "#b388ff", # violet
87-
"astronomical twilight end": "#2e86c1", # deep blue
88-
}
89-
for name, dt in astro.as_local(tz).items():
90-
label = name.replace("_", " ").title()
91-
if isinstance(dt, datetime):
92-
value = dt.strftime(time_fmt)
93-
else:
94-
value = str(dt)
95-
logger.info(f"Displaying {label}: {value}")
96-
# Pick color based on event type
97-
color = event_colors.get(label.lower(), "#e17055") # fallback: coral
98-
astro_table.add_row(
99-
f"[{color}]{label}[/{color}]", f"[{color}]{value}[/{color}]"
100-
)
101-
102-
# Compose all parts into a single renderable for the panel
103-
from rich.columns import Columns
104-
from rich.console import Group
105-
106-
# Combine sunrise and sunset figlet art and times in the same row
107-
sun_figlet_row = Columns(
108-
[
109-
Group(Align.center(sun_text), Align.center(sunrise_time_text)),
110-
Group(Align.center(sun_set_text), Align.center(sunset_time_text)),
111-
],
112-
align="center",
113-
expand=True,
114-
)
8+
"""Display astronomical data using the synthwave terminal UI."""
9+
from sample_python_app.ui.synthwave import synthwave_display
11510

116-
panel_content = Group(
117-
Align.center(header_text),
118-
Align.center(date_text),
119-
sun_figlet_row,
120-
Align.center(astro_table),
121-
)
122-
console.print(
123-
Panel(
124-
panel_content,
125-
title="[bold #ff6ec7]Synthwave Astronomical Events[/bold #ff6ec7]",
126-
border_style="#ff00cc",
127-
padding=(1, 2),
128-
)
129-
)
11+
synthwave_display(astro, settings)
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""Models package for weather.gov API response parsing."""
22

3-
from sample_python_app.models.weather_gov import WeatherGovFeature
3+
from sample_python_app.models.weather_gov import AstronomicalData, WeatherGovFeature
44

5-
__all__ = ["WeatherGovFeature"]
5+
__all__ = ["WeatherGovFeature", "AstronomicalData"]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"""UI package for synthwave terminal display and related components."""
2+
3+
from sample_python_app.ui.synthwave import synthwave_display
4+
5+
__all__ = ["synthwave_display"]
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
"""Synthwave terminal UI for astronomical data display using rich and pyfiglet."""
2+
3+
from datetime import datetime
4+
5+
from pyfiglet import Figlet
6+
from rich.align import Align
7+
from rich.columns import Columns
8+
from rich.console import Console, Group
9+
from rich.panel import Panel
10+
from rich.table import Table
11+
from rich.text import Text
12+
13+
from sample_python_app.core import Settings, setup_logger
14+
from sample_python_app.models import AstronomicalData
15+
16+
17+
def synthwave_display(astro: AstronomicalData, settings: Settings):
18+
"""Display astronomical data in a synthwave terminal UI."""
19+
logger = setup_logger(mode="silent")
20+
console = Console()
21+
logger.info("Rendering synthwave terminal UI for astronomical data.")
22+
header = Figlet(font="slant", width=120).renderText("SYNTHWAVE SUNRISE 🌅")
23+
logger.info("Header rendered as figlet art.")
24+
header_text = Text(header)
25+
header_text.stylize("bold magenta")
26+
27+
sunrise_local = astro.sunrise.astimezone(settings.tz)
28+
sunset_local = astro.sunset.astimezone(settings.tz)
29+
logger.info(f"Local sunrise: {sunrise_local}, Local sunset: {sunset_local}")
30+
date_str = sunrise_local.strftime("%A, %B %d, %Y")
31+
date_art = Figlet(font="mini", width=150).renderText(date_str)
32+
logger.info(f"Date rendered as figlet: {date_str}")
33+
date_text = Text(date_art)
34+
date_text.stylize("bold cyan")
35+
36+
sun_art = Figlet(font="starwars", width=120).renderText("SUNRISE")
37+
sun_set_art = Figlet(font="starwars", width=120).renderText("SUNSET")
38+
sun_text = Text(sun_art)
39+
sun_text.stylize("bold yellow")
40+
sunrise_time_str = sunrise_local.strftime("%I:%M:%S %p")
41+
logger.info(f"Sunrise time (figlet): {sunrise_time_str}")
42+
sunrise_time_art = Figlet(font="big", width=100).renderText(sunrise_time_str)
43+
sunrise_time_text = Text(sunrise_time_art)
44+
sunrise_time_text.stylize("bold yellow")
45+
46+
sun_set_text = Text(sun_set_art)
47+
sun_set_text.stylize("bold blue")
48+
sunset_time_str = sunset_local.strftime("%I:%M:%S %p")
49+
logger.info(f"Sunset time (figlet): {sunset_time_str}")
50+
sunset_time_art = Figlet(font="big", width=100).renderText(sunset_time_str)
51+
sunset_time_text = Text(sunset_time_art)
52+
sunset_time_text.stylize("bold blue")
53+
54+
# Table with color-coded events
55+
astro_table = Table(show_header=True, header_style="bold magenta", box=None)
56+
astro_table.add_column("Event", style="bold #ff00cc")
57+
astro_table.add_column("Local Time", style="bold #00eaff")
58+
tz = settings.tz
59+
time_fmt = "%I:%M:%S %p %Z"
60+
event_colors = {
61+
"sunrise": "#ffe066",
62+
"sunset": "#5dade2",
63+
"transit": "#ffb347",
64+
"civil twilight begin": "#f7cac9",
65+
"civil twilight end": "#92a8d1",
66+
"nautical twilight begin": "#f9d423",
67+
"nautical twilight end": "#6a89cc",
68+
"astronomical twilight begin": "#b388ff",
69+
"astronomical twilight end": "#2e86c1",
70+
}
71+
for name, dt in astro.as_local(tz).items():
72+
label = name.replace("_", " ").title()
73+
if isinstance(dt, datetime):
74+
value = dt.strftime(time_fmt)
75+
else:
76+
value = str(dt)
77+
color = event_colors.get(label.lower(), "#e17055")
78+
logger.info(f"Event: {label}, Time: {value}, Color: {color}")
79+
astro_table.add_row(
80+
f"[{color}]{label}[/{color}]", f"[{color}]{value}[/{color}]"
81+
)
82+
83+
sun_figlet_row = Columns(
84+
[
85+
Group(Align.center(sun_text), Align.center(sunrise_time_text)),
86+
Group(Align.center(sun_set_text), Align.center(sunset_time_text)),
87+
],
88+
align="center",
89+
expand=True,
90+
)
91+
92+
panel_content = Group(
93+
Align.center(header_text),
94+
Align.center(date_text),
95+
sun_figlet_row,
96+
Align.center(astro_table),
97+
)
98+
console.print(
99+
Panel(
100+
panel_content,
101+
title="[bold #ff6ec7]Synthwave Astronomical Events[/bold #ff6ec7]",
102+
border_style="#ff00cc",
103+
padding=(1, 2),
104+
)
105+
)

0 commit comments

Comments
 (0)