pygeofetch 0.1.1__py3-none-any.whl
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.
- pygeofetch/__init__.py +39 -0
- pygeofetch/cli/__init__.py +1 -0
- pygeofetch/cli/auth_commands.py +257 -0
- pygeofetch/cli/config_commands.py +143 -0
- pygeofetch/cli/download_commands.py +272 -0
- pygeofetch/cli/main.py +770 -0
- pygeofetch/cli/search_commands.py +249 -0
- pygeofetch/config/__init__.py +11 -0
- pygeofetch/config/defaults.yaml +86 -0
- pygeofetch/config/settings.py +235 -0
- pygeofetch/core/__init__.py +18 -0
- pygeofetch/core/authenticator.py +428 -0
- pygeofetch/core/cache_manager.py +288 -0
- pygeofetch/core/downloader.py +354 -0
- pygeofetch/core/engine.py +312 -0
- pygeofetch/core/scheduler.py +473 -0
- pygeofetch/core/searcher.py +341 -0
- pygeofetch/models/__init__.py +44 -0
- pygeofetch/models/download_task.py +282 -0
- pygeofetch/models/satellite_data.py +395 -0
- pygeofetch/models/search_query.py +329 -0
- pygeofetch/models/user_auth.py +123 -0
- pygeofetch/providers/__init__.py +192 -0
- pygeofetch/providers/airbus_oneatlas.py +150 -0
- pygeofetch/providers/alaska_satellite_facility.py +150 -0
- pygeofetch/providers/aws_earth.py +267 -0
- pygeofetch/providers/base.py +306 -0
- pygeofetch/providers/copernicus.py +487 -0
- pygeofetch/providers/digitalglobe.py +150 -0
- pygeofetch/providers/earth_explorer_additional.py +150 -0
- pygeofetch/providers/element84.py +230 -0
- pygeofetch/providers/esa_scihub.py +150 -0
- pygeofetch/providers/geoserver_generic.py +150 -0
- pygeofetch/providers/google_earth_engine.py +150 -0
- pygeofetch/providers/inpe_cbers.py +150 -0
- pygeofetch/providers/isro_bhuvan.py +150 -0
- pygeofetch/providers/jaxa_earth.py +150 -0
- pygeofetch/providers/maxar_gbdx.py +150 -0
- pygeofetch/providers/nasa_earthdata.py +190 -0
- pygeofetch/providers/nasa_earthdata_cloud.py +345 -0
- pygeofetch/providers/noaa_big_data.py +150 -0
- pygeofetch/providers/opentopography.py +108 -0
- pygeofetch/providers/planet.py +369 -0
- pygeofetch/providers/planetary_computer.py +273 -0
- pygeofetch/providers/sentinel_hub.py +173 -0
- pygeofetch/providers/terrabotics.py +278 -0
- pygeofetch/providers/usgs.py +469 -0
- pygeofetch/utils/__init__.py +50 -0
- pygeofetch/utils/file_utils.py +275 -0
- pygeofetch/utils/geo_utils.py +240 -0
- pygeofetch/utils/logging_setup.py +107 -0
- pygeofetch/utils/retry_handler.py +225 -0
- pygeofetch/utils/validators.py +155 -0
- pygeofetch-0.1.1.dist-info/METADATA +720 -0
- pygeofetch-0.1.1.dist-info/RECORD +59 -0
- pygeofetch-0.1.1.dist-info/WHEEL +5 -0
- pygeofetch-0.1.1.dist-info/entry_points.txt +2 -0
- pygeofetch-0.1.1.dist-info/licenses/LICENSE +21 -0
- pygeofetch-0.1.1.dist-info/top_level.txt +1 -0
pygeofetch/__init__.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""
|
|
2
|
+
pygeofetch v1.0.0 — Universal Satellite Data Pipeline.
|
|
3
|
+
|
|
4
|
+
Unified access to 22+ satellite data providers with a consistent
|
|
5
|
+
Python API and CLI. Supports authentication management, federated search,
|
|
6
|
+
parallel downloads, pipeline orchestration, and post-processing.
|
|
7
|
+
|
|
8
|
+
Quick Start::
|
|
9
|
+
|
|
10
|
+
from pygeofetch import pygeofetch
|
|
11
|
+
|
|
12
|
+
sb = pygeofetch()
|
|
13
|
+
sb.add_credentials("usgs", username="user", password="pass")
|
|
14
|
+
|
|
15
|
+
results = sb.search(
|
|
16
|
+
providers=["usgs", "copernicus", "planetary_computer"],
|
|
17
|
+
bbox=(-74.1, 40.6, -73.7, 40.9),
|
|
18
|
+
start_date="2024-01-01",
|
|
19
|
+
cloud_cover_max=20,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
sb.download(results[:5], output="./data/", parallel=4)
|
|
23
|
+
|
|
24
|
+
CLI::
|
|
25
|
+
|
|
26
|
+
pygeofetch auth add usgs --username user --password pass
|
|
27
|
+
pygeofetch search run --bbox "-74,40,-73,41" --providers copernicus
|
|
28
|
+
pygeofetch download run --from-search results.geojson --output ./data/
|
|
29
|
+
pygeofetch status
|
|
30
|
+
pygeofetch doctor
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
__version__ = "1.0.0"
|
|
34
|
+
__author__ = "pygeofetch Contributors"
|
|
35
|
+
__license__ = "MIT"
|
|
36
|
+
|
|
37
|
+
from pygeofetch.core.engine import pygeofetch # noqa: F401
|
|
38
|
+
|
|
39
|
+
__all__ = ["pygeofetch", "__version__"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""pygeofetch CLI package."""
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Authentication CLI commands for pygeofetch.
|
|
3
|
+
|
|
4
|
+
Provides the ``pygeofetch auth`` command group for managing provider
|
|
5
|
+
credentials: adding, listing, removing, testing, and exporting them.
|
|
6
|
+
|
|
7
|
+
Usage::
|
|
8
|
+
|
|
9
|
+
pygeofetch auth add usgs --username user --password pass
|
|
10
|
+
pygeofetch auth add planet --api-key PL_KEY
|
|
11
|
+
pygeofetch auth login copernicus # interactive prompt
|
|
12
|
+
pygeofetch auth list
|
|
13
|
+
pygeofetch auth test usgs
|
|
14
|
+
pygeofetch auth remove planet
|
|
15
|
+
pygeofetch auth export --output creds_backup.json
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import json
|
|
21
|
+
import sys
|
|
22
|
+
|
|
23
|
+
import click
|
|
24
|
+
from rich.console import Console
|
|
25
|
+
from rich.table import Table
|
|
26
|
+
|
|
27
|
+
console = Console()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@click.group()
|
|
31
|
+
def auth() -> None:
|
|
32
|
+
"""Manage provider authentication credentials."""
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@auth.command(name="add")
|
|
36
|
+
@click.argument("provider")
|
|
37
|
+
@click.option("--username", "-u", default=None, help="Username or email.")
|
|
38
|
+
@click.option("--password", "-p", default=None, help="Password (prompted if omitted).")
|
|
39
|
+
@click.option("--api-key", "-k", default=None, help="API key (alternative to username/password).")
|
|
40
|
+
@click.option("--client-id", default=None, help="OAuth2 client ID.")
|
|
41
|
+
@click.option("--client-secret", default=None, help="OAuth2 client secret.")
|
|
42
|
+
@click.option("--token", default=None, help="Bearer token.")
|
|
43
|
+
@click.option(
|
|
44
|
+
"--store",
|
|
45
|
+
default="keyring",
|
|
46
|
+
type=click.Choice(["keyring", "file"]),
|
|
47
|
+
show_default=True,
|
|
48
|
+
help="Credential storage backend.",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
def auth_add(
|
|
52
|
+
provider: str,
|
|
53
|
+
username: str | None,
|
|
54
|
+
password: str | None,
|
|
55
|
+
api_key: str | None,
|
|
56
|
+
client_id: str | None,
|
|
57
|
+
client_secret: str | None,
|
|
58
|
+
token: str | None,
|
|
59
|
+
store: str,
|
|
60
|
+
) -> None:
|
|
61
|
+
"""
|
|
62
|
+
Add credentials for PROVIDER.
|
|
63
|
+
|
|
64
|
+
\b
|
|
65
|
+
Examples:
|
|
66
|
+
pygeofetch auth add usgs --username samuelyamforo --password USGS@sak@2001server
|
|
67
|
+
pygeofetch auth add planet --api-key PL_KEY
|
|
68
|
+
pygeofetch auth add copernicus --username me@example.com
|
|
69
|
+
"""
|
|
70
|
+
from pygeofetch.core.authenticator import AuthManager
|
|
71
|
+
|
|
72
|
+
creds: dict = {}
|
|
73
|
+
|
|
74
|
+
if api_key:
|
|
75
|
+
creds["api_key"] = api_key
|
|
76
|
+
if client_id:
|
|
77
|
+
creds["client_id"] = client_id
|
|
78
|
+
if client_secret:
|
|
79
|
+
creds["client_secret"] = client_secret
|
|
80
|
+
if token:
|
|
81
|
+
creds["token"] = token
|
|
82
|
+
|
|
83
|
+
if not creds and not username:
|
|
84
|
+
username = click.prompt(f"Username for {provider}")
|
|
85
|
+
|
|
86
|
+
if username:
|
|
87
|
+
creds["username"] = username
|
|
88
|
+
if not password and not api_key:
|
|
89
|
+
password = click.prompt(f"Password for {provider}", hide_input=True)
|
|
90
|
+
if password:
|
|
91
|
+
creds["password"] = password
|
|
92
|
+
|
|
93
|
+
if not creds:
|
|
94
|
+
console.print("[red]No credentials provided.[/]")
|
|
95
|
+
sys.exit(1)
|
|
96
|
+
|
|
97
|
+
mgr = AuthManager(storage_backend='file')
|
|
98
|
+
mgr.add_credentials(provider, **creds)
|
|
99
|
+
console.print(f"[green]Credentials for [bold]{provider}[/] saved.[/]")
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@auth.command(name="login")
|
|
103
|
+
@click.argument("provider")
|
|
104
|
+
def auth_login(provider: str) -> None:
|
|
105
|
+
"""
|
|
106
|
+
Interactive login for PROVIDER (prompts for all required fields).
|
|
107
|
+
|
|
108
|
+
\b
|
|
109
|
+
Example:
|
|
110
|
+
pygeofetch auth login copernicus
|
|
111
|
+
"""
|
|
112
|
+
from pygeofetch.core.authenticator import AuthManager
|
|
113
|
+
from pygeofetch.providers import get_provider
|
|
114
|
+
|
|
115
|
+
prov = get_provider(provider)
|
|
116
|
+
caps = prov.get_capabilities()
|
|
117
|
+
|
|
118
|
+
console.print(f"\n[bold]Logging in to {caps.name}[/]\n")
|
|
119
|
+
|
|
120
|
+
creds: dict = {}
|
|
121
|
+
|
|
122
|
+
# Determine what to prompt based on auth type
|
|
123
|
+
auth_type = caps.auth_type if hasattr(caps, "auth_type") else "username_password"
|
|
124
|
+
|
|
125
|
+
if auth_type in ("api_key",):
|
|
126
|
+
creds["api_key"] = click.prompt("API Key", hide_input=True)
|
|
127
|
+
elif auth_type in ("oauth2_client",):
|
|
128
|
+
creds["client_id"] = click.prompt("Client ID")
|
|
129
|
+
creds["client_secret"] = click.prompt("Client Secret", hide_input=True)
|
|
130
|
+
else:
|
|
131
|
+
creds["username"] = click.prompt("Username")
|
|
132
|
+
creds["password"] = click.prompt("Password", hide_input=True)
|
|
133
|
+
|
|
134
|
+
mgr = AuthManager(storage_backend='file')
|
|
135
|
+
mgr.add_credentials(provider, creds)
|
|
136
|
+
|
|
137
|
+
console.print(f"\n[green]Credentials for [bold]{provider}[/] saved.[/]")
|
|
138
|
+
|
|
139
|
+
# Optionally verify
|
|
140
|
+
if click.confirm("Verify credentials now?", default=True):
|
|
141
|
+
try:
|
|
142
|
+
session = mgr.authenticate(provider)
|
|
143
|
+
console.print(f"[green]Authentication successful![/] Session expires: {session.expires_at}")
|
|
144
|
+
except Exception as exc:
|
|
145
|
+
console.print(f"[red]Authentication failed: {exc}[/]")
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@auth.command(name="list")
|
|
149
|
+
@click.option("--json", "as_json", is_flag=True, help="Output as JSON.")
|
|
150
|
+
def auth_list(as_json: bool) -> None:
|
|
151
|
+
"""List all stored provider credentials."""
|
|
152
|
+
from pygeofetch.core.authenticator import AuthManager
|
|
153
|
+
|
|
154
|
+
mgr = AuthManager(storage_backend='file')
|
|
155
|
+
entries = mgr.list()
|
|
156
|
+
|
|
157
|
+
if as_json:
|
|
158
|
+
click.echo(json.dumps(entries, indent=2, default=str))
|
|
159
|
+
return
|
|
160
|
+
|
|
161
|
+
if not entries:
|
|
162
|
+
console.print("[dim]No credentials stored.[/]")
|
|
163
|
+
return
|
|
164
|
+
|
|
165
|
+
table = Table(title="Stored Credentials", header_style="bold blue")
|
|
166
|
+
table.add_column("Provider", style="cyan")
|
|
167
|
+
table.add_column("Has Username", justify="center")
|
|
168
|
+
table.add_column("Has API Key", justify="center")
|
|
169
|
+
table.add_column("Has Token", justify="center")
|
|
170
|
+
|
|
171
|
+
for entry in entries:
|
|
172
|
+
table.add_row(
|
|
173
|
+
entry["provider"],
|
|
174
|
+
"[green]✓[/]" if entry.get("has_username") else "—",
|
|
175
|
+
"[green]✓[/]" if entry.get("has_api_key") else "—",
|
|
176
|
+
"[green]✓[/]" if entry.get("has_token") else "—",
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
console.print(table)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
@auth.command(name="test")
|
|
183
|
+
@click.argument("provider")
|
|
184
|
+
def auth_test(provider: str) -> None:
|
|
185
|
+
"""
|
|
186
|
+
Test stored credentials for PROVIDER by attempting authentication.
|
|
187
|
+
|
|
188
|
+
\b
|
|
189
|
+
Example:
|
|
190
|
+
pygeofetch auth test usgs
|
|
191
|
+
"""
|
|
192
|
+
from pygeofetch.core.authenticator import AuthManager
|
|
193
|
+
|
|
194
|
+
console.print(f"Testing credentials for [bold]{provider}[/]...")
|
|
195
|
+
mgr = AuthManager(storage_backend='file')
|
|
196
|
+
try:
|
|
197
|
+
session = mgr.authenticate(provider)
|
|
198
|
+
console.print(f"[green]Success![/] Session valid until: {session.expires_at}")
|
|
199
|
+
except Exception as exc:
|
|
200
|
+
console.print(f"[red]Failed: {exc}[/]")
|
|
201
|
+
sys.exit(1)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
@auth.command(name="remove")
|
|
205
|
+
@click.argument("provider")
|
|
206
|
+
@click.option("--yes", "-y", is_flag=True, help="Skip confirmation prompt.")
|
|
207
|
+
def auth_remove(provider: str, yes: bool) -> None:
|
|
208
|
+
"""
|
|
209
|
+
Remove stored credentials for PROVIDER.
|
|
210
|
+
|
|
211
|
+
\b
|
|
212
|
+
Example:
|
|
213
|
+
pygeofetch auth remove planet
|
|
214
|
+
"""
|
|
215
|
+
from pygeofetch.core.authenticator import AuthManager
|
|
216
|
+
|
|
217
|
+
if not yes:
|
|
218
|
+
click.confirm(f"Remove credentials for {provider!r}?", abort=True)
|
|
219
|
+
|
|
220
|
+
mgr = AuthManager(storage_backend='file')
|
|
221
|
+
mgr.remove_credentials(provider)
|
|
222
|
+
console.print(f"[green]Credentials for [bold]{provider}[/] removed.[/]")
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
@auth.command(name="export")
|
|
226
|
+
@click.option("--provider", default=None, help="Export only this provider (default: all).")
|
|
227
|
+
@click.option(
|
|
228
|
+
"--output",
|
|
229
|
+
"-o",
|
|
230
|
+
default="credentials_backup.json",
|
|
231
|
+
show_default=True,
|
|
232
|
+
help="Output file path.",
|
|
233
|
+
)
|
|
234
|
+
def auth_export(provider: str | None, output: str) -> None:
|
|
235
|
+
"""
|
|
236
|
+
Export stored credentials to a JSON file for backup.
|
|
237
|
+
|
|
238
|
+
WARNING: Exported file contains sensitive credentials — store securely.
|
|
239
|
+
|
|
240
|
+
\b
|
|
241
|
+
Example:
|
|
242
|
+
pygeofetch auth export --output backup.json
|
|
243
|
+
pygeofetch auth export --provider usgs --output usgs_creds.json
|
|
244
|
+
"""
|
|
245
|
+
from pygeofetch.core.authenticator import AuthManager
|
|
246
|
+
|
|
247
|
+
mgr = AuthManager(storage_backend='file')
|
|
248
|
+
data = mgr.export_credentials(provider_filter=provider)
|
|
249
|
+
|
|
250
|
+
with open(output, "w") as f:
|
|
251
|
+
json.dump(data, f, indent=2, default=str)
|
|
252
|
+
|
|
253
|
+
console.print(
|
|
254
|
+
f"[yellow]WARNING: {output} contains sensitive credentials. "
|
|
255
|
+
"Store it securely and delete after use.[/]\n"
|
|
256
|
+
f"[green]Exported {len(data)} provider(s) to {output}[/]"
|
|
257
|
+
)
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Configuration CLI commands for pygeofetch.
|
|
3
|
+
|
|
4
|
+
Usage::
|
|
5
|
+
|
|
6
|
+
pygeofetch config show
|
|
7
|
+
pygeofetch config get download.parallel
|
|
8
|
+
pygeofetch config set download.parallel 4
|
|
9
|
+
pygeofetch config path
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import sys
|
|
15
|
+
|
|
16
|
+
import click
|
|
17
|
+
from rich.console import Console
|
|
18
|
+
from rich.syntax import Syntax
|
|
19
|
+
|
|
20
|
+
console = Console()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@click.group()
|
|
24
|
+
def config() -> None:
|
|
25
|
+
"""Inspect and modify pygeofetch configuration."""
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@config.command(name="show")
|
|
29
|
+
@click.option("--json", "as_json", is_flag=True, help="Output as JSON.")
|
|
30
|
+
def config_show(as_json: bool) -> None:
|
|
31
|
+
"""Show the effective configuration (all layers merged)."""
|
|
32
|
+
import json
|
|
33
|
+
from pygeofetch.config.settings import get_settings
|
|
34
|
+
|
|
35
|
+
settings = get_settings()
|
|
36
|
+
data = settings.model_dump()
|
|
37
|
+
|
|
38
|
+
if as_json:
|
|
39
|
+
click.echo(json.dumps(data, indent=2, default=str))
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
import yaml
|
|
43
|
+
rendered = yaml.dump(data, default_flow_style=False, sort_keys=True)
|
|
44
|
+
console.print(Syntax(rendered, "yaml", theme="monokai"))
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@config.command(name="get")
|
|
48
|
+
@click.argument("key")
|
|
49
|
+
def config_get(key: str) -> None:
|
|
50
|
+
"""
|
|
51
|
+
Get a single configuration value by dotted KEY path.
|
|
52
|
+
|
|
53
|
+
\b
|
|
54
|
+
Example:
|
|
55
|
+
pygeofetch config get download.parallel
|
|
56
|
+
"""
|
|
57
|
+
from pygeofetch.config.settings import get_settings
|
|
58
|
+
|
|
59
|
+
settings = get_settings()
|
|
60
|
+
data = settings.model_dump()
|
|
61
|
+
|
|
62
|
+
parts = key.split(".")
|
|
63
|
+
value = data
|
|
64
|
+
for part in parts:
|
|
65
|
+
if isinstance(value, dict) and part in value:
|
|
66
|
+
value = value[part]
|
|
67
|
+
else:
|
|
68
|
+
console.print(f"[red]Key not found: {key!r}[/]")
|
|
69
|
+
sys.exit(1)
|
|
70
|
+
|
|
71
|
+
console.print(f"{key} = {value!r}")
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@config.command(name="set")
|
|
75
|
+
@click.argument("key")
|
|
76
|
+
@click.argument("value")
|
|
77
|
+
def config_set(key: str, value: str) -> None:
|
|
78
|
+
"""
|
|
79
|
+
Set a configuration value in the user config file.
|
|
80
|
+
|
|
81
|
+
The value is cast to int/float/bool if it looks like one; otherwise stored as string.
|
|
82
|
+
|
|
83
|
+
\b
|
|
84
|
+
Example:
|
|
85
|
+
pygeofetch config set download.parallel 4
|
|
86
|
+
pygeofetch config set cache.ttl_seconds 7200
|
|
87
|
+
"""
|
|
88
|
+
from pygeofetch.config.settings import get_settings, save_user_config
|
|
89
|
+
|
|
90
|
+
# Try to coerce to typed value
|
|
91
|
+
typed_value: object = value
|
|
92
|
+
if value.lower() in ("true", "yes"):
|
|
93
|
+
typed_value = True
|
|
94
|
+
elif value.lower() in ("false", "no"):
|
|
95
|
+
typed_value = False
|
|
96
|
+
else:
|
|
97
|
+
try:
|
|
98
|
+
typed_value = int(value)
|
|
99
|
+
except ValueError:
|
|
100
|
+
try:
|
|
101
|
+
typed_value = float(value)
|
|
102
|
+
except ValueError:
|
|
103
|
+
pass # keep as string
|
|
104
|
+
|
|
105
|
+
# Build nested dict from dotted key
|
|
106
|
+
parts = key.split(".")
|
|
107
|
+
nested: dict = {}
|
|
108
|
+
current = nested
|
|
109
|
+
for i, part in enumerate(parts):
|
|
110
|
+
if i == len(parts) - 1:
|
|
111
|
+
current[part] = typed_value
|
|
112
|
+
else:
|
|
113
|
+
current[part] = {}
|
|
114
|
+
current = current[part]
|
|
115
|
+
|
|
116
|
+
save_user_config(nested)
|
|
117
|
+
console.print(f"[green]Set[/] {key} = {typed_value!r}")
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@config.command(name="path")
|
|
121
|
+
def config_path() -> None:
|
|
122
|
+
"""Show the location of configuration files."""
|
|
123
|
+
from pygeofetch.config.settings import get_config_dir
|
|
124
|
+
|
|
125
|
+
cfg_dir = get_config_dir()
|
|
126
|
+
console.print(f"Config directory: [cyan]{cfg_dir}[/]")
|
|
127
|
+
console.print(f"User config: [cyan]{cfg_dir / 'config.yaml'}[/]")
|
|
128
|
+
console.print(f"Credentials: [cyan]{cfg_dir / 'credentials.json'}[/]")
|
|
129
|
+
console.print(f"Cache: [cyan]{cfg_dir / 'cache'}[/]")
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@config.command(name="reset")
|
|
133
|
+
@click.confirmation_option(prompt="Reset user config to defaults?")
|
|
134
|
+
def config_reset() -> None:
|
|
135
|
+
"""Remove the user configuration file, restoring defaults."""
|
|
136
|
+
from pygeofetch.config.settings import get_config_dir
|
|
137
|
+
|
|
138
|
+
cfg_path = get_config_dir() / "config.yaml"
|
|
139
|
+
if cfg_path.exists():
|
|
140
|
+
cfg_path.unlink()
|
|
141
|
+
console.print(f"[green]Removed {cfg_path}[/]")
|
|
142
|
+
else:
|
|
143
|
+
console.print("[dim]No user config file found.[/]")
|