eodag 3.1.0b1__py3-none-any.whl → 3.1.0b2__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.
Files changed (85) hide show
  1. eodag/api/core.py +59 -52
  2. eodag/api/product/_assets.py +5 -5
  3. eodag/api/product/_product.py +27 -12
  4. eodag/api/product/drivers/__init__.py +81 -4
  5. eodag/api/product/drivers/base.py +65 -4
  6. eodag/api/product/drivers/generic.py +65 -0
  7. eodag/api/product/drivers/sentinel1.py +97 -0
  8. eodag/api/product/drivers/sentinel2.py +95 -0
  9. eodag/api/product/metadata_mapping.py +62 -74
  10. eodag/api/search_result.py +13 -23
  11. eodag/cli.py +4 -4
  12. eodag/config.py +66 -69
  13. eodag/plugins/apis/base.py +1 -1
  14. eodag/plugins/apis/ecmwf.py +10 -9
  15. eodag/plugins/apis/usgs.py +11 -10
  16. eodag/plugins/authentication/aws_auth.py +16 -13
  17. eodag/plugins/authentication/base.py +5 -3
  18. eodag/plugins/authentication/header.py +3 -3
  19. eodag/plugins/authentication/keycloak.py +4 -4
  20. eodag/plugins/authentication/oauth.py +7 -3
  21. eodag/plugins/authentication/openid_connect.py +14 -14
  22. eodag/plugins/authentication/sas_auth.py +4 -4
  23. eodag/plugins/authentication/token.py +7 -7
  24. eodag/plugins/authentication/token_exchange.py +1 -1
  25. eodag/plugins/base.py +4 -4
  26. eodag/plugins/crunch/base.py +4 -4
  27. eodag/plugins/crunch/filter_date.py +4 -4
  28. eodag/plugins/crunch/filter_latest_intersect.py +6 -6
  29. eodag/plugins/crunch/filter_latest_tpl_name.py +7 -7
  30. eodag/plugins/crunch/filter_overlap.py +4 -4
  31. eodag/plugins/crunch/filter_property.py +4 -4
  32. eodag/plugins/download/aws.py +47 -66
  33. eodag/plugins/download/base.py +8 -17
  34. eodag/plugins/download/creodias_s3.py +2 -2
  35. eodag/plugins/download/http.py +30 -32
  36. eodag/plugins/download/s3rest.py +5 -4
  37. eodag/plugins/manager.py +10 -20
  38. eodag/plugins/search/__init__.py +6 -5
  39. eodag/plugins/search/base.py +35 -40
  40. eodag/plugins/search/build_search_result.py +69 -68
  41. eodag/plugins/search/cop_marine.py +22 -12
  42. eodag/plugins/search/creodias_s3.py +8 -78
  43. eodag/plugins/search/csw.py +11 -11
  44. eodag/plugins/search/data_request_search.py +16 -15
  45. eodag/plugins/search/qssearch.py +56 -52
  46. eodag/plugins/search/stac_list_assets.py +85 -0
  47. eodag/plugins/search/static_stac_search.py +3 -3
  48. eodag/resources/ext_product_types.json +1 -1
  49. eodag/resources/product_types.yml +288 -288
  50. eodag/resources/providers.yml +146 -6
  51. eodag/resources/stac_api.yml +2 -2
  52. eodag/resources/user_conf_template.yml +11 -0
  53. eodag/rest/cache.py +2 -2
  54. eodag/rest/config.py +3 -3
  55. eodag/rest/core.py +24 -24
  56. eodag/rest/errors.py +5 -5
  57. eodag/rest/server.py +3 -11
  58. eodag/rest/stac.py +40 -38
  59. eodag/rest/types/collections_search.py +3 -3
  60. eodag/rest/types/eodag_search.py +23 -23
  61. eodag/rest/types/queryables.py +13 -13
  62. eodag/rest/types/stac_search.py +15 -25
  63. eodag/rest/utils/__init__.py +11 -21
  64. eodag/rest/utils/cql_evaluate.py +6 -6
  65. eodag/rest/utils/rfc3339.py +2 -2
  66. eodag/types/__init__.py +24 -18
  67. eodag/types/bbox.py +2 -2
  68. eodag/types/download_args.py +2 -2
  69. eodag/types/queryables.py +5 -2
  70. eodag/types/search_args.py +4 -4
  71. eodag/types/whoosh.py +1 -3
  72. eodag/utils/__init__.py +81 -40
  73. eodag/utils/exceptions.py +2 -2
  74. eodag/utils/import_system.py +2 -2
  75. eodag/utils/requests.py +2 -2
  76. eodag/utils/rest.py +2 -2
  77. eodag/utils/s3.py +208 -0
  78. eodag/utils/stac_reader.py +10 -10
  79. {eodag-3.1.0b1.dist-info → eodag-3.1.0b2.dist-info}/METADATA +5 -4
  80. eodag-3.1.0b2.dist-info/RECORD +113 -0
  81. {eodag-3.1.0b1.dist-info → eodag-3.1.0b2.dist-info}/entry_points.txt +1 -0
  82. eodag-3.1.0b1.dist-info/RECORD +0 -108
  83. {eodag-3.1.0b1.dist-info → eodag-3.1.0b2.dist-info}/LICENSE +0 -0
  84. {eodag-3.1.0b1.dist-info → eodag-3.1.0b2.dist-info}/WHEEL +0 -0
  85. {eodag-3.1.0b1.dist-info → eodag-3.1.0b2.dist-info}/top_level.txt +0 -0
