eodag 3.5.1__py3-none-any.whl → 3.7.0__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.
eodag/rest/server.py CHANGED
@@ -383,24 +383,26 @@ async def list_collection_queryables(
383
383
  :returns: A json object containing the list of available queryable properties for the specified collection.
384
384
  """
385
385
  logger.info(f"{request.method} {request.state.url}")
386
- # split by `,` to handle list of parameters
387
- additional_params = {k: v.split(",") for k, v in dict(request.query_params).items()}
388
- provider = additional_params.pop("provider", None)
389
386
 
390
- datetime = additional_params.pop("datetime", None)
387
+ params: dict[str, list[Any]] = {}
388
+ for k, v in request.query_params.multi_items():
389
+ params.setdefault(k, []).append(v)
390
+
391
+ provider = params.pop("provider", [None])[0]
392
+ datetime = params.pop("datetime", [None])[0]
391
393
 
392
394
  queryables = await get_queryables(
393
395
  request,
394
396
  QueryablesGetParams.model_validate(
395
397
  {
396
- **additional_params,
398
+ **params,
397
399
  **{
398
400
  "collection": collection_id,
399
- "datetime": datetime[0] if datetime else None,
401
+ "datetime": datetime,
400
402
  },
401
403
  }
402
404
  ),
403
- provider=provider[0] if provider else None,
405
+ provider=provider,
404
406
  )
405
407
 
406
408
  return ORJSONResponse(queryables)
eodag/utils/__init__.py CHANGED
@@ -36,6 +36,7 @@ import re
36
36
  import shutil
37
37
  import ssl
38
38
  import string
39
+ import struct
39
40
  import sys
40
41
  import types
41
42
  import unicodedata
@@ -61,18 +62,7 @@ from typing import (
61
62
  Union,
62
63
  cast,
63
64
  )
64
-
65
- # All modules using these should import them from utils package
66
- from urllib.parse import ( # noqa; noqa
67
- parse_qs,
68
- parse_qsl,
69
- quote,
70
- unquote,
71
- urlencode,
72
- urljoin,
73
- urlparse,
74
- urlsplit,
75
- )
65
+ from urllib.parse import urlparse, urlsplit
76
66
  from urllib.request import url2pathname
77
67
 
78
68
  if sys.version_info >= (3, 12):
@@ -80,7 +70,6 @@ if sys.version_info >= (3, 12):
80
70
  else:
81
71
  from typing_extensions import Unpack # noqa
82
72
 
83
-
84
73
  import click
85
74
  import orjson
86
75
  import shapefile
@@ -110,6 +99,13 @@ logger = py_logging.getLogger("eodag.utils")
110
99
  DEFAULT_PROJ = "EPSG:4326"
111
100
 
112
101
  GENERIC_PRODUCT_TYPE = "GENERIC_PRODUCT_TYPE"
102
+ GENERIC_STAC_PROVIDER = "generic_stac_provider"
103
+
104
+ STAC_SEARCH_PLUGINS = [
105
+ "StacSearch",
106
+ "StacListAssets",
107
+ "StaticStacSearch",
108
+ ]
113
109
 
114
110
  eodag_version = metadata("eodag")["Version"]
115
111
  USER_AGENT = {"User-Agent": f"eodag/{eodag_version}"}
@@ -217,14 +213,13 @@ class FloatRange(click.types.FloatParamType):
217
213
  ):
218
214
  if self.min is None:
219
215
  self.fail(
220
- "%s is bigger than the maximum valid value " "%s." % (rv, self.max),
216
+ "%s is bigger than the maximum valid value %s." % (rv, self.max),
221
217
  param,
222
218
  ctx,
223
219
  )
224
220
  elif self.max is None:
225
221
  self.fail(
226
- "%s is smaller than the minimum valid value "
227
- "%s." % (rv, self.min),
222
+ "%s is smaller than the minimum valid value %s." % (rv, self.min),
228
223
  param,
229
224
  ctx,
230
225
  )
@@ -380,27 +375,29 @@ def merge_mappings(mapping1: dict[Any, Any], mapping2: dict[Any, Any]) -> None:
380
375
  # `m1_keys_lowercase.get(key, key)`
381
376
  current_value = mapping1.get(m1_keys_lowercase.get(key, key))
382
377
  if current_value is not None:
383
- current_value_type = type(current_value)
384
- new_value_type = type(value)
385
378
  try:
386
379
  # If current or new value is a list (search queryable parameter), simply replace current with new
387
380
  if (
388
- new_value_type == list
389
- and current_value_type != list
390
- or new_value_type != list
391
- and current_value_type == list
381
+ isinstance(value, list)
382
+ and not isinstance(current_value, list)
383
+ or not isinstance(value, list)
384
+ and isinstance(current_value, list)
392
385
  ):
393
386
  mapping1[m1_keys_lowercase.get(key, key)] = value
394
387
  else:
395
388
  mapping1[m1_keys_lowercase.get(key, key)] = cast_scalar_value(
396
- value, current_value_type
389
+ value, type(current_value)
397
390
  )
398
391
  except (TypeError, ValueError):
399
392
  # Ignore any override value that does not have the same type
400
393
  # as the default value
401
394
  logger.debug(
402
- f"Ignored '{key}' setting override from '{current_value}' to '{value}', "
403
- f"(could not cast {new_value_type} to {current_value_type})"
395
+ "Ignored '%s' setting override from '%s' to '%s', (could not cast %s to %s)",
396
+ key,
397
+ current_value,
398
+ value,
399
+ type(value),
400
+ type(current_value),
404
401
  )
405
402
  pass
406
403
  else:
@@ -1444,8 +1441,7 @@ def cast_scalar_value(value: Any, new_type: Any) -> Any:
1444
1441
  # case
1445
1442
  if value.capitalize() not in ("True", "False"):
1446
1443
  raise ValueError(
1447
- "Only true or false strings (case insensitive) are "
1448
- "allowed for booleans"
1444
+ "Only true or false strings (case insensitive) are allowed for booleans"
1449
1445
  )
1450
1446
  # Get the real Python value of the boolean. e.g: value='tRuE'
1451
1447
  # => eval(value.capitalize())=True.
@@ -1498,6 +1494,7 @@ def guess_extension(type: str) -> Optional[str]:
1498
1494
  return mimetypes.guess_extension(type, strict=False)
1499
1495
 
1500
1496
 
1497
+ @functools.lru_cache(maxsize=2)
1501
1498
  def get_ssl_context(ssl_verify: bool) -> ssl.SSLContext:
1502
1499
  """
1503
1500
  Returns an SSL context based on ``ssl_verify`` argument.
@@ -1565,3 +1562,27 @@ def remove_str_array_quotes(input_str: str) -> str:
1565
1562
  continue
1566
1563
  output_str += input_str[i]
1567
1564
  return output_str
1565
+
1566
+
1567
+ def parse_le_uint32(data: bytes) -> int:
1568
+ """
1569
+ Parse little-endian unsigned 4-byte integer.
1570
+
1571
+ >>> parse_le_uint32(b'\\x01\\x00\\x00\\x00')
1572
+ 1
1573
+ >>> parse_le_uint32(b'\\xff\\xff\\xff\\xff')
1574
+ 4294967295
1575
+ """
1576
+ return struct.unpack("<I", data)[0]
1577
+
1578
+
1579
+ def parse_le_uint16(data: bytes) -> int:
1580
+ """
1581
+ Parse little-endian unsigned 2-byte integer.
1582
+
1583
+ >>> parse_le_uint16(b'\\x01\\x00')
1584
+ 1
1585
+ >>> parse_le_uint16(b'\\xff\\xff')
1586
+ 65535
1587
+ """
1588
+ return struct.unpack("<H", data)[0]
eodag/utils/exceptions.py CHANGED
@@ -79,6 +79,10 @@ class STACOpenerError(EodagError):
79
79
  """An error indicating that a STAC file could not be opened"""
80
80
 
81
81
 
82
+ class InvalidDataError(EodagError):
83
+ """Raised when data is invalid, malformed, or corrupt and cannot be processed as expected."""
84
+
85
+
82
86
  class RequestError(EodagError):
83
87
  """An error indicating that a request has failed. Usually eodag functions
84
88
  and methods should catch and skip this"""