weathr 1.0.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.
Files changed (45) hide show
  1. weathr-1.0.0/PKG-INFO +202 -0
  2. weathr-1.0.0/README.md +172 -0
  3. weathr-1.0.0/pyproject.toml +74 -0
  4. weathr-1.0.0/pyproject.toml.orig +66 -0
  5. weathr-1.0.0/src/weather/__init__.py +1 -0
  6. weathr-1.0.0/src/weather/__main__.py +4 -0
  7. weathr-1.0.0/src/weather/app.py +74 -0
  8. weathr-1.0.0/src/weather/cache.py +139 -0
  9. weathr-1.0.0/src/weather/cli.py +157 -0
  10. weathr-1.0.0/src/weather/config.py +77 -0
  11. weathr-1.0.0/src/weather/exceptions.py +14 -0
  12. weathr-1.0.0/src/weather/logging.py +26 -0
  13. weathr-1.0.0/src/weather/models.py +84 -0
  14. weathr-1.0.0/src/weather/onboarding.py +83 -0
  15. weathr-1.0.0/src/weather/providers/__init__.py +3 -0
  16. weathr-1.0.0/src/weather/providers/aqi/__init__.py +5 -0
  17. weathr-1.0.0/src/weather/providers/aqi/base.py +9 -0
  18. weathr-1.0.0/src/weather/providers/aqi/openmeteo.py +55 -0
  19. weathr-1.0.0/src/weather/providers/aqi/openweather.py +52 -0
  20. weathr-1.0.0/src/weather/providers/base.py +32 -0
  21. weathr-1.0.0/src/weather/providers/geocoding/__init__.py +5 -0
  22. weathr-1.0.0/src/weather/providers/geocoding/base.py +9 -0
  23. weathr-1.0.0/src/weather/providers/geocoding/nominatim.py +47 -0
  24. weathr-1.0.0/src/weather/providers/geocoding/openmeteo.py +59 -0
  25. weathr-1.0.0/src/weather/providers/geolocation/__init__.py +7 -0
  26. weathr-1.0.0/src/weather/providers/geolocation/base.py +9 -0
  27. weathr-1.0.0/src/weather/providers/geolocation/countryis.py +43 -0
  28. weathr-1.0.0/src/weather/providers/geolocation/freeipapi.py +36 -0
  29. weathr-1.0.0/src/weather/providers/geolocation/ipinfo.py +43 -0
  30. weathr-1.0.0/src/weather/providers/geolocation/ipwhois.py +38 -0
  31. weathr-1.0.0/src/weather/providers/weather/__init__.py +4 -0
  32. weathr-1.0.0/src/weather/providers/weather/base.py +11 -0
  33. weathr-1.0.0/src/weather/providers/weather/openmeteo.py +134 -0
  34. weathr-1.0.0/src/weather/services/__init__.py +6 -0
  35. weathr-1.0.0/src/weather/services/aqi.py +42 -0
  36. weathr-1.0.0/src/weather/services/geocoding.py +35 -0
  37. weathr-1.0.0/src/weather/services/geolocation.py +37 -0
  38. weathr-1.0.0/src/weather/services/weather.py +43 -0
  39. weathr-1.0.0/src/weather/ui/conditions.py +281 -0
  40. weathr-1.0.0/src/weather/ui/presentation.py +114 -0
  41. weathr-1.0.0/src/weather/ui/render.py +66 -0
  42. weathr-1.0.0/src/weather/ui/themes/__init__.py +3 -0
  43. weathr-1.0.0/src/weather/ui/themes/base.py +17 -0
  44. weathr-1.0.0/src/weather/ui/themes/default.py +71 -0
  45. weathr-1.0.0/src/weather/utils.py +56 -0