@@ -23,17 +23,7 @@ import logging
23
23
  import os
24
24
  from io import BufferedReader
25
25
  from shutil import make_archive, rmtree
26
- from typing import (
27
- TYPE_CHECKING,
28
- Any,
29
- Callable,
30
- Dict,
31
- Iterator,
32
- List,
33
- NamedTuple,
34
- Optional,
35
- Union,
36
- )
26
+ from typing import TYPE_CHECKING, Any, Callable, Iterator, NamedTuple, Optional, Union
37
27
  from urllib.parse import unquote_plus, urlencode
38
28
 
39
29
  import orjson
@@ -63,7 +53,7 @@ class Cruncher(NamedTuple):
63
53
  """Type hinted Cruncher namedTuple"""
64
54
 
65
55
  clazz: Callable[..., Any]
66
- config_params: List[str]
56
+ config_params: list[str]
67
57
 
68
58
 
69
59
  crunchers = {
@@ -90,19 +80,19 @@ def format_pydantic_error(e: pydanticValidationError) -> str:
90
80
 
91
81
  def is_dict_str_any(var: Any) -> bool:
92
82
  """Verify whether the variable is of type dict[str, Any]"""
93
- if isinstance(var, Dict):
83
+ if isinstance(var, dict):
94
84
  return all(isinstance(k, str) for k in var.keys()) # type: ignore
95
85
  return False
96
86
 
97
87
 
98
- def str2list(v: Optional[str]) -> Optional[List[str]]:
88
+ def str2list(v: Optional[str]) -> Optional[list[str]]:
99
89
  """Convert string to list base on , delimiter."""
100
90
  if v:
101
91
  return v.split(",")
102
92
  return None
103
93
 
104
94
 
105
- def str2json(k: str, v: Optional[str] = None) -> Optional[Dict[str, Any]]:
95
+ def str2json(k: str, v: Optional[str] = None) -> Optional[dict[str, Any]]:
106
96
  """decoding a URL parameter and then parsing it as JSON."""
107
97
  if not v:
108
98
  return None
@@ -112,25 +102,25 @@ def str2json(k: str, v: Optional[str] = None) -> Optional[Dict[str, Any]]:
112
102
  raise ValidationError(f"{k}: Incorrect JSON object") from e
113
103
 
114
104
 
115
- def flatten_list(nested_list: Union[Any, List[Any]]) -> List[Any]:
105
+ def flatten_list(nested_list: Union[Any, list[Any]]) -> list[Any]:
116
106
  """Flatten a nested list structure into a single list."""
117
107
  if not isinstance(nested_list, list):
118
108
  return [nested_list]
119
109
  else:
120
- flattened: List[Any] = []
110
+ flattened: list[Any] = []
121
111
  for element in nested_list:
122
112
  flattened.extend(flatten_list(element))
123
113
  return flattened
124
114
 
125
115
 
126
- def list_to_str_list(input_list: List[Any]) -> List[str]:
116
+ def list_to_str_list(input_list: list[Any]) -> list[str]:
127
117
  """Attempt to convert a list of any type to a list of strings."""
128
118
  try:
129
119
  # Try to convert each element to a string
130
120
  return [str(element) for element in input_list]
131
121
  except Exception as e:
132
122
  # Raise an exception if any element cannot be converted
133
- raise TypeError(f"Failed to convert to List[str]: {e}") from e
123
+ raise TypeError(f"Failed to convert to list[str]: {e}") from e
134
124
 
135
125
 
136
126
  def get_next_link(
@@ -138,7 +128,7 @@ def get_next_link(
138
128
  search_request: SearchPostRequest,
139
129
  total_results: Optional[int],
140
130
  items_per_page: int,
141
- ) -> Optional[Dict[str, Any]]:
131
+ ) -> Optional[dict[str, Any]]:
142
132
  """Generate next link URL and body"""
143
133
  body = search_request.model_dump(exclude_none=True)
144
134
  if "bbox" in body:
@@ -159,7 +149,7 @@ def get_next_link(
159
149
  params["page"] = str(page + 1)
160
150
  url += f"?{urlencode(params)}"
161
151
 
162
- next: Dict[str, Any] = {
152
+ next: dict[str, Any] = {
163
153
  "rel": "next",
164
154
  "href": url,
165
155
  "title": "Next page",
@@ -16,13 +16,13 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
  from datetime import datetime as dt
19
- from typing import Any, Dict, List, Optional, Tuple, Union
19
+ from typing import Any, Optional, Union
20
20
 
21
21
  from pygeofilter import ast
22
22
  from pygeofilter.backends.evaluator import Evaluator, handle
23
23
  from pygeofilter.values import Geometry, Interval
24
24
 
25
- simpleNode = Union[ast.Attribute, str, int, complex, float, List[Any], Tuple[Any, ...]]
25
+ simpleNode = Union[ast.Attribute, str, int, complex, float, list[Any], tuple[Any, ...]]
26
26
 
27
27
 
28
28
  class EodagEvaluator(Evaluator):
@@ -36,7 +36,7 @@ class EodagEvaluator(Evaluator):
36
36
  return node
37
37
 
38
38
  @handle(Geometry)
39
- def spatial(self, node: Geometry) -> Dict[str, Any]:
39
+ def spatial(self, node: Geometry) -> dict[str, Any]:
40
40
  """handle geometry"""
41
41
  return node.geometry
42
42
 
@@ -46,7 +46,7 @@ class EodagEvaluator(Evaluator):
46
46
  return node.strftime("%Y-%m-%dT%H:%M:%SZ")
47
47
 
48
48
  @handle(Interval)
49
- def interval(self, _, *interval: Any) -> List[Any]:
49
+ def interval(self, _, *interval: Any) -> list[Any]:
50
50
  """handle datetime interval"""
51
51
  return list(interval)
52
52
 
@@ -60,7 +60,7 @@ class EodagEvaluator(Evaluator):
60
60
  )
61
61
  def predicate(
62
62
  self, node: ast.Predicate, lhs: Any, rhs: Any
63
- ) -> Optional[Dict[str, Any]]:
63
+ ) -> Optional[dict[str, Any]]:
64
64
  """
65
65
  Handle predicates
66
66
  Verify the property is first attribute in each predicate
@@ -114,6 +114,6 @@ class EodagEvaluator(Evaluator):
114
114
  return {lhs.name: list(rhs)}
115
115
 
116
116
  @handle(ast.And)
117
- def combination(self, _, lhs: Dict[str, str], rhs: Dict[str, str]):
117
+ def combination(self, _, lhs: dict[str, str], rhs: dict[str, str]):
118
118
  """handle combinations"""
119
119
  return {**lhs, **rhs}
@@ -16,14 +16,14 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
  import datetime
19
- from typing import Optional, Tuple
19
+ from typing import Optional
20
20
 
21
21
  from eodag.utils.rest import rfc3339_str_to_datetime
22
22
 
23
23
 
24
24
  def str_to_interval(
25
25
  interval: Optional[str],
26
- ) -> Tuple[Optional[datetime.datetime], Optional[datetime.datetime]]:
26
+ ) -> tuple[Optional[datetime.datetime], Optional[datetime.datetime]]:
27
27
  """Extract a tuple of datetimes from an interval string.
28
28
 
29
29
  Interval strings are defined by
eodag/types/__init__.py CHANGED
@@ -22,11 +22,8 @@ from __future__ import annotations
22
22
  from typing import (
23
23
  Annotated,
24
24
  Any,
25
- Dict,
26
- List,
27
25
  Literal,
28
26
  Optional,
29
- Tuple,
30
27
  TypedDict,
31
28
  Union,
32
29
  get_args,
@@ -42,7 +39,7 @@ from eodag.utils.exceptions import ValidationError
42
39
 
43
40
  # Types mapping from JSON Schema and OpenAPI 3.1.0 specifications to Python
44
41
  # See https://spec.openapis.org/oas/v3.1.0#data-types
45
- JSON_TYPES_MAPPING: Dict[str, type] = {
42
+ JSON_TYPES_MAPPING: dict[str, type] = {
46
43
  "boolean": bool,
47
44
  "integer": int,
48
45
  "number": float,
@@ -53,7 +50,7 @@ JSON_TYPES_MAPPING: Dict[str, type] = {
53
50
  }
54
51
 
55
52
 
56
- def json_type_to_python(json_type: Union[str, List[str]]) -> type:
53
+ def json_type_to_python(json_type: Union[str, list[str]]) -> type:
57
54
  """Get python type from json type https://spec.openapis.org/oas/v3.1.0#data-types
58
55
 
59
56
  >>> json_type_to_python("number")
@@ -70,7 +67,7 @@ def json_type_to_python(json_type: Union[str, List[str]]) -> type:
70
67
  return type(None)
71
68
 
72
69
 
73
- def _get_min_or_max(type_info: Union[Lt, Gt, Any]) -> Tuple[str, Any]:
70
+ def _get_min_or_max(type_info: Union[Lt, Gt, Any]) -> tuple[str, Any]:
74
71
  """Checks if the value from an Annotated object is a minimum or maximum
75
72
 
76
73
  :param type_info: info from Annotated
@@ -85,7 +82,7 @@ def _get_min_or_max(type_info: Union[Lt, Gt, Any]) -> Tuple[str, Any]:
85
82
 
86
83
  def _get_type_info_from_annotated(
87
84
  annotated_type: Annotated[type, Any],
88
- ) -> Dict[str, Any]:
85
+ ) -> dict[str, Any]:
89
86
  """Retrieves type information from an annotated object
90
87
 
91
88
  :param annotated_type: annotated object
@@ -108,7 +105,7 @@ def _get_type_info_from_annotated(
108
105
 
109
106
  def python_type_to_json(
110
107
  python_type: type,
111
- ) -> Optional[Union[str, List[Dict[str, Any]]]]:
108
+ ) -> Optional[Union[str, list[dict[str, Any]]]]:
112
109
  """Get json type from python https://spec.openapis.org/oas/v3.1.0#data-types
113
110
 
114
111
  >>> python_type_to_json(int)
@@ -149,7 +146,7 @@ def python_type_to_json(
149
146
 
150
147
 
151
148
  def json_field_definition_to_python(
152
- json_field_definition: Dict[str, Any],
149
+ json_field_definition: dict[str, Any],
153
150
  default_value: Optional[Any] = None,
154
151
  required: Optional[bool] = False,
155
152
  ) -> Annotated[Any, FieldInfo]:
@@ -186,7 +183,7 @@ def json_field_definition_to_python(
186
183
  if python_type in (list, set):
187
184
  items = json_field_definition.get("items", None)
188
185
  if isinstance(items, list):
189
- python_type = Tuple[ # type: ignore
186
+ python_type = tuple[ # type: ignore
190
187
  tuple(
191
188
  json_field_definition_to_python(item, required=required)
192
189
  for item in items
@@ -197,7 +194,7 @@ def json_field_definition_to_python(
197
194
 
198
195
  if enum:
199
196
  literal = Literal[tuple(sorted(enum))] # type: ignore
200
- python_type = List[literal] if python_type in (list, set) else literal # type: ignore
197
+ python_type = list[literal] if python_type in (list, set) else literal # type: ignore
201
198
 
202
199
  if "$ref" in json_field_definition:
203
200
  field_type_kwargs["json_schema_extra"] = {"$ref": json_field_definition["$ref"]}
@@ -210,7 +207,7 @@ def json_field_definition_to_python(
210
207
 
211
208
  def python_field_definition_to_json(
212
209
  python_field_definition: Annotated[Any, FieldInfo],
213
- ) -> Dict[str, Any]:
210
+ ) -> dict[str, Any]:
214
211
  """Get json field definition from python `typing.Annotated`
215
212
 
216
213
  >>> from pydantic import Field
@@ -231,7 +228,7 @@ def python_field_definition_to_json(
231
228
  "%s must be an instance of Annotated" % python_field_definition
232
229
  )
233
230
 
234
- json_field_definition: Dict[str, Any] = dict()
231
+ json_field_definition: dict[str, Any] = dict()
235
232
 
236
233
  python_field_args = get_args(python_field_definition)
237
234
 
@@ -311,8 +308,8 @@ def python_field_definition_to_json(
311
308
 
312
309
 
313
310
  def model_fields_to_annotated(
314
- model_fields: Dict[str, FieldInfo],
315
- ) -> Dict[str, Annotated[Any, FieldInfo]]:
311
+ model_fields: dict[str, FieldInfo],
312
+ ) -> dict[str, Annotated[Any, FieldInfo]]:
316
313
  """Convert BaseModel.model_fields from FieldInfo to Annotated
317
314
 
318
315
  >>> from pydantic import create_model
@@ -326,7 +323,7 @@ def model_fields_to_annotated(
326
323
  :param model_fields: BaseModel.model_fields to convert
327
324
  :returns: Annotated tuple usable as create_model argument
328
325
  """
329
- annotated_model_fields: Dict[str, Annotated[Any, FieldInfo]] = dict()
326
+ annotated_model_fields: dict[str, Annotated[Any, FieldInfo]] = dict()
330
327
  for param, field_info in model_fields.items():
331
328
  field_type = field_info.annotation or type(None)
332
329
  new_field_info = copy_deepcopy(field_info)
@@ -336,7 +333,7 @@ def model_fields_to_annotated(
336
333
 
337
334
 
338
335
  def annotated_dict_to_model(
339
- model_name: str, annotated_fields: Dict[str, Annotated[Any, FieldInfo]]
336
+ model_name: str, annotated_fields: dict[str, Annotated[Any, FieldInfo]]
340
337
  ) -> BaseModel:
341
338
  """Convert a dictionary of Annotated values to a Pydantic BaseModel.
342
339
 
@@ -364,5 +361,14 @@ class ProviderSortables(TypedDict):
364
361
  :param max_sort_params: (optional) The allowed maximum number of sortable(s) in a search request with the provider
365
362
  """
366
363
 
367
- sortables: List[str]
364
+ sortables: list[str]
368
365
  max_sort_params: Annotated[Optional[int], Gt(0)]
366
+
367
+
368
+ class S3SessionKwargs(TypedDict, total=False):
369
+ """A class representing available keyword arguments to pass to :class:`boto3.session.Session` for authentication"""
370
+
371
+ aws_access_key_id: Optional[str]
372
+ aws_secret_access_key: Optional[str]
373
+ aws_session_token: Optional[str]
374
+ profile_name: Optional[str]
eodag/types/bbox.py CHANGED
@@ -15,14 +15,14 @@
15
15
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
- from typing import Dict, List, Tuple, Union
18
+ from typing import Union
19
19
 
20
20
  from pydantic import BaseModel, ValidationInfo, field_validator
21
21
  from shapely.geometry.polygon import Polygon
22
22
 
23
23
  NumType = Union[float, int]
24
24
  BBoxArgs = Union[
25
- List[NumType], Tuple[NumType, NumType, NumType, NumType], Dict[str, NumType]
25
+ list[NumType], tuple[NumType, NumType, NumType, NumType], dict[str, NumType]
26
26
  ]
27
27
 
28
28
 
@@ -17,7 +17,7 @@
17
17
  # limitations under the License.
18
18
  from __future__ import annotations
19
19
 
20
- from typing import Dict, Optional, TypedDict, Union
20
+ from typing import Optional, TypedDict, Union
21
21
 
22
22
 
23
23
  class DownloadConf(TypedDict, total=False):
@@ -35,6 +35,6 @@ class DownloadConf(TypedDict, total=False):
35
35
  output_dir: str
36
36
  output_extension: Union[str, None]
37
37
  extract: bool
38
- dl_url_params: Dict[str, str]
38
+ dl_url_params: dict[str, str]
39
39
  delete_archive: bool
40
40
  asset: Optional[str]
eodag/types/queryables.py CHANGED
@@ -148,7 +148,7 @@ class Queryables(CommonQueryables):
148
148
  incidenceAngleVariation: Annotated[float, Field(None)]
149
149
 
150
150
 
151
- class QueryablesDict(UserDict):
151
+ class QueryablesDict(UserDict[str, Any]):
152
152
  """Class inheriting from UserDict which contains queryables with their annotated type;
153
153
 
154
154
  :param additional_properties: if additional properties (properties not given in EODAG config)
@@ -160,7 +160,10 @@ class QueryablesDict(UserDict):
160
160
  additional_information: str = Field("")
161
161
 
162
162
  def __init__(
163
- self, additional_properties: bool, additional_information: str = "", **kwargs
163
+ self,
164
+ additional_properties: bool = True,
165
+ additional_information: str = "",
166
+ **kwargs: Any,
164
167
  ):
165
168
  self.additional_properties = additional_properties
166
169
  self.additional_information = additional_information
@@ -17,7 +17,7 @@
17
17
  # limitations under the License.
18
18
  import re
19
19
  from datetime import datetime
20
- from typing import Annotated, Any, Dict, List, Optional, Tuple, Union, cast
20
+ from typing import Annotated, Any, Optional, Union, cast
21
21
 
22
22
  from annotated_types import MinLen
23
23
  from pydantic import BaseModel, ConfigDict, Field, conint, field_validator
@@ -31,10 +31,10 @@ from eodag.utils import DEFAULT_ITEMS_PER_PAGE, DEFAULT_PAGE
31
31
  from eodag.utils.exceptions import ValidationError
32
32
 
33
33
  NumType = Union[float, int]
34
- GeomArgs = Union[List[NumType], Tuple[NumType], Dict[str, NumType], str, BaseGeometry]
34
+ GeomArgs = Union[list[NumType], tuple[NumType], dict[str, NumType], str, BaseGeometry]
35
35
 
36
36
  PositiveInt = conint(gt=0)
37
- SortByList = Annotated[List[Tuple[str, str]], MinLen(1)]
37
+ SortByList = Annotated[list[tuple[str, str]], MinLen(1)]
38
38
 
39
39
 
40
40
  class SearchArgs(BaseModel):
@@ -48,7 +48,7 @@ class SearchArgs(BaseModel):
48
48
  start: Optional[str] = Field(None)
49
49
  end: Optional[str] = Field(None)
50
50
  geom: Optional[BaseGeometry] = Field(None)
51
- locations: Optional[Dict[str, str]] = Field(None)
51
+ locations: Optional[dict[str, str]] = Field(None)
52
52
  page: Optional[int] = Field(DEFAULT_PAGE, gt=0) # type: ignore
53
53
  items_per_page: Optional[PositiveInt] = Field(DEFAULT_ITEMS_PER_PAGE) # type: ignore
54
54
  sort_by: Optional[SortByList] = Field(None) # type: ignore
eodag/types/whoosh.py CHANGED
@@ -15,8 +15,6 @@
15
15
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
- from typing import List
19
-
20
18
  from whoosh.fields import Schema
21
19
  from whoosh.index import _DEF_INDEX_NAME, FileIndex
22
20
  from whoosh.matching import NullMatcher
@@ -52,7 +50,7 @@ class EODAGQueryParser(QueryParser):
52
50
 
53
51
  def __init__(
54
52
  self,
55
- filters: List[str],
53
+ filters: list[str],
56
54
  schema: Schema,
57
55
  ):
58
56
  """