isobar-cli 1.1.2__tar.gz → 1.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {isobar_cli-1.1.2/src/isobar_cli.egg-info → isobar_cli-1.3.0}/PKG-INFO +114 -39
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/README.md +110 -37
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/pyproject.toml +13 -10
- isobar_cli-1.3.0/src/isobar_cli/__init__.py +1 -0
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/src/isobar_cli/api.py +42 -10
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/src/isobar_cli/config.py +21 -0
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/src/isobar_cli/logic.py +72 -2
- isobar_cli-1.3.0/src/isobar_cli/ui.py +582 -0
- {isobar_cli-1.1.2 → isobar_cli-1.3.0/src/isobar_cli.egg-info}/PKG-INFO +114 -39
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/src/isobar_cli.egg-info/requires.txt +3 -0
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/tests/test_ui.py +9 -6
- isobar_cli-1.1.2/src/isobar_cli/__init__.py +0 -1
- isobar_cli-1.1.2/src/isobar_cli/ui.py +0 -259
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/LICENSE +0 -0
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/setup.cfg +0 -0
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/src/isobar_cli/location.py +0 -0
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/src/isobar_cli/main.py +0 -0
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/src/isobar_cli/models.py +0 -0
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/src/isobar_cli.egg-info/SOURCES.txt +0 -0
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/src/isobar_cli.egg-info/dependency_links.txt +0 -0
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/src/isobar_cli.egg-info/entry_points.txt +0 -0
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/src/isobar_cli.egg-info/top_level.txt +0 -0
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/tests/test_api.py +0 -0
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/tests/test_isobar_extra.py +0 -0
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/tests/test_location.py +0 -0
- {isobar_cli-1.1.2 → isobar_cli-1.3.0}/tests/test_main.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: isobar-cli
|
|
3
|
-
Version: 1.
|
|
4
|
-
Summary: A
|
|
3
|
+
Version: 1.3.0
|
|
4
|
+
Summary: A terminal weather tool with industrial aesthetic, focusing on Real Feel and Windchill.
|
|
5
5
|
Author: Beau Bremer / KnowOneActual
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/KnowOneActual/isobar-cli
|
|
@@ -29,6 +29,8 @@ Provides-Extra: test
|
|
|
29
29
|
Requires-Dist: pytest>=7.0.0; extra == "test"
|
|
30
30
|
Requires-Dist: requests-mock>=1.11.0; extra == "test"
|
|
31
31
|
Requires-Dist: pytest-cov>=4.1.0; extra == "test"
|
|
32
|
+
Provides-Extra: timezone
|
|
33
|
+
Requires-Dist: pytz>=2024.1; extra == "timezone"
|
|
32
34
|
Dynamic: license-file
|
|
33
35
|
|
|
34
36
|
# Isobar CLI
|
|
@@ -36,7 +38,7 @@ Dynamic: license-file
|
|
|
36
38
|

|
|
37
39
|

