PyGeoFetch 0.1.2__tar.gz → 0.1.4__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 (65) hide show
  1. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/PKG-INFO +5 -5
  2. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/README.md +4 -4
  3. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/cli/auth_commands.py +20 -20
  4. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/cli/download_commands.py +1 -1
  5. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/cli/main.py +1 -1
  6. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/cli/search_commands.py +1 -1
  7. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/core/authenticator.py +20 -16
  8. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/core/engine.py +12 -11
  9. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/core/searcher.py +14 -14
  10. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch.egg-info/PKG-INFO +5 -5
  11. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pyproject.toml +1 -1
  12. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/LICENSE +0 -0
  13. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/__init__.py +0 -0
  14. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/cli/__init__.py +0 -0
  15. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/cli/config_commands.py +0 -0
  16. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/config/__init__.py +0 -0
  17. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/config/defaults.yaml +0 -0
  18. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/config/settings.py +0 -0
  19. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/core/__init__.py +0 -0
  20. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/core/cache_manager.py +0 -0
  21. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/core/downloader.py +0 -0
  22. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/core/scheduler.py +0 -0
  23. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/models/__init__.py +0 -0
  24. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/models/download_task.py +0 -0
  25. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/models/satellite_data.py +0 -0
  26. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/models/search_query.py +0 -0
  27. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/models/user_auth.py +0 -0
  28. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/__init__.py +0 -0
  29. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/airbus_oneatlas.py +0 -0
  30. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/alaska_satellite_facility.py +0 -0
  31. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/aws_earth.py +0 -0
  32. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/base.py +0 -0
  33. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/copernicus.py +0 -0
  34. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/digitalglobe.py +0 -0
  35. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/earth_explorer_additional.py +0 -0
  36. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/element84.py +0 -0
  37. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/esa_scihub.py +0 -0
  38. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/geoserver_generic.py +0 -0
  39. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/google_earth_engine.py +0 -0
  40. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/inpe_cbers.py +0 -0
  41. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/isro_bhuvan.py +0 -0
  42. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/jaxa_earth.py +0 -0
  43. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/maxar_gbdx.py +0 -0
  44. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/nasa_earthdata.py +0 -0
  45. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/nasa_earthdata_cloud.py +0 -0
  46. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/noaa_big_data.py +0 -0
  47. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/opentopography.py +0 -0
  48. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/planet.py +0 -0
  49. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/planetary_computer.py +0 -0
  50. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/sentinel_hub.py +0 -0
  51. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/terrabotics.py +0 -0
  52. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/providers/usgs.py +0 -0
  53. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/utils/__init__.py +0 -0
  54. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/utils/file_utils.py +0 -0
  55. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/utils/geo_utils.py +0 -0
  56. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/utils/logging_setup.py +0 -0
  57. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/utils/retry_handler.py +0 -0
  58. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch/utils/validators.py +0 -0
  59. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch.egg-info/SOURCES.txt +0 -0
  60. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch.egg-info/dependency_links.txt +0 -0
  61. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch.egg-info/entry_points.txt +0 -0
  62. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch.egg-info/not-zip-safe +0 -0
  63. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch.egg-info/requires.txt +0 -0
  64. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/pygeofetch.egg-info/top_level.txt +0 -0
  65. {pygeofetch-0.1.2 → pygeofetch-0.1.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pygeofetch
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: Universal satellite data download pipeline with unified access to 20+ repositories
5
5
  Author: pygeofetch Contributors
6
6
  License: MIT License
@@ -272,7 +272,7 @@ pygeofetch pipeline schedule weekly-sentinel2.yaml
272
272
 
273
273
  ## 📋 Documentation
274
274
 
275
- Comprehensive documentation is available at **https://pygeofetch.readthedocs.io**, including:
275
+ Comprehensive documentation is available at **https://appiahkubis14.github.io/pygeofetch-docs/**, including:
276
276
 
277
277
  - Full CLI reference
278
278
  - Provider authentication guides
@@ -284,16 +284,16 @@ Comprehensive documentation is available at **https://pygeofetch.readthedocs.io*
284
284
 
285
285
  ## 🤝 Contributing
286
286
 
287
- Contributions of all kinds are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for full guidelines.
287
+ Contributions of all kinds are welcome. See [CONTRIBUTING.md](https://github.com/appiahkubis14/pygeofetch?tab=contributing-ov-file) for full guidelines.
288
288
 
289
289
  Good first issues include implementing stub providers to full API integrations, improving test coverage, and adding new post-processing actions.
290
290
 
291
- ```bash
291
+ <!-- ```bash
292
292
  git clone https://github.com/appiahkubis14/pygeofetch
293
293
  cd pygeofetch
294
294
  pip install -e ".[dev,all]"
295
295
  pytest tests/ -v
296
- ```
296
+ ``` -->
297
297
 
298
298
  ---
299
299
 
@@ -189,7 +189,7 @@ pygeofetch pipeline schedule weekly-sentinel2.yaml
189
189
 
190
190
  ## 📋 Documentation
191
191
 
192
- Comprehensive documentation is available at **https://pygeofetch.readthedocs.io**, including:
192
+ Comprehensive documentation is available at **https://appiahkubis14.github.io/pygeofetch-docs/**, including:
193
193
 
194
194
  - Full CLI reference
195
195
  - Provider authentication guides
@@ -201,16 +201,16 @@ Comprehensive documentation is available at **https://pygeofetch.readthedocs.io*
201
201
 
202
202
  ## 🤝 Contributing
203
203
 
204
- Contributions of all kinds are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for full guidelines.
204
+ Contributions of all kinds are welcome. See [CONTRIBUTING.md](https://github.com/appiahkubis14/pygeofetch?tab=contributing-ov-file) for full guidelines.
205
205
 
206
206
  Good first issues include implementing stub providers to full API integrations, improving test coverage, and adding new post-processing actions.
207
207
 
208
- ```bash
208
+ <!-- ```bash
209
209
  git clone https://github.com/appiahkubis14/pygeofetch
210
210
  cd pygeofetch
211
211
  pip install -e ".[dev,all]"
212
212
  pytest tests/ -v
213
- ```
213
+ ``` -->
214
214
 
215
215
  ---
216
216
 
@@ -31,7 +31,6 @@ console = Console()
31
31
  def auth() -> None:
32
32
  """Manage provider authentication credentials."""
33
33
 
34
-
35
34
  @auth.command(name="add")
36
35
  @click.argument("provider")
37
36
  @click.option("--username", "-u", default=None, help="Username or email.")
@@ -47,7 +46,6 @@ def auth() -> None:
47
46
  show_default=True,
48
47
  help="Credential storage backend.",
49
48
  )
50
-
51
49
  def auth_add(
52
50
  provider: str,
53
51
  username: str | None,
@@ -60,44 +58,46 @@ def auth_add(
60
58
  ) -> None:
61
59
  """
62
60
  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
61
  """
70
62
  from pygeofetch.core.authenticator import AuthManager
71
63
 
72
- creds: dict = {}
73
-
64
+ # Initialize credentials dict
65
+ creds = {}
66
+
67
+ # Handle API key auth
74
68
  if api_key:
75
69
  creds["api_key"] = api_key
70
+ # Handle OAuth
76
71
  if client_id:
77
72
  creds["client_id"] = client_id
78
73
  if client_secret:
79
74
  creds["client_secret"] = client_secret
80
75
  if token:
81
76
  creds["token"] = token
82
-
83
- if not creds and not username:
84
- username = click.prompt(f"Username for {provider}")
85
-
86
- if username:
77
+
78
+ # Handle username/password auth
79
+ if username or (not creds): # If no credentials provided yet, prompt for username
80
+ if not username:
81
+ username = click.prompt(f"Username for {provider}")
87
82
  creds["username"] = username
88
- if not password and not api_key:
83
+
84
+ if not password and not api_key and not token:
89
85
  password = click.prompt(f"Password for {provider}", hide_input=True)
90
86
  if password:
91
87
  creds["password"] = password
92
-
88
+
93
89
  if not creds:
94
90
  console.print("[red]No credentials provided.[/]")
95
91
  sys.exit(1)
96
-
97
- mgr = AuthManager(storage_backend='file')
92
+
93
+ console.print(f"[yellow]Credentials to save: {list(creds.keys())}[/]") # Debug
94
+
95
+ mgr = AuthManager(storage_backend=store)
98
96
  mgr.add_credentials(provider, **creds)
99
97
  console.print(f"[green]Credentials for [bold]{provider}[/] saved.[/]")
100
-
98
+
99
+
100
+
101
101
 
102
102
  @auth.command(name="login")
103
103
  @click.argument("provider")
@@ -128,7 +128,7 @@ def download_run(
128
128
  overwrite=overwrite,
129
129
  )
130
130
 
131
- sb = pygeofetch()
131
+ sb = pygeofetch(auth_backend='file')
132
132
 
133
133
  # Load data
134
134
  if from_search:
@@ -102,7 +102,7 @@ def status(as_json: bool) -> None:
102
102
  from pygeofetch.core.engine import pygeofetch
103
103
  from pygeofetch.core.cache_manager import CacheManager
104
104
 
105
- sb = pygeofetch()
105
+ sb = pygeofetch(auth_backend='file')
106
106
  info = sb.status()
107
107
  cache_stats = CacheManager().stats()
108
108
 
@@ -148,7 +148,7 @@ def search_run(
148
148
  timeout_seconds=timeout,
149
149
  )
150
150
 
151
- sb = pygeofetch()
151
+ sb = pygeofetch(auth_backend='file')
152
152
 
153
153
  with console.status(f"[cyan]Searching {len(provider_list or [])} provider(s)...[/]"):
154
154
  results = sb.search(query, providers=provider_list, use_cache=not no_cache)
@@ -1,5 +1,5 @@
1
1
  """
2
- Authentication manager for pygeofetch.
2
+ Authentication manager for PyGeoFetch.
3
3
 
4
4
  Handles secure credential storage, session caching, and authentication
5
5
  flows for all providers. Supports system keyring, encrypted file storage,
@@ -41,7 +41,7 @@ class CredentialStore:
41
41
 
42
42
  SERVICE_NAME = "pygeofetch"
43
43
 
44
- def __init__(self, storage_backend: str = "keyring") -> None:
44
+ def __init__(self, storage_backend: str = "file") -> None:
45
45
  self.storage_backend = storage_backend
46
46
  self._config_dir = Path.home() / ".pygeofetch"
47
47
  self._cred_file = self._config_dir / "credentials.json"
@@ -56,12 +56,19 @@ class CredentialStore:
56
56
  self._in_memory[provider] = credentials
57
57
 
58
58
  def load(self, provider: str) -> Optional[Dict[str, Any]]:
59
- """Load credentials for a provider."""
59
+ """Load credentials for a provider — keyring first, then file fallback."""
60
60
  if provider in self._in_memory:
61
61
  return self._in_memory[provider]
62
62
  if self.storage_backend == "keyring":
63
- return self._load_keyring(provider)
64
- return self._load_file(provider)
63
+ result = self._load_keyring(provider)
64
+ if result:
65
+ return result
66
+ # Fall back to file store so credentials saved via --store file
67
+ # are always visible regardless of which backend is active
68
+ result = self._load_file(provider)
69
+ if result:
70
+ self._in_memory[provider] = result # cache it
71
+ return result
65
72
 
66
73
  def delete(self, provider: str) -> bool:
67
74
  """Remove stored credentials for a provider."""
@@ -204,11 +211,11 @@ class AuthManager:
204
211
  auth.remove("copernicus")
205
212
  """
206
213
 
207
- def __init__(self, storage_backend: str = "file") -> None: # Change default to 'file'
214
+ def __init__(self, storage_backend: str = "file") -> None:
208
215
  self.store = CredentialStore(storage_backend=storage_backend)
209
216
  self._sessions: Dict[str, AuthSession] = {}
210
217
 
211
- def add_credentials(
218
+ def add(
212
219
  self,
213
220
  provider: str,
214
221
  *,
@@ -287,7 +294,6 @@ class AuthManager:
287
294
  # Invalidate cached session
288
295
  self._sessions.pop(provider, None)
289
296
  logger.info(f"Credentials saved for provider {provider!r}")
290
- logger.info(cred_data)
291
297
 
292
298
  def get_credentials(self, provider: str) -> Optional[Credentials]:
293
299
  """
@@ -304,6 +310,9 @@ class AuthManager:
304
310
  return None
305
311
  try:
306
312
  from pydantic import SecretStr
313
+ # Always inject the provider field — it may not be persisted on disk
314
+ data = dict(data)
315
+ data.setdefault("provider", provider)
307
316
  if "password" in data and isinstance(data["password"], str):
308
317
  data["password"] = SecretStr(data["password"])
309
318
  if "api_key" in data and isinstance(data["api_key"], str):
@@ -371,25 +380,20 @@ class AuthManager:
371
380
  List all providers with stored credentials.
372
381
 
373
382
  Returns:
374
- List of dicts with provider info and credential types.
383
+ List of dicts with provider info and session status.
375
384
  """
376
385
  providers = self.store.list_providers()
377
386
  result = []
378
387
  for provider in providers:
379
- creds = self.get_credentials(provider)
380
388
  session = self._sessions.get(provider)
381
389
  result.append({
382
390
  "provider": provider,
383
391
  "has_session": session is not None and session.is_valid,
384
392
  "session_expires": session.expires_at.isoformat() if session and session.expires_at else None,
385
- "has_username": creds is not None and creds.username is not None,
386
- "has_api_key": creds is not None and creds.api_key is not None,
387
- "has_token": creds is not None and creds.token is not None,
388
393
  })
389
394
  return result
390
395
 
391
-
392
- def remove_credentials(self, provider: str) -> bool:
396
+ def remove(self, provider: str) -> bool:
393
397
  """
394
398
  Remove stored credentials and session for a provider.
395
399
 
@@ -425,4 +429,4 @@ class AuthManager:
425
429
  "auth_type": creds.auth_type.value,
426
430
  "username": creds.username,
427
431
  }
428
- return result
432
+ return result
@@ -1,17 +1,17 @@
1
1
  """
2
- pygeofetch main engine.
2
+ PyGeoFetch main engine.
3
3
 
4
- The ``pygeofetch`` class is the single entry point for the Python API.
4
+ The ``PyGeoFetch`` class is the single entry point for the Python API.
5
5
  It wires together authentication, search, and download subsystems and
6
6
  exposes a clean high-level interface.
7
7
 
8
8
  Example::
9
9
 
10
10
  from pathlib import Path
11
- from pygeofetch import pygeofetch
11
+ from pygeofetch import PyGeoFetch
12
12
  from pygeofetch.models import SearchQuery
13
13
 
14
- sb = pygeofetch()
14
+ sb = PyGeoFetch()
15
15
  sb.auth.add("usgs", username="user", password="pass")
16
16
 
17
17
  results = sb.search(
@@ -47,7 +47,7 @@ class pygeofetch:
47
47
  """
48
48
  Universal satellite data pipeline.
49
49
 
50
- ``pygeofetch`` is the top-level API object that provides access
50
+ ``PyGeoFetch`` is the top-level API object that provides access
51
51
  to all subsystems:
52
52
 
53
53
  - ``sb.auth`` – :class:`~pygeofetch.core.authenticator.AuthManager`
@@ -62,7 +62,7 @@ class pygeofetch:
62
62
 
63
63
  Example::
64
64
 
65
- sb = pygeofetch(log_level="INFO")
65
+ sb = PyGeoFetch(log_level="INFO")
66
66
  results = sb.search(SearchQuery(bbox=(-74, 40, -73, 41)))
67
67
  sb.download(results, Path("./data/"))
68
68
  """
@@ -75,9 +75,10 @@ class pygeofetch:
75
75
  cache_ttl: int = 3600,
76
76
  max_search_workers: int = 8,
77
77
  progress_callback: Optional[Callable] = None,
78
+ auth_backend: str = "file",
78
79
  ) -> None:
79
80
  """
80
- Initialize pygeofetch.
81
+ Initialize PyGeoFetch.
81
82
 
82
83
  Args:
83
84
  config_path: Optional path to a custom config YAML file.
@@ -88,9 +89,9 @@ class pygeofetch:
88
89
  progress_callback: Optional callable(DownloadProgress) for progress events.
89
90
  """
90
91
  setup_logging(level=log_level, use_rich=not log_json)
91
- logger.debug("Initializing pygeofetch")
92
+ logger.debug("Initializing PyGeoFetch")
92
93
 
93
- self.auth = AuthManager()
94
+ self.auth = AuthManager(storage_backend=auth_backend)
94
95
  self.searcher = FederatedSearcher(
95
96
  auth_manager=self.auth,
96
97
  cache_ttl=cache_ttl,
@@ -104,7 +105,7 @@ class pygeofetch:
104
105
  if config_path:
105
106
  self._load_config(config_path)
106
107
 
107
- logger.info("pygeofetch ready")
108
+ logger.info("PyGeoFetch ready")
108
109
 
109
110
  # ------------------------------------------------------------------
110
111
  # Search
@@ -306,7 +307,7 @@ class pygeofetch:
306
307
  def __repr__(self) -> str:
307
308
  authed = [item["provider"] for item in self.auth.list()]
308
309
  return (
309
- f"pygeofetch("
310
+ f"PyGeoFetch("
310
311
  f"authenticated={authed}, "
311
312
  f"cache_entries={len(self.searcher.cache._cache)})"
312
313
  )
@@ -1,5 +1,5 @@
1
1
  """
2
- Federated search engine for pygeofetch.
2
+ Federated search engine for PyGeoFetch.
3
3
 
4
4
  Provides parallel search across multiple providers with result deduplication,
5
5
  relevance scoring, caching, and STAC-compliant output.
@@ -208,20 +208,20 @@ class FederatedSearcher:
208
208
 
209
209
  def _get_provider(self, provider_id: str) -> Any:
210
210
  """Get or create a provider instance with session from auth manager."""
211
- if provider_id not in self._provider_instances:
212
- from pygeofetch.providers import get_provider
213
- prov = get_provider(provider_id)
211
+ from pygeofetch.providers import get_provider
212
+ prov = get_provider(provider_id)
214
213
 
215
- if self.auth_manager and prov.REQUIRES_AUTH:
216
- try:
217
- session = self.auth_manager.authenticate(provider_id)
218
- prov.set_session(session)
219
- except Exception as exc:
220
- logger.debug(f"Auth for {provider_id} failed: {exc}")
214
+ if self.auth_manager and prov.REQUIRES_AUTH:
215
+ # Always re-attempt auth — do not cache unauthenticated providers
216
+ try:
217
+ session = self.auth_manager.authenticate(provider_id)
218
+ prov.set_session(session)
219
+ logger.debug(f"Authenticated {provider_id} for search")
220
+ except Exception as exc:
221
+ logger.warning(f"{provider_id}: authentication failed: {exc}")
222
+ # Leave provider unauthenticated — require_auth() in search() will raise
221
223
 
222
- self._provider_instances[provider_id] = prov
223
-
224
- return self._provider_instances[provider_id]
224
+ return prov
225
225
 
226
226
  def _get_available_providers(self) -> List[str]:
227
227
  """Return providers that have stored credentials or require no auth."""
@@ -338,4 +338,4 @@ class FederatedSearcher:
338
338
  "providers", [{}]
339
339
  )[0].get("name", "unknown")
340
340
  results.append(SatelliteData.from_stac_item(feature, provider))
341
- return results
341
+ return results
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pygeofetch
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: Universal satellite data download pipeline with unified access to 20+ repositories
5
5
  Author: pygeofetch Contributors
6
6
  License: MIT License
@@ -272,7 +272,7 @@ pygeofetch pipeline schedule weekly-sentinel2.yaml
272
272
 
273
273
  ## 📋 Documentation
274
274
 
275
- Comprehensive documentation is available at **https://pygeofetch.readthedocs.io**, including:
275
+ Comprehensive documentation is available at **https://appiahkubis14.github.io/pygeofetch-docs/**, including:
276
276
 
277
277
  - Full CLI reference
278
278
  - Provider authentication guides
@@ -284,16 +284,16 @@ Comprehensive documentation is available at **https://pygeofetch.readthedocs.io*
284
284
 
285
285
  ## 🤝 Contributing
286
286
 
287
- Contributions of all kinds are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for full guidelines.
287
+ Contributions of all kinds are welcome. See [CONTRIBUTING.md](https://github.com/appiahkubis14/pygeofetch?tab=contributing-ov-file) for full guidelines.
288
288
 
289
289
  Good first issues include implementing stub providers to full API integrations, improving test coverage, and adding new post-processing actions.
290
290
 
291
- ```bash
291
+ <!-- ```bash
292
292
  git clone https://github.com/appiahkubis14/pygeofetch
293
293
  cd pygeofetch
294
294
  pip install -e ".[dev,all]"
295
295
  pytest tests/ -v
296
- ```
296
+ ``` -->
297
297
 
298
298
  ---
299
299
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pygeofetch"
7
- version = "0.1.2"
7
+ version = "0.1.4"
8
8
  description = "Universal satellite data download pipeline with unified access to 20+ repositories"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
File without changes
File without changes