isobar-cli 1.3.3__tar.gz → 1.3.5__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.3.3/src/isobar_cli.egg-info → isobar_cli-1.3.5}/PKG-INFO +6 -49
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/README.md +5 -48
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/pyproject.toml +1 -1
- isobar_cli-1.3.5/src/isobar_cli/__init__.py +1 -0
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/src/isobar_cli/api.py +13 -13
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/src/isobar_cli/main.py +18 -10
- {isobar_cli-1.3.3 → isobar_cli-1.3.5/src/isobar_cli.egg-info}/PKG-INFO +6 -49
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/tests/test_isobar_extra.py +34 -2
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/tests/test_main.py +16 -0
- isobar_cli-1.3.3/src/isobar_cli/__init__.py +0 -1
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/LICENSE +0 -0
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/setup.cfg +0 -0
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/src/isobar_cli/config.py +0 -0
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/src/isobar_cli/location.py +0 -0
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/src/isobar_cli/logic.py +0 -0
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/src/isobar_cli/models.py +0 -0
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/src/isobar_cli/ui.py +0 -0
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/src/isobar_cli.egg-info/SOURCES.txt +0 -0
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/src/isobar_cli.egg-info/dependency_links.txt +0 -0
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/src/isobar_cli.egg-info/entry_points.txt +0 -0
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/src/isobar_cli.egg-info/requires.txt +0 -0
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/src/isobar_cli.egg-info/top_level.txt +0 -0
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/tests/test_api.py +0 -0
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/tests/test_location.py +0 -0
- {isobar_cli-1.3.3 → isobar_cli-1.3.5}/tests/test_ui.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: isobar-cli
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.5
|
|
4
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
|
|
@@ -44,13 +44,15 @@ Dynamic: license-file
|
|
|
44
44
|

|
|
45
45
|