weathr-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,202 @@
1
+ Metadata-Version: 2.4
2
+ Name: weathr
3
+ Version: 1.0.0
4
+ Summary: A fast terminal weather client
5
+ Keywords: weather,cli,terminal,air-quality
6
+ Author: Harshit Pawar
7
+ Author-email: Harshit Pawar <hpchess64@gmail.com>
8
+ License-Expression: MIT
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: End Users/Desktop
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Topic :: Utilities
18
+ Requires-Dist: httpx>=0.28.1
19
+ Requires-Dist: msgspec>=0.21.1
20
+ Requires-Dist: platformdirs>=4.11.2
21
+ Requires-Dist: rich>=15.0.0
22
+ Requires-Dist: tomli-w>=1.2.0
23
+ Requires-Dist: typer>=0.27.1
24
+ Requires-Python: >=3.12
25
+ Project-URL: Homepage, https://github.com/harshitpawar64/weather
26
+ Project-URL: Repository, https://github.com/harshitpawar64/weather
27
+ Project-URL: Issues, https://github.com/harshitpawar64/weather/issues
28
+ Project-URL: Changelog, https://github.com/harshitpawar64/weather/blob/main/CHANGELOG.md
29
+ Description-Content-Type: text/markdown
30
+
31
+ # weather ⛅
32
+
33
+ [![CI](https://github.com/harshitpawar64/weather/actions/workflows/ci.yml/badge.svg?event=push)](https://github.com/harshitpawar64/weather/actions/workflows/ci.yml)
34
+ [![python](https://img.shields.io/badge/Python-3.12_|_3.13_|_3.14-35c555.svg?logo=python&labelColor=31373c&logoColor=skyblue)](https://www.python.org/)
35
+
36
+ [![uv](https://img.shields.io/badge/uv-black.svg?logo=uv)](https://docs.astral.sh/uv/)
37
+ [![ruff](https://img.shields.io/badge/ruff-black.svg?logo=ruff)](https://docs.astral.sh/ruff/)
38
+ [![ty](https://img.shields.io/badge/ty-black.svg?logo=ty)](https://docs.astral.sh/ty/)
39
+ [![pytest](https://img.shields.io/badge/pytest-black.svg?logo=pytest)](https://docs.pytest.org/)
40
+
41
+ A fast, beautiful terminal weather client with multi-provider fallbacks, AQI metrics, and smart caching.
42
+
43
+ ![weather demo](assets/demo.gif)
44
+
45
+ ---
46
+
47
+ ## Install
48
+
49
+ ```bash
50
+ # With uv (recommended)
51
+ uv tool install weathr
52
+
53
+ # With pipx
54
+ pipx install weathr
55
+ ```
56
+
57
+ ---
58
+
59
+ ## First-Run Onboarding
60
+
61
+ On your first launch (or at any time by running `weather setup`), `weather` launches an interactive onboarding flow. It detects your location using IP geolocation, asks to confirm your preferred city, and lets you pick your default unit system.
62
+
63
+ ![onboarding demo](assets/onboarding.gif)
64
+
65
+ Your preferences are saved locally (`config.toml`). After setup, simply running `weather` displays your local forecast instantly.
66
+
67
+ ---
68
+
69
+ ## Usage
70
+
71
+ ```bash
72
+ # Check current weather + 6-day forecast for your saved location
73
+ weather
74
+
75
+ # Check weather for any city, landmark, address or postal codes
76
+ weather -l Tokyo
77
+ weather -l "Berlin, Germany"
78
+ weather -l 94103
79
+
80
+ # Specify total days of forecast (1 to 16 days)
81
+ weather -d 3
82
+ weather -l London -d 10
83
+
84
+ # Override unit system
85
+ weather --metric # °C, km/h, mm
86
+ weather --imperial # °F, mph, in
87
+
88
+ # Output JSON for scripting
89
+ weather --json
90
+ weather -l "Reykjavik" --json | jq .weather.current.temperature
91
+
92
+ # Verbose logging
93
+ weather -l "Berlin" -v
94
+ ```
95
+
96
+ ---
97
+
98
+ ## CLI Options & Subcommands
99
+
100
+ ### Options
101
+
102
+ | **Flag** | **Short** | **Default** | **Description** |
103
+ |--------------|:---------:|:--------------:|-------------------------------------------------|
104
+ | `--location` | `-l` | Saved location | City, landmark, address or postal codes. |
105
+ | `--days` | `-d` | `7` | Total days of forecast, including today. (1-16) |
106
+ | `--metric` | | | Use metric units (°C, km/h, mm) |
107
+ | `--imperial` | | | Use imperial units (°F, mph, in) |
108
+ | `--json` | | `False` | Output result in JSON format. |
109
+ | `--theme` | `-t` | `default` | Theme to use for rendering output. |
110
+ | `--verbose` | `-v` | `False` | Enable verbose debug logging. |
111
+ | `--version` | | | Show version and exit. |
112
+
113
+ ### Default File Paths
114
+
115
+ | **OS** | **Config Path (`weather config path`)** | **Cache Path (`weather cache path`)** |
116
+ |---------|-----------------------------------------------------|-------------------------------------------|
117
+ | Linux | `~/.config/weather/config.toml` | `~/.cache/weather/cache.bin` |
118
+ | macOS | `~/Library/Application Support/weather/config.toml` | `~/Library/Caches/weather/cache.bin` |
119
+ | Windows | `%LOCALAPPDATA%\weather\config.toml` | `%LOCALAPPDATA%\weather\Cache\cache.bin` |
120
+
121
+ ### Cache Management
122
+
123
+ `weather` maintains a fast binary msgpack cache to eliminate redundant network calls:
124
+
125
+ ```bash
126
+ # View cache file location
127
+ weather cache path
128
+
129
+ # Remove expired entries (>1 week old)
130
+ weather cache prune
131
+
132
+ # Wipe the cache entirely
133
+ weather cache clear
134
+ ```
135
+
136
+ ### Configuration Management
137
+
138
+ ```bash
139
+ # Run interactive setup at any time
140
+ weather setup
141
+
142
+ # Display config file path
143
+ weather config path
144
+ ```
145
+
146
+ Config file example (`config.toml`):
147
+
148
+ ```toml
149
+ unit_system = "metric"
150
+ theme = "default"
151
+
152
+ [location]
153
+ latitude = 37.774929
154
+ longitude = -122.419416
155
+ display_name = "San Francisco, California, United States"
156
+ ```
157
+
158
+ ---
159
+
160
+ ## Optional: OpenWeather API Key
161
+
162
+ `weather` works out of the box with **zero configuration** using Open-Meteo. If you want [OpenWeather](https://openweathermap.org/) as an automatic secondary fallback for Air Quality (AQI) data, [obtain a free API key](https://openweathermap.org/api) and set the `OPENWEATHER_API_KEY` environment variable:
163
+
164
+ ### Linux & macOS (Bash / Zsh)
165
+
166
+ ```bash
167
+ echo 'export OPENWEATHER_API_KEY="your_api_key_here"' >> ~/.bashrc # or ~/.zshrc
168
+ source ~/.bashrc # or source ~/.zshrc
169
+ ```
170
+
171
+ ### Windows (Powershell)
172
+
173
+ ```powershell
174
+ [System.Environment]::SetEnvironmentVariable('OPENWEATHER_API_KEY', 'your_api_key_here', 'User')
175
+ ```
176
+
177
+ ---
178
+
179
+ ## Attributions & Data Sources
180
+
181
+ This project is powered by several free and open data providers:
182
+
183
+ - **Weather Forecast**:
184
+ - [Open-Meteo](https://open-meteo.com/en/docs/) (Weather Forecast API) under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
185
+
186
+ - **Air Quality**:
187
+ - [Open-Meteo](https://open-meteo.com/en/docs/air-quality-api/) (Air Quality API) under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
188
+ - [OpenWeather](https://openweathermap.org/) (Air Pollution API).
189
+ - **Geocoding**:
190
+ - [Nominatim](https://nominatim.org/) (Data © [OpenStreetMap contributors](https://www.openstreetmap.org/copyright)).
191
+ - [Open-Meteo](https://open-meteo.com/en/docs/geocoding-api/) (Geocoding API) under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
192
+ - **IP Geolocation**:
193
+ - [IPWhoIs](https://ipwhois.io/)
194
+ - [FreeIPAPI](https://freeipapi.com/)
195
+ - [CountryIs](https://country.is/)
196
+ - [IPInfo](https://ipinfo.io/)
197
+
198
+ ---
199
+
200
+ ## License
201
+
202
+ This project is licensed under the [MIT License](LICENSE).
weathr-1.0.0/README.md ADDED
@@ -0,0 +1,172 @@
1
+ # weather ⛅
2
+
3
+ [![CI](https://github.com/harshitpawar64/weather/actions/workflows/ci.yml/badge.svg?event=push)](https://github.com/harshitpawar64/weather/actions/workflows/ci.yml)
4
+ [![python](https://img.shields.io/badge/Python-3.12_|_3.13_|_3.14-35c555.svg?logo=python&labelColor=31373c&logoColor=skyblue)](https://www.python.org/)
5
+
6
+ [![uv](https://img.shields.io/badge/uv-black.svg?logo=uv)](https://docs.astral.sh/uv/)
7
+ [![ruff](https://img.shields.io/badge/ruff-black.svg?logo=ruff)](https://docs.astral.sh/ruff/)
8
+ [![ty](https://img.shields.io/badge/ty-black.svg?logo=ty)](https://docs.astral.sh/ty/)
9
+ [![pytest](https://img.shields.io/badge/pytest-black.svg?logo=pytest)](https://docs.pytest.org/)
10
+
11
+ A fast, beautiful terminal weather client with multi-provider fallbacks, AQI metrics, and smart caching.
12
+
13
+ ![weather demo](assets/demo.gif)
14
+
15
+ ---
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ # With uv (recommended)
21
+ uv tool install weathr
22
+
23
+ # With pipx
24
+ pipx install weathr
25
+ ```
26
+
27
+ ---
28
+
29
+ ## First-Run Onboarding
30
+
31
+ On your first launch (or at any time by running `weather setup`), `weather` launches an interactive onboarding flow. It detects your location using IP geolocation, asks to confirm your preferred city, and lets you pick your default unit system.
32
+
33
+ ![onboarding demo](assets/onboarding.gif)
34
+
35
+ Your preferences are saved locally (`config.toml`). After setup, simply running `weather` displays your local forecast instantly.
36
+
37
+ ---
38
+
39
+ ## Usage
40
+
41
+ ```bash
42
+ # Check current weather + 6-day forecast for your saved location
43
+ weather
44
+
45
+ # Check weather for any city, landmark, address or postal codes
46
+ weather -l Tokyo
47
+ weather -l "Berlin, Germany"
48
+ weather -l 94103
49
+
50
+ # Specify total days of forecast (1 to 16 days)
51
+ weather -d 3
52
+ weather -l London -d 10
53
+
54
+ # Override unit system
55
+ weather --metric # °C, km/h, mm
56
+ weather --imperial # °F, mph, in
57
+
58
+ # Output JSON for scripting
59
+ weather --json
60
+ weather -l "Reykjavik" --json | jq .weather.current.temperature
61
+
62
+ # Verbose logging
63
+ weather -l "Berlin" -v
64
+ ```
65
+
66
+ ---
67
+
68
+ ## CLI Options & Subcommands
69
+
70
+ ### Options
71
+
72
+ | **Flag** | **Short** | **Default** | **Description** |
73
+ |--------------|:---------:|:--------------:|-------------------------------------------------|
74
+ | `--location` | `-l` | Saved location | City, landmark, address or postal codes. |
75
+ | `--days` | `-d` | `7` | Total days of forecast, including today. (1-16) |
76
+ | `--metric` | | | Use metric units (°C, km/h, mm) |
77
+ | `--imperial` | | | Use imperial units (°F, mph, in) |
78
+ | `--json` | | `False` | Output result in JSON format. |
79
+ | `--theme` | `-t` | `default` | Theme to use for rendering output. |
80
+ | `--verbose` | `-v` | `False` | Enable verbose debug logging. |
81
+ | `--version` | | | Show version and exit. |
82
+
83
+ ### Default File Paths
84
+
85
+ | **OS** | **Config Path (`weather config path`)** | **Cache Path (`weather cache path`)** |
86
+ |---------|-----------------------------------------------------|-------------------------------------------|
87
+ | Linux | `~/.config/weather/config.toml` | `~/.cache/weather/cache.bin` |
88
+ | macOS | `~/Library/Application Support/weather/config.toml` | `~/Library/Caches/weather/cache.bin` |
89
+ | Windows | `%LOCALAPPDATA%\weather\config.toml` | `%LOCALAPPDATA%\weather\Cache\cache.bin` |
90
+
91
+ ### Cache Management
92
+
93
+ `weather` maintains a fast binary msgpack cache to eliminate redundant network calls:
94
+
95
+ ```bash
96
+ # View cache file location
97
+ weather cache path
98
+
99
+ # Remove expired entries (>1 week old)
100
+ weather cache prune
101
+
102
+ # Wipe the cache entirely
103
+ weather cache clear
104
+ ```
105
+
106
+ ### Configuration Management
107
+
108
+ ```bash
109
+ # Run interactive setup at any time
110
+ weather setup
111
+
112
+ # Display config file path
113
+ weather config path
114
+ ```
115
+
116
+ Config file example (`config.toml`):
117
+
118
+ ```toml
119
+ unit_system = "metric"
120
+ theme = "default"
121
+
122
+ [location]
123
+ latitude = 37.774929
124
+ longitude = -122.419416
125
+ display_name = "San Francisco, California, United States"
126
+ ```
127
+
128
+ ---
129
+
130
+ ## Optional: OpenWeather API Key
131
+
132
+ `weather` works out of the box with **zero configuration** using Open-Meteo. If you want [OpenWeather](https://openweathermap.org/) as an automatic secondary fallback for Air Quality (AQI) data, [obtain a free API key](https://openweathermap.org/api) and set the `OPENWEATHER_API_KEY` environment variable:
133
+
134
+ ### Linux & macOS (Bash / Zsh)
135
+
136
+ ```bash
137
+ echo 'export OPENWEATHER_API_KEY="your_api_key_here"' >> ~/.bashrc # or ~/.zshrc
138
+ source ~/.bashrc # or source ~/.zshrc
139
+ ```
140
+
141
+ ### Windows (Powershell)
142
+
143
+ ```powershell
144
+ [System.Environment]::SetEnvironmentVariable('OPENWEATHER_API_KEY', 'your_api_key_here', 'User')
145
+ ```
146
+
147
+ ---
148
+
149
+ ## Attributions & Data Sources
150
+
151
+ This project is powered by several free and open data providers:
152
+
153
+ - **Weather Forecast**:
154
+ - [Open-Meteo](https://open-meteo.com/en/docs/) (Weather Forecast API) under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
155
+
156
+ - **Air Quality**:
157
+ - [Open-Meteo](https://open-meteo.com/en/docs/air-quality-api/) (Air Quality API) under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
158
+ - [OpenWeather](https://openweathermap.org/) (Air Pollution API).
159
+ - **Geocoding**:
160
+ - [Nominatim](https://nominatim.org/) (Data © [OpenStreetMap contributors](https://www.openstreetmap.org/copyright)).
161
+ - [Open-Meteo](https://open-meteo.com/en/docs/geocoding-api/) (Geocoding API) under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
162
+ - **IP Geolocation**:
163
+ - [IPWhoIs](https://ipwhois.io/)
164
+ - [FreeIPAPI](https://freeipapi.com/)
165
+ - [CountryIs](https://country.is/)
166
+ - [IPInfo](https://ipinfo.io/)
167
+
168
+ ---
169
+
170
+ ## License
171
+
172
+ This project is licensed under the [MIT License](LICENSE).
@@ -0,0 +1,74 @@
1
+ [project]
2
+ name = "weathr"
3
+ version = "1.0.0"
4
+ description = "A fast terminal weather client"
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ requires-python = ">=3.12"
8
+ dependencies = [
9
+ "httpx>=0.28.1",
10
+ "msgspec>=0.21.1",
11
+ "platformdirs>=4.11.2",
12
+ "rich>=15.0.0",
13
+ "tomli-w>=1.2.0",
14
+ "typer>=0.27.1",
15
+ ]
16
+ keywords = [
17
+ "weather",
18
+ "cli",
19
+ "terminal",
20
+ "air-quality",
21
+ ]
22
+ classifiers = [
23
+ "Development Status :: 5 - Production/Stable",
24
+ "Environment :: Console",
25
+ "Intended Audience :: End Users/Desktop",
26
+ "Operating System :: OS Independent",
27
+ "Programming Language :: Python :: 3",
28
+ "Programming Language :: Python :: 3.12",
29
+ "Programming Language :: Python :: 3.13",
30
+ "Programming Language :: Python :: 3.14",
31
+ "Topic :: Utilities",
32
+ ]
33
+
34
+ [[project.authors]]
35
+ name = "Harshit Pawar"
36
+ email = "hpchess64@gmail.com"
37
+
38
+ [project.urls]
39
+ Homepage = "https://github.com/harshitpawar64/weather"
40
+ Repository = "https://github.com/harshitpawar64/weather"
41
+ Issues = "https://github.com/harshitpawar64/weather/issues"
42
+ Changelog = "https://github.com/harshitpawar64/weather/blob/main/CHANGELOG.md"
43
+
44
+ [project.scripts]
45
+ weather = "weather.cli:app"
46
+
47
+ [build-system]
48
+ requires = ["uv_build>=0.12.3,<0.13.0"]
49
+ build-backend = "uv_build"
50
+
51
+ [dependency-groups]
52
+ dev = [
53
+ "pytest>=9.1.1",
54
+ "pytest-asyncio>=1.4.0",
55
+ "pytest-cov>=7.1.0",
56
+ "ruff>=0.16.2",
57
+ "ty>=0.0.71",
58
+ ]
59
+
60
+ [tool.uv.build-backend]
61
+ module-name = "weather"
62
+
63
+ [tool.ruff.format]
64
+ skip-magic-trailing-comma = true
65
+
66
+ [tool.ruff.lint]
67
+ extend-select = ["I"]
68
+
69
+ [tool.ruff.lint.isort]
70
+ split-on-trailing-comma = false
71
+
72
+ [tool.pytest.ini_options]
73
+ asyncio_mode = "auto"
74
+ addopts = "--cov=weather --cov-report=term-missing --cov-branch -v"
@@ -0,0 +1,66 @@
1
+ [project]
2
+ name = "weathr"
3
+ version = "1.0.0"
4
+ description = "A fast terminal weather client"
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ authors = [{ name = "Harshit Pawar", email = "hpchess64@gmail.com" }]
8
+ requires-python = ">=3.12"
9
+ dependencies = [
10
+ "httpx>=0.28.1",
11
+ "msgspec>=0.21.1",
12
+ "platformdirs>=4.11.2",
13
+ "rich>=15.0.0",
14
+ "tomli-w>=1.2.0",
15
+ "typer>=0.27.1",
16
+ ]
17
+ keywords = ["weather", "cli", "terminal", "air-quality"]
18
+ classifiers = [
19
+ "Development Status :: 5 - Production/Stable",
20
+ "Environment :: Console",
21
+ "Intended Audience :: End Users/Desktop",
22
+ "Operating System :: OS Independent",
23
+ "Programming Language :: Python :: 3",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ "Programming Language :: Python :: 3.14",
27
+ "Topic :: Utilities",
28
+ ]
29
+
30
+ [project.urls]
31
+ Homepage = "https://github.com/harshitpawar64/weather"
32
+ Repository = "https://github.com/harshitpawar64/weather"
33
+ Issues = "https://github.com/harshitpawar64/weather/issues"
34
+ Changelog = "https://github.com/harshitpawar64/weather/blob/main/CHANGELOG.md"
35
+
36
+ [project.scripts]
37
+ weather = "weather.cli:app"
38
+
39
+ [build-system]
40
+ requires = ["uv_build>=0.12.3,<0.13.0"]
41
+ build-backend = "uv_build"
42
+
43
+ [dependency-groups]
44
+ dev = [
45
+ "pytest>=9.1.1",
46
+ "pytest-asyncio>=1.4.0",
47
+ "pytest-cov>=7.1.0",
48
+ "ruff>=0.16.2",
49
+ "ty>=0.0.71",
50
+ ]
51
+
52
+ [tool.uv.build-backend]
53
+ module-name = "weather"
54
+
55
+ [tool.ruff.format]
56
+ skip-magic-trailing-comma = true
57
+
58
+ [tool.ruff.lint]
59
+ extend-select = ["I"]
60
+
61
+ [tool.ruff.lint.isort]
62
+ split-on-trailing-comma = false
63
+
64
+ [tool.pytest.ini_options]
65
+ asyncio_mode = "auto"
66
+ addopts = "--cov=weather --cov-report=term-missing --cov-branch -v"
@@ -0,0 +1 @@
1
+ __version__ = "1.0.0" # x-release-please-version
@@ -0,0 +1,4 @@
1
+ from weather.cli import app
2
+
3
+ if __name__ == "__main__":
4
+ app()
@@ -0,0 +1,74 @@
1
+ import asyncio
2
+
3
+ import httpx
4
+ import msgspec
5
+
6
+ from weather.cache import Cache
7
+ from weather.config import Config
8
+ from weather.models import Theme, UnitSystem, WeatherResponse
9
+ from weather.onboarding import onboarding
10
+ from weather.services import (
11
+ AQIService,
12
+ GeocodingService,
13
+ GeolocationService,
14
+ WeatherService,
15
+ )
16
+ from weather.ui.render import render_weather
17
+
18
+ cache = Cache()
19
+ config = Config()
20
+
21
+
22
+ async def run(
23
+ query: str | None,
24
+ unit_system: UnitSystem,
25
+ theme: Theme,
26
+ days: int,
27
+ json_output: bool,
28
+ ) -> None:
29
+ async with httpx.AsyncClient(timeout=10.0) as client:
30
+ if query:
31
+ geocoder = GeocodingService(client, cache)
32
+ location = await geocoder.geocode(query)
33
+ elif config.location:
34
+ location = config.location
35
+ else:
36
+ location, unit_system = await onboarding(
37
+ GeolocationService(client), GeocodingService(client, cache)
38
+ )
39
+
40
+ config.save(location, unit_system)
41
+
42
+ weather_service = WeatherService(client, cache)
43
+ aqi_service = AQIService(client, cache)
44
+
45
+ weather, aqi = await asyncio.gather(
46
+ weather_service.get_weather(location, unit_system),
47
+ aqi_service.get_aqi(location),
48
+ return_exceptions=True,
49
+ )
50
+
51
+ if isinstance(weather, BaseException):
52
+ raise weather
53
+
54
+ if isinstance(aqi, BaseException):
55
+ aqi = None
56
+
57
+ cache.save(location, weather, aqi, query)
58
+
59
+ response = WeatherResponse(location, weather, aqi)
60
+
61
+ if json_output:
62
+ print(msgspec.json.encode(response).decode())
63
+
64
+ return
65
+
66
+ render_weather(response, theme, days)
67
+
68
+
69
+ async def run_setup() -> None:
70
+ async with httpx.AsyncClient(timeout=10.0) as client:
71
+ location, unit_system = await onboarding(
72
+ GeolocationService(client), GeocodingService(client, cache)
73
+ )
74
+ config.save(location, unit_system)