|
|
38
40
|
[](https://badge.fury.io/py/isobar-cli)
|
|
39
|
-

|
|
40
42
|

|
|
41
43
|

|
|
42
44
|

|
|
@@ -54,11 +56,13 @@ Most weather apps overwhelm with data. Isobar strips away everything except what
|
|
|
54
56
|
- **Essential over comprehensive** — Show Real Feel, not 47 data points.
|
|
55
57
|
- **Terminal-native** — Built for quick checks within a developer workflow.
|
|
56
58
|
- **Zero friction** — No API keys or configuration files required.
|
|
57
|
-
- **Information density** —
|
|
59
|
+
- **Information density** — Industrial dashboard UI for maximum readability.
|
|
58
60
|
- **Intentional features** — Each feature must answer: *"Does this help someone understand what it feels like outside?"*
|
|
61
|
+
- **Distinctive aesthetic** — Retro-futuristic industrial styling that avoids generic "AI slop"
|
|
59
62
|
|
|
60
63
|
## ✨ Features
|
|
61
64
|
|
|
65
|
+
- **Industrial Aesthetic** — Retro-futuristic weather observatory dashboard with brutalist styling 🏭
|
|
62
66
|
- **Auto-Location** — `isobar` detects the city automatically 🌍
|
|
63
67
|
- **Weather Condition Icons** — WMO-standard emoji + plain-English description (☀️ Clear sky, 🌨️ Moderate snow, ⛈️ Thunderstorm)
|
|
64
68
|
- **Real Feel** — Apparent temperature metrics (what it *actually* feels like).
|
|
@@ -75,12 +79,16 @@ Most weather apps overwhelm with data. Isobar strips away everything except what
|
|
|
75
79
|
- **Metric Support** — `--metric` or `-m` for Celsius, km/h, and mm.
|
|
76
80
|
- **No API Keys** — Free Open-Meteo and ip-api.com.
|
|
77
81
|
- **Zero Config** — Works instantly after installation.
|
|
82
|
+
- **Visual Gauges** — Temperature and humidity gauge visualizations 📊
|
|
83
|
+
- **Severity Indicators** — Weather condition severity icons (⚡, ▲, ●, ○, ◇)
|
|
84
|
+
- **Wind Categories** — Descriptive wind speed classifications (CALM, LIGHT, GENTLE, etc.)
|
|
85
|
+
- **Industrial Styling** — Heavy borders, uppercase labels, status columns
|
|
78
86
|
- **Phase 7: Intuition & Analysis** — Higher-level context and automated insights:
|
|
79
|
-
- **Preparation Guidance** — Clothing and gear suggestions
|
|
87
|
+
- **Preparation Guidance** — Clothing and gear suggestions with priority levels 🧥☂️🧴
|
|
80
88
|
- **Temporal Context** — Comparison with previous day conditions 📈
|
|
81
89
|
- **UV Index Monitoring** — Sun protection guidance with intensity levels ☀️
|
|
82
90
|
- **Wind Gust Alerts** — Highlighting of significant gust events 💨⚠️
|
|
83
|
-
- **Home City Persistence** — Set a default city with `isobar home "Your City"` 🏠
|
|
91
|
+
- **Home City Persistence** — Set a default city with `isobar home "Your City"` 🏠 *(Note: Due to a Typer limitation, this currently shows weather for "Home, Kansas" instead of setting home city. Manual config editing required.)*
|
|
84
92
|
|
|
85
93
|
## 🚀 Installation
|
|
86
94
|
|
|
@@ -124,12 +132,16 @@ isobar London Tokyo Paris # Multiple cities
|
|
|
124
132
|
isobar "New York" # Use quotes for multi-word cities
|
|
125
133
|
|
|
126
134
|
# Hourly outlook (next 12h)
|
|
127
|
-
isobar --hourly
|
|
128
|
-
isobar -H
|
|
135
|
+
isobar --hourly Chicago
|
|
136
|
+
isobar -H Chicago
|
|
129
137
|
|
|
130
138
|
# 7-day forecast
|
|
131
|
-
isobar --forecast
|
|
132
|
-
isobar -f
|
|
139
|
+
isobar --forecast Chicago
|
|
140
|
+
isobar -f Chicago
|
|
141
|
+
|
|
142
|
+
# Note: Flags must come before city names
|
|
143
|
+
# ✅ isobar -H Chicago
|
|
144
|
+
# ❌ isobar Chicago -H (treats "-H" as a city name)
|
|
133
145
|
isobar "San Francisco" --forecast
|
|
134
146
|
isobar -f Sydney
|
|
135
147
|
|
|
@@ -145,6 +157,42 @@ isobar home --clear # Clear home city
|
|
|
145
157
|
isobar # Uses home city if set (otherwise auto-detects)
|
|
146
158
|
```
|
|
147
159
|
|
|
160
|
+
## ⚙️ Configuration
|
|
161
|
+
|
|
162
|
+
Isobar supports configuration via environment variables for advanced use cases:
|
|
163
|
+
|
|
164
|
+
### API Endpoint Configuration
|
|
165
|
+
Customize API endpoints for different weather providers or testing:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
# Use custom weather APIs
|
|
169
|
+
export ISOBAR_GEOCODING_URL="https://custom-geocoding-api.example.com/v1/search"
|
|
170
|
+
export ISOBAR_WEATHER_URL="https://custom-weather-api.example.com/v1/forecast"
|
|
171
|
+
export ISOBAR_AQI_URL="https://custom-aqi-api.example.com/v1/air-quality"
|
|
172
|
+
|
|
173
|
+
# Run with custom endpoints
|
|
174
|
+
isobar "New York"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Timezone Support
|
|
178
|
+
For enhanced timezone accuracy (optional):
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# Install optional timezone support
|
|
182
|
+
pip install isobar-cli[timezone]
|
|
183
|
+
|
|
184
|
+
# Sunrise/sunset will now display in local timezone
|
|
185
|
+
isobar London
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Debug Mode
|
|
189
|
+
Enable debug logging to stderr:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
# View API errors and debugging information
|
|
193
|
+
isobar "Test City" 2> debug.log
|
|
194
|
+
```
|
|
195
|
+
|
|
148
196
|
## ⌨️ Shell Completion
|
|
149
197
|
|
|
150
198
|
Isobar supports tab-completion for city names. To enable it for a shell:
|
|
@@ -163,36 +211,53 @@ isobar --install-completion bash
|
|
|
163
211
|
|
|
164
212
|
## 🖥️ Example Output
|
|
165
213
|
|
|
214
|
+
### Industrial Aesthetic (v1.3.0+)
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
┌─ WEATHER OBSERVATORY ─┐
|
|
218
|
+
CHICAGO
|
|
219
|
+
┌─────┬──────────────────────┬────────────────┬────────────────┐
|
|
220
|
+
│ │ METRIC │ READING │ STATUS │
|
|
221
|
+
├─────┼──────────────────────┼────────────────┼────────────────┤
|
|
222
|
+
│ ☀️ │ CONDITIONS │ MAINLY CLEAR │ ◇ │
|
|
223
|
+
│ 🌡️ │ TEMPERATURE │ 75.2°F │ [███░░░░░░░] │
|
|
224
|
+
│ 🤔 │ REAL FEEL │ 78.5°F │ ▲ 3.3°F │
|
|
225
|
+
│ 💨 │ WIND SPEED │ 12.4 mph │ GENTLE │
|
|
226
|
+
│ 💧 │ HUMIDITY │ 65% │ [▓▓▓░░] │
|
|
227
|
+
│ 😷 │ AIR QUALITY │ 45 │ GOOD ◇ │
|
|
228
|
+
│ ☔ │ PRECIPITATION │ 30% (6h) │ [▓░░] │
|
|
229
|
+
│ │ FORECAST │ LIGHT RAIN LIKELY │ │
|
|
230
|
+
│ 🌅 │ SUNRISE │ 06:29 │ DAWN │
|
|
231
|
+
│ 🌇 │ SUNSET │ 17:37 │ DUSK │
|
|
232
|
+
│ ☀️ │ UV INDEX │ 6.5 │ HIGH ☀️☀️☀️ │
|
|
233
|
+
│ ⚡ │ GUST ALERT │ 25 mph │ ⚠️ SEVERE │
|
|
234
|
+
└─────┴──────────────────────┴────────────────┴────────────────┘
|
|
235
|
+
|
|
236
|
+
┌─ TREND ANALYSIS ─┐
|
|
237
|
+
↑ 5.2°F WARMER THAN YESTERDAY
|
|
238
|
+
└──────────────────┘
|
|
239
|
+
|
|
240
|
+
┌─ PREPARATION PROTOCOL ─┐
|
|
241
|
+
⚠️ HIGH PRIORITY
|
|
242
|
+
▶ Wind gusts up to 25 mph - secure loose items
|
|
243
|
+
▲ RECOMMENDED
|
|
244
|
+
▶ Light jacket recommended
|
|
245
|
+
▶ Sunscreen recommended (UV: High)
|
|
246
|
+
○ ADVISORY
|
|
247
|
+
▶ Sunglasses recommended for glare
|
|
248
|
+
└─────────────────────────┘
|
|
249
|
+
|
|
250
|
+
┌─ FORECAST PANEL ─┐
|
|
251
|
+
CHICAGO
|
|
252
|
+
┌──────┬──┬────────────────────┬───────┬───────┬───────┬────────┐
|
|
253
|
+
│ DAY │ │ CONDITIONS │ HIGH │ LOW │ RAIN% │ STATUS │
|
|
254
|
+
├──────┼──┼────────────────────┼───────┼───────┼───────┼────────┤
|
|
255
|
+
│ TODAY│☀️│ MAINLY CLEAR │ 78.7°F│ 63.9°F│ 30% │ ○ │
|
|
256
|
+
│ TUE │⛅│ PARTLY CLOUDY │ 82.4°F│ 65.4°F│ 20% │ ○ │
|
|
257
|
+
│ WED │🌦️│ LIGHT DRIZZLE │ 76.8°F│ 60.9°F│ 45% │ ● │
|
|
258
|
+
│ THU │☀️│ CLEAR SKY │ 80.3°F│ 63.5°F│ 10% │ ○ │
|
|
259
|
+
└──────┴──┴────────────────────┴───────┴───────┴───────┴────────┘
|
|
166
260
|
```
|
|
167
|
-
Chicago, Illinois Weather
|
|
168
|
-
☀️ Conditions: Mainly clear
|
|
169
|
-
🌡️ Temperature: 75.2°F
|
|
170
|
-
🤔 Real Feel: 78.5°F
|
|
171
|
-
💨 Wind Speed: 12.4 mph
|
|
172
|
-
💧 Humidity: 65%
|
|
173
|
-
☔ Precip Chance: 30% (6h) | Light rain likely
|
|
174
|
-
🌅 Sunrise: 6:29 AM
|
|
175
|
-
🌇 Sunset: 5:37 PM
|
|
176
|
-
☀️ UV Index: 6.5 (High)
|
|
177
|
-
💨 Wind Alert: ⚠️ Gusts up to 25 mph
|
|
178
|
-
😷 Air Quality: 45 (Good)
|
|
179
|
-
|
|
180
|
-
↑ 5.2°F warmer than yesterday
|
|
181
|
-
|
|
182
|
-
Preparation Guidance:
|
|
183
|
-
• 🧥 Light jacket
|
|
184
|
-
• 🧴 Sunscreen recommended
|
|
185
|
-
• 🕶️ Sunglasses recommended
|
|
186
|
-
|
|
187
|
-
7-Day Forecast — Chicago, Illinois
|
|
188
|
-
Day Conditions High Low Rain% UV
|
|
189
|
-
Today ☁️ Overcast 78.7°F 63.9°F 30% 7.2
|
|
190
|
-
Tue Apr 1 ⛅ Partly cloudy 82.4°F 65.4°F 20% 8.1
|
|
191
|
-
Wed Apr 2 🌦️ Light drizzle 76.8°F 60.9°F 45% 5.8
|
|
192
|
-
Thu Apr 3 ☀️ Clear sky 80.3°F 63.5°F 10% 8.5
|
|
193
|
-
Fri Apr 4 ☀️ Clear sky 83.6°F 67.1°F 5% 9.0
|
|
194
|
-
Sat Apr 5 ⛅ Partly cloudy 79.8°F 64.9°F 15% 7.8
|
|
195
|
-
Sun Apr 6 🌤️ Mainly clear 81.2°F 66.3°F 10% 8.3
|
|
196
261
|
```
|
|
197
262
|
|
|
198
263
|
## 🛠 Tech Stack
|
|
@@ -212,6 +277,15 @@ Preparation Guidance:
|
|
|
212
277
|
| `config.py` | Persistent home city configuration |
|
|
213
278
|
| Enhanced `logic.py` | Preparation guidance, UV monitoring, gust alerts |
|
|
214
279
|
| Updated `ui.py` | Contextual display of insights |
|
|
280
|
+
| **v1.2.0 Features** | **Security & Configuration** |
|
|
281
|
+
| Configurable API Endpoints | Environment variable support for custom APIs |
|
|
282
|
+
| Enhanced Error Handling | Specific exception catching with timeouts |
|
|
283
|
+
| Timezone Support | Optional `pytz` dependency for local time display |
|
|
284
|
+
| **v1.3.0 Features** | **Industrial Aesthetic** |
|
|
285
|
+
| Industrial UI Design | Retro-futuristic weather observatory dashboard |
|
|
286
|
+
| Visual Gauges | Temperature and humidity gauge visualizations |
|
|
287
|
+
| Severity Indicators | Weather condition severity classification |
|
|
288
|
+
| Enhanced Typography | Heavy borders, uppercase labels, status columns |
|
|
215
289
|
|
|
216
290
|
## 🔒 Security
|
|
217
291
|
|
|
@@ -235,6 +309,7 @@ All security scans are integrated into the CI/CD pipeline and run on every push,
|
|
|
235
309
|
✅ **Phase 5 Complete** — Testing & Reliability
|
|
236
310
|
✅ **Phase 6 Complete** — Distribution (PyPI, Homebrew)
|
|
237
311
|
✅ **Phase 7 Complete** — Intuition & Analysis (v1.1.0)
|
|
312
|
+
✅ **v1.2.0 Complete** — Security & Configuration Enhancements
|
|
238
313
|
Refer to [ROADMAP.md](ROADMAP.md) and [CHANGELOG.md](CHANGELOG.md) for details.
|
|
239
314
|
|
|
240
315
|
## 🤝 Contributing
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|

|
|
4
4
|

|
|
5
5
|
[](https://badge.fury.io/py/isobar-cli)
|
|
6
|
-

|
|
7
7
|

|
|
8
8
|

|
|
9
9
|

|
|
@@ -21,11 +21,13 @@ Most weather apps overwhelm with data. Isobar strips away everything except what
|
|
|
21
21
|
- **Essential over comprehensive** — Show Real Feel, not 47 data points.
|
|
22
22
|
- **Terminal-native** — Built for quick checks within a developer workflow.
|
|
23
23
|
- **Zero friction** — No API keys or configuration files required.
|
|
24
|
-
- **Information density** —
|
|
24
|
+
- **Information density** — Industrial dashboard UI for maximum readability.
|
|
25
25
|
- **Intentional features** — Each feature must answer: *"Does this help someone understand what it feels like outside?"*
|
|
26
|
+
- **Distinctive aesthetic** — Retro-futuristic industrial styling that avoids generic "AI slop"
|
|
26
27
|
|
|
27
28
|
## ✨ Features
|
|
28
29
|
|
|
30
|
+
- **Industrial Aesthetic** — Retro-futuristic weather observatory dashboard with brutalist styling 🏭
|
|
29
31
|
- **Auto-Location** — `isobar` detects the city automatically 🌍
|
|
30
32
|
- **Weather Condition Icons** — WMO-standard emoji + plain-English description (☀️ Clear sky, 🌨️ Moderate snow, ⛈️ Thunderstorm)
|
|
31
33
|
- **Real Feel** — Apparent temperature metrics (what it *actually* feels like).
|
|
@@ -42,12 +44,16 @@ Most weather apps overwhelm with data. Isobar strips away everything except what
|
|
|
42
44
|
- **Metric Support** — `--metric` or `-m` for Celsius, km/h, and mm.
|
|
43
45
|
- **No API Keys** — Free Open-Meteo and ip-api.com.
|
|
44
46
|
- **Zero Config** — Works instantly after installation.
|
|
47
|
+
- **Visual Gauges** — Temperature and humidity gauge visualizations 📊
|
|
48
|
+
- **Severity Indicators** — Weather condition severity icons (⚡, ▲, ●, ○, ◇)
|
|
49
|
+
- **Wind Categories** — Descriptive wind speed classifications (CALM, LIGHT, GENTLE, etc.)
|
|
50
|
+
- **Industrial Styling** — Heavy borders, uppercase labels, status columns
|
|
45
51
|
- **Phase 7: Intuition & Analysis** — Higher-level context and automated insights:
|
|
46
|
-
- **Preparation Guidance** — Clothing and gear suggestions
|
|
52
|
+
- **Preparation Guidance** — Clothing and gear suggestions with priority levels 🧥☂️🧴
|
|
47
53
|
- **Temporal Context** — Comparison with previous day conditions 📈
|
|
48
54
|
- **UV Index Monitoring** — Sun protection guidance with intensity levels ☀️
|
|
49
55
|
- **Wind Gust Alerts** — Highlighting of significant gust events 💨⚠️
|
|
50
|
-
- **Home City Persistence** — Set a default city with `isobar home "Your City"` 🏠
|
|
56
|
+
- **Home City Persistence** — Set a default city with `isobar home "Your City"` 🏠 *(Note: Due to a Typer limitation, this currently shows weather for "Home, Kansas" instead of setting home city. Manual config editing required.)*
|
|
51
57
|
|
|
52
58
|
## 🚀 Installation
|
|
53
59
|
|
|
@@ -91,12 +97,16 @@ isobar London Tokyo Paris # Multiple cities
|
|
|
91
97
|
isobar "New York" # Use quotes for multi-word cities
|
|
92
98
|
|
|
93
99
|
# Hourly outlook (next 12h)
|
|
94
|
-
isobar --hourly
|
|
95
|
-
isobar -H
|
|
100
|
+
isobar --hourly Chicago
|
|
101
|
+
isobar -H Chicago
|
|
96
102
|
|
|
97
103
|
# 7-day forecast
|
|
98
|
-
isobar --forecast
|
|
99
|
-
isobar -f
|
|
104
|
+
isobar --forecast Chicago
|
|
105
|
+
isobar -f Chicago
|
|
106
|
+
|
|
107
|
+
# Note: Flags must come before city names
|
|
108
|
+
# ✅ isobar -H Chicago
|
|
109
|
+
# ❌ isobar Chicago -H (treats "-H" as a city name)
|
|
100
110
|
isobar "San Francisco" --forecast
|
|
101
111
|
isobar -f Sydney
|
|
102
112
|
|
|
@@ -112,6 +122,42 @@ isobar home --clear # Clear home city
|
|
|
112
122
|
isobar # Uses home city if set (otherwise auto-detects)
|
|
113
123
|
```
|
|
114
124
|
|
|
125
|
+
## ⚙️ Configuration
|
|
126
|
+
|
|
127
|
+
Isobar supports configuration via environment variables for advanced use cases:
|
|
128
|
+
|
|
129
|
+
### API Endpoint Configuration
|
|
130
|
+
Customize API endpoints for different weather providers or testing:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# Use custom weather APIs
|
|
134
|
+
export ISOBAR_GEOCODING_URL="https://custom-geocoding-api.example.com/v1/search"
|
|
135
|
+
export ISOBAR_WEATHER_URL="https://custom-weather-api.example.com/v1/forecast"
|
|
136
|
+
export ISOBAR_AQI_URL="https://custom-aqi-api.example.com/v1/air-quality"
|
|
137
|
+
|
|
138
|
+
# Run with custom endpoints
|
|
139
|
+
isobar "New York"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Timezone Support
|
|
143
|
+
For enhanced timezone accuracy (optional):
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Install optional timezone support
|
|
147
|
+
pip install isobar-cli[timezone]
|
|
148
|
+
|
|
149
|
+
# Sunrise/sunset will now display in local timezone
|
|
150
|
+
isobar London
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Debug Mode
|
|
154
|
+
Enable debug logging to stderr:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# View API errors and debugging information
|
|
158
|
+
isobar "Test City" 2> debug.log
|
|
159
|
+
```
|
|
160
|
+
|
|
115
161
|
## ⌨️ Shell Completion
|
|
116
162
|
|
|
117
163
|
Isobar supports tab-completion for city names. To enable it for a shell:
|
|
@@ -130,36 +176,53 @@ isobar --install-completion bash
|
|
|
130
176
|
|
|
131
177
|
## 🖥️ Example Output
|
|
132
178
|
|
|
179
|
+
### Industrial Aesthetic (v1.3.0+)
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
┌─ WEATHER OBSERVATORY ─┐
|
|
183
|
+
CHICAGO
|
|
184
|
+
┌─────┬──────────────────────┬────────────────┬────────────────┐
|
|
185
|
+
│ │ METRIC │ READING │ STATUS │
|
|
186
|
+
├─────┼──────────────────────┼────────────────┼────────────────┤
|
|
187
|
+
│ ☀️ │ CONDITIONS │ MAINLY CLEAR │ ◇ │
|
|
188
|
+
│ 🌡️ │ TEMPERATURE │ 75.2°F │ [███░░░░░░░] │
|
|
189
|
+
│ 🤔 │ REAL FEEL │ 78.5°F │ ▲ 3.3°F │
|
|
190
|
+
│ 💨 │ WIND SPEED │ 12.4 mph │ GENTLE │
|
|
191
|
+
│ 💧 │ HUMIDITY │ 65% │ [▓▓▓░░] │
|
|
192
|
+
│ 😷 │ AIR QUALITY │ 45 │ GOOD ◇ │
|
|
193
|
+
│ ☔ │ PRECIPITATION │ 30% (6h) │ [▓░░] │
|
|
194
|
+
│ │ FORECAST │ LIGHT RAIN LIKELY │ │
|
|
195
|
+
│ 🌅 │ SUNRISE │ 06:29 │ DAWN │
|
|
196
|
+
│ 🌇 │ SUNSET │ 17:37 │ DUSK │
|
|
197
|
+
│ ☀️ │ UV INDEX │ 6.5 │ HIGH ☀️☀️☀️ │
|
|
198
|
+
│ ⚡ │ GUST ALERT │ 25 mph │ ⚠️ SEVERE │
|
|
199
|
+
└─────┴──────────────────────┴────────────────┴────────────────┘
|
|
200
|
+
|
|
201
|
+
┌─ TREND ANALYSIS ─┐
|
|
202
|
+
↑ 5.2°F WARMER THAN YESTERDAY
|
|
203
|
+
└──────────────────┘
|
|
204
|
+
|
|
205
|
+
┌─ PREPARATION PROTOCOL ─┐
|
|
206
|
+
⚠️ HIGH PRIORITY
|
|
207
|
+
▶ Wind gusts up to 25 mph - secure loose items
|
|
208
|
+
▲ RECOMMENDED
|
|
209
|
+
▶ Light jacket recommended
|
|
210
|
+
▶ Sunscreen recommended (UV: High)
|
|
211
|
+
○ ADVISORY
|
|
212
|
+
▶ Sunglasses recommended for glare
|
|
213
|
+
└─────────────────────────┘
|
|
214
|
+
|
|
215
|
+
┌─ FORECAST PANEL ─┐
|
|
216
|
+
CHICAGO
|
|
217
|
+
┌──────┬──┬────────────────────┬───────┬───────┬───────┬────────┐
|
|
218
|
+
│ DAY │ │ CONDITIONS │ HIGH │ LOW │ RAIN% │ STATUS │
|
|
219
|
+
├──────┼──┼────────────────────┼───────┼───────┼───────┼────────┤
|
|
220
|
+
│ TODAY│☀️│ MAINLY CLEAR │ 78.7°F│ 63.9°F│ 30% │ ○ │
|
|
221
|
+
│ TUE │⛅│ PARTLY CLOUDY │ 82.4°F│ 65.4°F│ 20% │ ○ │
|
|
222
|
+
│ WED │🌦️│ LIGHT DRIZZLE │ 76.8°F│ 60.9°F│ 45% │ ● │
|
|
223
|
+
│ THU │☀️│ CLEAR SKY │ 80.3°F│ 63.5°F│ 10% │ ○ │
|
|
224
|
+
└──────┴──┴────────────────────┴───────┴───────┴───────┴────────┘
|
|
133
225
|
```
|
|
134
|
-
Chicago, Illinois Weather
|
|
135
|
-
☀️ Conditions: Mainly clear
|
|
136
|
-
🌡️ Temperature: 75.2°F
|
|
137
|
-
🤔 Real Feel: 78.5°F
|
|
138
|
-
💨 Wind Speed: 12.4 mph
|
|
139
|
-
💧 Humidity: 65%
|
|
140
|
-
☔ Precip Chance: 30% (6h) | Light rain likely
|
|
141
|
-
🌅 Sunrise: 6:29 AM
|
|
142
|
-
🌇 Sunset: 5:37 PM
|
|
143
|
-
☀️ UV Index: 6.5 (High)
|
|
144
|
-
💨 Wind Alert: ⚠️ Gusts up to 25 mph
|
|
145
|
-
😷 Air Quality: 45 (Good)
|
|
146
|
-
|
|
147
|
-
↑ 5.2°F warmer than yesterday
|
|
148
|
-
|
|
149
|
-
Preparation Guidance:
|
|
150
|
-
• 🧥 Light jacket
|
|
151
|
-
• 🧴 Sunscreen recommended
|
|
152
|
-
• 🕶️ Sunglasses recommended
|
|
153
|
-
|
|
154
|
-
7-Day Forecast — Chicago, Illinois
|
|
155
|
-
Day Conditions High Low Rain% UV
|
|
156
|
-
Today ☁️ Overcast 78.7°F 63.9°F 30% 7.2
|
|
157
|
-
Tue Apr 1 ⛅ Partly cloudy 82.4°F 65.4°F 20% 8.1
|
|
158
|
-
Wed Apr 2 🌦️ Light drizzle 76.8°F 60.9°F 45% 5.8
|
|
159
|
-
Thu Apr 3 ☀️ Clear sky 80.3°F 63.5°F 10% 8.5
|
|
160
|
-
Fri Apr 4 ☀️ Clear sky 83.6°F 67.1°F 5% 9.0
|
|
161
|
-
Sat Apr 5 ⛅ Partly cloudy 79.8°F 64.9°F 15% 7.8
|
|
162
|
-
Sun Apr 6 🌤️ Mainly clear 81.2°F 66.3°F 10% 8.3
|
|
163
226
|
```
|
|
164
227
|
|
|
165
228
|
## 🛠 Tech Stack
|
|
@@ -179,6 +242,15 @@ Preparation Guidance:
|
|
|
179
242
|
| `config.py` | Persistent home city configuration |
|
|
180
243
|
| Enhanced `logic.py` | Preparation guidance, UV monitoring, gust alerts |
|
|
181
244
|
| Updated `ui.py` | Contextual display of insights |
|
|
245
|
+
| **v1.2.0 Features** | **Security & Configuration** |
|
|
246
|
+
| Configurable API Endpoints | Environment variable support for custom APIs |
|
|
247
|
+
| Enhanced Error Handling | Specific exception catching with timeouts |
|
|
248
|
+
| Timezone Support | Optional `pytz` dependency for local time display |
|
|
249
|
+
| **v1.3.0 Features** | **Industrial Aesthetic** |
|
|
250
|
+
| Industrial UI Design | Retro-futuristic weather observatory dashboard |
|
|
251
|
+
| Visual Gauges | Temperature and humidity gauge visualizations |
|
|
252
|
+
| Severity Indicators | Weather condition severity classification |
|
|
253
|
+
| Enhanced Typography | Heavy borders, uppercase labels, status columns |
|
|
182
254
|
|
|
183
255
|
## 🔒 Security
|
|
184
256
|
|
|
@@ -202,6 +274,7 @@ All security scans are integrated into the CI/CD pipeline and run on every push,
|
|
|
202
274
|
✅ **Phase 5 Complete** — Testing & Reliability
|
|
203
275
|
✅ **Phase 6 Complete** — Distribution (PyPI, Homebrew)
|
|
204
276
|
✅ **Phase 7 Complete** — Intuition & Analysis (v1.1.0)
|
|
277
|
+
✅ **v1.2.0 Complete** — Security & Configuration Enhancements
|
|
205
278
|
Refer to [ROADMAP.md](ROADMAP.md) and [CHANGELOG.md](CHANGELOG.md) for details.
|
|
206
279
|
|
|
207
280
|
## 🤝 Contributing
|
|
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "isobar-cli"
|
|
7
|
-
version = "1.
|
|
8
|
-
description = "A
|
|
7
|
+
version = "1.3.0"
|
|
8
|
+
description = "A terminal weather tool with industrial aesthetic, focusing on Real Feel and Windchill."
|
|
9
9
|
authors = [
|
|
10
10
|
{ name="Beau Bremer / KnowOneActual" },
|
|
11
11
|
]
|
|
@@ -27,9 +27,9 @@ dependencies = [
|
|
|
27
27
|
"rich>=13.0.0",
|
|
28
28
|
"requests>=2.31.0",
|
|
29
29
|
"typer>=0.9.0",
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
"timezonefinder>=6.0.0",
|
|
31
|
+
]
|
|
32
|
+
requires-python = ">=3.8"
|
|
33
33
|
|
|
34
34
|
[project.urls]
|
|
35
35
|
Homepage = "https://github.com/KnowOneActual/isobar-cli"
|
|
@@ -39,11 +39,14 @@ dependencies = [
|
|
|
39
39
|
|
|
40
40
|
[project.optional-dependencies]
|
|
41
41
|
|
|
42
|
-
test = [
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
]
|
|
42
|
+
test = [
|
|
43
|
+
"pytest>=7.0.0",
|
|
44
|
+
"requests-mock>=1.11.0",
|
|
45
|
+
"pytest-cov>=4.1.0",
|
|
46
|
+
]
|
|
47
|
+
timezone = [
|
|
48
|
+
"pytz>=2024.1",
|
|
49
|
+
]
|
|
47
50
|
|
|
48
51
|
[project.scripts]
|
|
49
52
|
isobar = "isobar_cli.main:app" # This allows you to type 'isobar' in the terminal to run it
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.3.0"
|
|
@@ -7,6 +7,7 @@ from typing import Optional
|
|
|
7
7
|
import requests
|
|
8
8
|
from timezonefinder import TimezoneFinder
|
|
9
9
|
|
|
10
|
+
from .config import get_aqi_url, get_geocoding_url, get_weather_url
|
|
10
11
|
from .logic import format_time
|
|
11
12
|
from .models import ForecastDay, HourlyForecast, UnitSystem, WeatherData, WeatherUnits
|
|
12
13
|
|
|
@@ -15,22 +16,39 @@ CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
class GeocodingClient:
|
|
18
|
-
|
|
19
|
+
@classmethod
|
|
20
|
+
def get_base_url(cls) -> str:
|
|
21
|
+
"""Get geocoding API URL from configuration."""
|
|
22
|
+
return get_geocoding_url()
|
|
19
23
|
|
|
20
24
|
@classmethod
|
|
21
25
|
def search(cls, city: str, count: int = 1) -> list[dict]:
|
|
22
26
|
try:
|
|
23
27
|
response = requests.get(
|
|
24
|
-
f"{cls.
|
|
28
|
+
f"{cls.get_base_url()}?name={city}&count={count}&format=json",
|
|
29
|
+
timeout=10,
|
|
25
30
|
)
|
|
26
31
|
response.raise_for_status()
|
|
27
32
|
return response.json().get("results", [])
|
|
28
|
-
except
|
|
33
|
+
except requests.exceptions.RequestException as e:
|
|
34
|
+
# Log error for debugging but don't crash
|
|
35
|
+
import sys
|
|
36
|
+
|
|
37
|
+
print(f"Geocoding error for '{city}': {e}", file=sys.stderr)
|
|
38
|
+
return []
|
|
39
|
+
except Exception as e:
|
|
40
|
+
# Catch-all for unexpected errors
|
|
41
|
+
import sys
|
|
42
|
+
|
|
43
|
+
print(f"Unexpected geocoding error for '{city}': {e}", file=sys.stderr)
|
|
29
44
|
return []
|
|
30
45
|
|
|
31
46
|
|
|
32
47
|
class WeatherClient:
|
|
33
|
-
|
|
48
|
+
@classmethod
|
|
49
|
+
def get_base_url(cls) -> str:
|
|
50
|
+
"""Get weather API URL from configuration."""
|
|
51
|
+
return get_weather_url()
|
|
34
52
|
|
|
35
53
|
def __init__(self, lat: float, lon: float, timezone: str, metric: bool = False):
|
|
36
54
|
self.lat = lat
|
|
@@ -59,23 +77,37 @@ class WeatherClient:
|
|
|
59
77
|
"forecast_days": 7,
|
|
60
78
|
}
|
|
61
79
|
|
|
62
|
-
response = requests.get(self.
|
|
80
|
+
response = requests.get(self.get_base_url(), params=params, timeout=15)
|
|
63
81
|
response.raise_for_status()
|
|
64
82
|
return response.json()
|
|
65
83
|
|
|
66
84
|
|
|
67
85
|
class AirQualityClient:
|
|
68
|
-
|
|
86
|
+
@classmethod
|
|
87
|
+
def get_base_url(cls) -> str:
|
|
88
|
+
"""Get air quality API URL from configuration."""
|
|
89
|
+
return get_aqi_url()
|
|
69
90
|
|
|
70
91
|
@classmethod
|
|
71
92
|
def get_aqi(cls, lat: float, lon: float) -> Optional[int]:
|
|
72
93
|
try:
|
|
73
94
|
response = requests.get(
|
|
74
|
-
f"{cls.
|
|
95
|
+
f"{cls.get_base_url()}?latitude={lat}&longitude={lon}¤t=us_aqi",
|
|
96
|
+
timeout=10,
|
|
75
97
|
)
|
|
76
98
|
response.raise_for_status()
|
|
77
99
|
return response.json().get("current", {}).get("us_aqi")
|
|
78
|
-
except
|
|
100
|
+
except requests.exceptions.RequestException as e:
|
|
101
|
+
# Log error for debugging but don't crash
|
|
102
|
+
import sys
|
|
103
|
+
|
|
104
|
+
print(f"AQI error for ({lat},{lon}): {e}", file=sys.stderr)
|
|
105
|
+
return None
|
|
106
|
+
except Exception as e:
|
|
107
|
+
# Catch-all for unexpected errors
|
|
108
|
+
import sys
|
|
109
|
+
|
|
110
|
+
print(f"Unexpected AQI error for ({lat},{lon}): {e}", file=sys.stderr)
|
|
79
111
|
return None
|
|
80
112
|
|
|
81
113
|
|
|
@@ -207,8 +239,8 @@ def get_weather_data(city: str, metric: bool = False) -> Optional[WeatherData]:
|
|
|
207
239
|
precip_prob=round(avg_precip_prob),
|
|
208
240
|
rainfall=next_6h_rain,
|
|
209
241
|
snowfall=next_6h_snow,
|
|
210
|
-
sunrise=format_time(daily["sunrise"][0]),
|
|
211
|
-
sunset=format_time(daily["sunset"][0]),
|
|
242
|
+
sunrise=format_time(daily["sunrise"][0], timezone),
|
|
243
|
+
sunset=format_time(daily["sunset"][0], timezone),
|
|
212
244
|
forecast=forecast,
|
|
213
245
|
hourly=hourly_forecast,
|
|
214
246
|
units=weather_client.units,
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
"""Configuration module for Isobar CLI persistent settings."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
import os
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
from typing import Optional
|
|
6
7
|
|
|
7
8
|
CONFIG_DIR = Path.home() / ".config" / "isobar"
|
|
8
9
|
CONFIG_FILE = CONFIG_DIR / "config.json"
|
|
9
10
|
|
|
11
|
+
# Default API endpoints (can be overridden by environment variables)
|
|
12
|
+
DEFAULT_GEOCODING_URL = "https://geocoding-api.open-meteo.com/v1/search"
|
|
13
|
+
DEFAULT_WEATHER_URL = "https://api.open-meteo.com/v1/forecast"
|
|
14
|
+
DEFAULT_AQI_URL = "https://air-quality-api.open-meteo.com/v1/air-quality"
|
|
15
|
+
|
|
10
16
|
|
|
11
17
|
def ensure_config_dir() -> None:
|
|
12
18
|
"""Create config directory if it doesn't exist."""
|
|
@@ -72,3 +78,18 @@ def clear_home_city() -> None:
|
|
|
72
78
|
def get_config_path() -> Path:
|
|
73
79
|
"""Get the path to the config file (for debugging/info)."""
|
|
74
80
|
return CONFIG_FILE
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def get_geocoding_url() -> str:
|
|
84
|
+
"""Get geocoding API URL from environment or default."""
|
|
85
|
+
return os.environ.get("ISOBAR_GEOCODING_URL", DEFAULT_GEOCODING_URL)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def get_weather_url() -> str:
|
|
89
|
+
"""Get weather API URL from environment or default."""
|
|
90
|
+
return os.environ.get("ISOBAR_WEATHER_URL", DEFAULT_WEATHER_URL)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def get_aqi_url() -> str:
|
|
94
|
+
"""Get air quality API URL from environment or default."""
|
|
95
|
+
return os.environ.get("ISOBAR_AQI_URL", DEFAULT_AQI_URL)
|