|
|
46
46
|
|
|
47
|
+
**I'm currently working on improving the layout. Thanks so much for your patience with any little hiccups that might come up along the way!**
|
|
48
|
+
|
|
47
49
|
A terminal weather tool designed to provide a fast, clean sense of what the weather **feels like** outside; right now and for the week ahead. Built with Python and Rich.
|
|
48
50
|
|
|
49
51
|
## Philosophy
|
|
50
52
|
|
|
51
53
|
Isobar CLI answers a simple question: **"What does it feel like outside right now, and do I need a jacket?"**
|
|
52
54
|
|
|
53
|
-
Most weather apps
|
|
55
|
+
Most weather apps are overwhelmed with data. Isobar strips away everything except what matters when deciding how to prepare for the day.
|
|
54
56
|
|
|
55
57
|
### Design Principles
|
|
56
58
|
- **Essential over comprehensive** — Show Real Feel, not 47 data points.
|
|
@@ -214,52 +216,8 @@ isobar --install-completion bash
|
|
|
214
216
|
### Industrial Aesthetic (v1.3.0+)
|
|
215
217
|
|
|
216
218
|
```
|
|
217
|
-
|
|
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
|
-
└──────┴──┴────────────────────┴───────┴───────┴───────┴────────┘
|
|
260
|
-
```
|
|
219
|
+
Coming soon..
|
|
261
220
|
```
|
|
262
|
-
|
|
263
221
|
## 🛠 Tech Stack
|
|
264
222
|
|
|
265
223
|
| Tool | Purpose |
|
|
@@ -273,7 +231,7 @@ CHICAGO
|
|
|
273
231
|
| [requests-mock](https://requests-mock.readthedocs.io/) | API testing |
|
|
274
232
|
| [Ruff](https://docs.astral.sh/ruff/) | Linting and formatting |
|
|
275
233
|
| [pip-audit](https://github.com/pypa/pip-audit) | Dependency security scanning |
|
|
276
|
-
|
|
|
234
|
+
| New improvemets | **Intuition & Analysis** |
|
|
277
235
|
| `config.py` | Persistent home city configuration |
|
|
278
236
|
| Enhanced `logic.py` | Preparation guidance, UV monitoring, gust alerts |
|
|
279
237
|
| Updated `ui.py` | Contextual display of insights |
|
|
@@ -281,7 +239,6 @@ CHICAGO
|
|
|
281
239
|
| Configurable API Endpoints | Environment variable support for custom APIs |
|
|
282
240
|
| Enhanced Error Handling | Specific exception catching with timeouts |
|
|
283
241
|
| Timezone Support | Optional `pytz` dependency for local time display |
|
|
284
|
-
| **v1.3.0 Features** | **Industrial Aesthetic** |
|
|
285
242
|
| Industrial UI Design | Retro-futuristic weather observatory dashboard |
|
|
286
243
|
| Visual Gauges | Temperature and humidity gauge visualizations |
|
|
287
244
|
| Severity Indicators | Weather condition severity classification |
|
|
@@ -9,13 +9,15 @@
|
|
|
9
9
|

|
|
10
10
|

|
|
11
11
|
|
|
12
|
+
**I'm currently working on improving the layout. Thanks so much for your patience with any little hiccups that might come up along the way!**
|
|
13
|
+
|
|
12
14
|
A terminal weather tool designed to provide a fast, clean sense of what the weather **feels like** outside; right now and for the week ahead. Built with Python and Rich.
|
|
13
15
|
|
|
14
16
|
## Philosophy
|
|
15
17
|
|
|
16
18
|
Isobar CLI answers a simple question: **"What does it feel like outside right now, and do I need a jacket?"**
|
|
17
19
|
|
|
18
|
-
Most weather apps
|
|
20
|
+
Most weather apps are overwhelmed with data. Isobar strips away everything except what matters when deciding how to prepare for the day.
|
|
19
21
|
|
|
20
22
|
### Design Principles
|
|
21
23
|
- **Essential over comprehensive** — Show Real Feel, not 47 data points.
|
|
@@ -179,52 +181,8 @@ isobar --install-completion bash
|
|
|
179
181
|
### Industrial Aesthetic (v1.3.0+)
|
|
180
182
|
|
|
181
183
|
```
|
|
182
|
-
|
|
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
|
-
└──────┴──┴────────────────────┴───────┴───────┴───────┴────────┘
|
|
225
|
-
```
|
|
184
|
+
Coming soon..
|
|
226
185
|
```
|
|
227
|
-
|
|
228
186
|
## 🛠 Tech Stack
|
|
229
187
|
|
|
230
188
|
| Tool | Purpose |
|
|
@@ -238,7 +196,7 @@ CHICAGO
|
|
|
238
196
|
| [requests-mock](https://requests-mock.readthedocs.io/) | API testing |
|
|
239
197
|
| [Ruff](https://docs.astral.sh/ruff/) | Linting and formatting |
|
|
240
198
|
| [pip-audit](https://github.com/pypa/pip-audit) | Dependency security scanning |
|
|
241
|
-
|
|
|
199
|
+
| New improvemets | **Intuition & Analysis** |
|
|
242
200
|
| `config.py` | Persistent home city configuration |
|
|
243
201
|
| Enhanced `logic.py` | Preparation guidance, UV monitoring, gust alerts |
|
|
244
202
|
| Updated `ui.py` | Contextual display of insights |
|
|
@@ -246,7 +204,6 @@ CHICAGO
|
|
|
246
204
|
| Configurable API Endpoints | Environment variable support for custom APIs |
|
|
247
205
|
| Enhanced Error Handling | Specific exception catching with timeouts |
|
|
248
206
|
| Timezone Support | Optional `pytz` dependency for local time display |
|
|
249
|
-
| **v1.3.0 Features** | **Industrial Aesthetic** |
|
|
250
207
|
| Industrial UI Design | Retro-futuristic weather observatory dashboard |
|
|
251
208
|
| Visual Gauges | Temperature and humidity gauge visualizations |
|
|
252
209
|
| Severity Indicators | Weather condition severity classification |
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "isobar-cli"
|
|
7
|
-
version = "1.3.
|
|
7
|
+
version = "1.3.5"
|
|
8
8
|
description = "A terminal weather tool with industrial aesthetic, focusing on Real Feel and Windchill."
|
|
9
9
|
authors = [
|
|
10
10
|
{ name="Beau Bremer / KnowOneActual" },
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.3.5"
|
|
@@ -15,6 +15,12 @@ CACHE_DIR = Path.home() / ".cache" / "isobar"
|
|
|
15
15
|
CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
class WeatherAPIError(Exception):
|
|
19
|
+
"""Raised when the weather or geocoding API request fails."""
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
18
24
|
class GeocodingClient:
|
|
19
25
|
@classmethod
|
|
20
26
|
def get_base_url(cls) -> str:
|
|
@@ -31,17 +37,9 @@ class GeocodingClient:
|
|
|
31
37
|
response.raise_for_status()
|
|
32
38
|
return response.json().get("results", [])
|
|
33
39
|
except requests.exceptions.RequestException as e:
|
|
34
|
-
|
|
35
|
-
import sys
|
|
36
|
-
|
|
37
|
-
print(f"Geocoding error for '{city}': {e}", file=sys.stderr)
|
|
38
|
-
return []
|
|
40
|
+
raise WeatherAPIError(f"Geocoding error for '{city}': {e}") from e
|
|
39
41
|
except Exception as e:
|
|
40
|
-
|
|
41
|
-
import sys
|
|
42
|
-
|
|
43
|
-
print(f"Unexpected geocoding error for '{city}': {e}", file=sys.stderr)
|
|
44
|
-
return []
|
|
42
|
+
raise WeatherAPIError(f"Unexpected geocoding error for '{city}': {e}") from e
|
|
45
43
|
|
|
46
44
|
|
|
47
45
|
class WeatherClient:
|
|
@@ -128,7 +126,10 @@ def get_cached_cities() -> list[str]:
|
|
|
128
126
|
|
|
129
127
|
def get_city_suggestions(city: str) -> list[str]:
|
|
130
128
|
"""Fetches a list of likely city name matches for a given input string."""
|
|
131
|
-
|
|
129
|
+
try:
|
|
130
|
+
results = GeocodingClient.search(city, count=5)
|
|
131
|
+
except WeatherAPIError:
|
|
132
|
+
return []
|
|
132
133
|
suggestions = []
|
|
133
134
|
for loc in results:
|
|
134
135
|
region = loc.get("admin1", loc.get("country", ""))
|
|
@@ -175,8 +176,7 @@ def get_weather_data(city: str, metric: bool = False) -> Optional[WeatherData]:
|
|
|
175
176
|
api_data = weather_client.fetch()
|
|
176
177
|
aqi_value = AirQualityClient.get_aqi(lat, lon)
|
|
177
178
|
except requests.RequestException as e:
|
|
178
|
-
|
|
179
|
-
return None
|
|
179
|
+
raise WeatherAPIError(f"Error fetching weather: {e}") from e
|
|
180
180
|
|
|
181
181
|
current = api_data["current"]
|
|
182
182
|
hourly = api_data["hourly"]
|
|
@@ -3,7 +3,12 @@ from typing import Annotated, Optional
|
|
|
3
3
|
import typer
|
|
4
4
|
from rich.console import Console
|
|
5
5
|
|
|
6
|
-
from isobar_cli.api import
|
|
6
|
+
from isobar_cli.api import (
|
|
7
|
+
WeatherAPIError,
|
|
8
|
+
get_cached_cities,
|
|
9
|
+
get_city_suggestions,
|
|
10
|
+
get_weather_data,
|
|
11
|
+
)
|
|
7
12
|
from isobar_cli.config import clear_home_city, get_home_city, set_home_city
|
|
8
13
|
from isobar_cli.location import get_auto_location
|
|
9
14
|
from isobar_cli.ui import (
|
|
@@ -161,15 +166,18 @@ def _run_weather_logic(
|
|
|
161
166
|
results = []
|
|
162
167
|
for city_name in cities_to_fetch:
|
|
163
168
|
full_city = city_name.replace("_", " ")
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
169
|
+
try:
|
|
170
|
+
weather = get_weather_data(full_city, metric=metric)
|
|
171
|
+
if weather:
|
|
172
|
+
results.append(weather)
|
|
173
|
+
else:
|
|
174
|
+
console.print(f"[bold red]❌ '{full_city}' not found.[/bold red]")
|
|
175
|
+
suggestions = get_city_suggestions(full_city)
|
|
176
|
+
if suggestions:
|
|
177
|
+
suggest_str = ", ".join(suggestions[:3])
|
|
178
|
+
console.print(f"[dim]Did you mean: {suggest_str}?[/dim]")
|
|
179
|
+
except WeatherAPIError as e:
|
|
180
|
+
console.print(f"[bold red]❌ {e}[/bold red]")
|
|
173
181
|
|
|
174
182
|
if not results:
|
|
175
183
|
raise typer.Exit(code=1)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: isobar-cli
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.5
|
|
4
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
|
|
@@ -44,13 +44,15 @@ Dynamic: license-file
|
|
|
44
44
|

|
|
45
45
|

|
|
46
46
|
|
|
47
|
+
**I'm currently working on improving the layout. Thanks so much for your patience with any little hiccups that might come up along the way!**
|
|
48
|
+
|
|
47
49
|
A terminal weather tool designed to provide a fast, clean sense of what the weather **feels like** outside; right now and for the week ahead. Built with Python and Rich.
|
|
48
50
|
|
|
49
51
|
## Philosophy
|
|
50
52
|
|
|
51
53
|
Isobar CLI answers a simple question: **"What does it feel like outside right now, and do I need a jacket?"**
|
|
52
54
|
|
|
53
|
-
Most weather apps
|
|
55
|
+
Most weather apps are overwhelmed with data. Isobar strips away everything except what matters when deciding how to prepare for the day.
|
|
54
56
|
|
|
55
57
|
### Design Principles
|
|
56
58
|
- **Essential over comprehensive** — Show Real Feel, not 47 data points.
|
|
@@ -214,52 +216,8 @@ isobar --install-completion bash
|
|
|
214
216
|
### Industrial Aesthetic (v1.3.0+)
|
|
215
217
|
|
|
216
218
|
```
|
|
217
|
-
|
|
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
|
-
└──────┴──┴────────────────────┴───────┴───────┴───────┴────────┘
|
|
260
|
-
```
|
|
219
|
+
Coming soon..
|
|
261
220
|
```
|
|
262
|
-
|
|
263
221
|
## 🛠 Tech Stack
|
|
264
222
|
|
|
265
223
|
| Tool | Purpose |
|
|
@@ -273,7 +231,7 @@ CHICAGO
|
|
|
273
231
|
| [requests-mock](https://requests-mock.readthedocs.io/) | API testing |
|
|
274
232
|
| [Ruff](https://docs.astral.sh/ruff/) | Linting and formatting |
|
|
275
233
|
| [pip-audit](https://github.com/pypa/pip-audit) | Dependency security scanning |
|
|
276
|
-
|
|
|
234
|
+
| New improvemets | **Intuition & Analysis** |
|
|
277
235
|
| `config.py` | Persistent home city configuration |
|
|
278
236
|
| Enhanced `logic.py` | Preparation guidance, UV monitoring, gust alerts |
|
|
279
237
|
| Updated `ui.py` | Contextual display of insights |
|
|
@@ -281,7 +239,6 @@ CHICAGO
|
|
|
281
239
|
| Configurable API Endpoints | Environment variable support for custom APIs |
|
|
282
240
|
| Enhanced Error Handling | Specific exception catching with timeouts |
|
|
283
241
|
| Timezone Support | Optional `pytz` dependency for local time display |
|
|
284
|
-
| **v1.3.0 Features** | **Industrial Aesthetic** |
|
|
285
242
|
| Industrial UI Design | Retro-futuristic weather observatory dashboard |
|
|
286
243
|
| Visual Gauges | Temperature and humidity gauge visualizations |
|
|
287
244
|
| Severity Indicators | Weather condition severity classification |
|
|
@@ -198,14 +198,46 @@ def test_get_weather_data_hourly_index_error(requests_mock):
|
|
|
198
198
|
|
|
199
199
|
|
|
200
200
|
def test_get_weather_data_request_exception(requests_mock):
|
|
201
|
+
import pytest
|
|
201
202
|
import requests
|
|
202
203
|
|
|
204
|
+
from isobar_cli.api import WeatherAPIError
|
|
205
|
+
|
|
203
206
|
requests_mock.get(
|
|
204
207
|
"https://geocoding-api.open-meteo.com/v1/search",
|
|
205
208
|
exc=requests.exceptions.RequestException("Connection error"),
|
|
206
209
|
)
|
|
207
|
-
|
|
208
|
-
|
|
210
|
+
with pytest.raises(WeatherAPIError):
|
|
211
|
+
get_weather_data("FailCity")
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def test_get_weather_data_forecast_request_exception(requests_mock):
|
|
215
|
+
import pytest
|
|
216
|
+
import requests
|
|
217
|
+
|
|
218
|
+
from isobar_cli.api import WeatherAPIError
|
|
219
|
+
|
|
220
|
+
geo_data = {
|
|
221
|
+
"results": [
|
|
222
|
+
{
|
|
223
|
+
"name": "Chicago",
|
|
224
|
+
"latitude": 41.85,
|
|
225
|
+
"longitude": -87.65,
|
|
226
|
+
"admin1": "Illinois",
|
|
227
|
+
"country": "United States",
|
|
228
|
+
}
|
|
229
|
+
]
|
|
230
|
+
}
|
|
231
|
+
requests_mock.get(
|
|
232
|
+
"https://geocoding-api.open-meteo.com/v1/search",
|
|
233
|
+
json=geo_data,
|
|
234
|
+
)
|
|
235
|
+
requests_mock.get(
|
|
236
|
+
"https://api.open-meteo.com/v1/forecast",
|
|
237
|
+
exc=requests.exceptions.RequestException("Weather connection error"),
|
|
238
|
+
)
|
|
239
|
+
with pytest.raises(WeatherAPIError):
|
|
240
|
+
get_weather_data("Chicago")
|
|
209
241
|
|
|
210
242
|
|
|
211
243
|
# --- Main Tests ---
|
|
@@ -109,3 +109,19 @@ def test_main_not_found_with_suggestions(mock_api):
|
|
|
109
109
|
assert result.exit_code == 1
|
|
110
110
|
assert "'Unknown' not found" in result.output
|
|
111
111
|
assert "Did you mean: Suggested City?" in result.output
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def test_main_weather_api_error(monkeypatch):
|
|
115
|
+
from isobar_cli.api import WeatherAPIError
|
|
116
|
+
|
|
117
|
+
def mock_get_weather_data(city, metric=False):
|
|
118
|
+
raise WeatherAPIError("Mocked API connection timeout")
|
|
119
|
+
|
|
120
|
+
monkeypatch.setattr("isobar_cli.main.get_weather_data", mock_get_weather_data)
|
|
121
|
+
|
|
122
|
+
result = runner.invoke(
|
|
123
|
+
app, ["Chicago"], color=False, env={"TERM": "dumb", "NO_COLOR": "1"}
|
|
124
|
+
)
|
|
125
|
+
assert result.exit_code == 1
|
|
126
|
+
assert "Mocked API connection timeout" in result.output
|
|
127
|
+
assert "not found" not in result.output
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "1.3.3"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|