etlplus 0.9.2__py3-none-any.whl → 0.10.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.
Files changed (120) hide show
  1. etlplus/__init__.py +26 -1
  2. etlplus/api/README.md +3 -51
  3. etlplus/api/__init__.py +0 -10
  4. etlplus/api/config.py +28 -39
  5. etlplus/api/endpoint_client.py +3 -3
  6. etlplus/api/pagination/client.py +1 -1
  7. etlplus/api/rate_limiting/config.py +1 -13
  8. etlplus/api/rate_limiting/rate_limiter.py +11 -8
  9. etlplus/api/request_manager.py +6 -11
  10. etlplus/api/transport.py +2 -14
  11. etlplus/api/types.py +6 -96
  12. etlplus/cli/commands.py +43 -76
  13. etlplus/cli/constants.py +1 -1
  14. etlplus/cli/handlers.py +12 -40
  15. etlplus/cli/io.py +2 -2
  16. etlplus/cli/main.py +1 -1
  17. etlplus/cli/state.py +7 -4
  18. etlplus/{workflow → config}/__init__.py +23 -10
  19. etlplus/{workflow → config}/connector.py +44 -58
  20. etlplus/{workflow → config}/jobs.py +32 -105
  21. etlplus/{workflow → config}/pipeline.py +51 -59
  22. etlplus/{workflow → config}/profile.py +5 -8
  23. etlplus/config/types.py +204 -0
  24. etlplus/config/utils.py +120 -0
  25. etlplus/database/ddl.py +1 -1
  26. etlplus/database/engine.py +3 -19
  27. etlplus/database/orm.py +0 -2
  28. etlplus/database/schema.py +1 -1
  29. etlplus/enums.py +266 -0
  30. etlplus/{ops/extract.py → extract.py} +99 -81
  31. etlplus/file.py +652 -0
  32. etlplus/{ops/load.py → load.py} +101 -78
  33. etlplus/{ops/run.py → run.py} +127 -159
  34. etlplus/{api/utils.py → run_helpers.py} +153 -209
  35. etlplus/{ops/transform.py → transform.py} +68 -75
  36. etlplus/types.py +4 -5
  37. etlplus/utils.py +2 -136
  38. etlplus/{ops/validate.py → validate.py} +12 -22
  39. etlplus/validation/__init__.py +44 -0
  40. etlplus/{ops → validation}/utils.py +17 -53
  41. {etlplus-0.9.2.dist-info → etlplus-0.10.1.dist-info}/METADATA +17 -210
  42. etlplus-0.10.1.dist-info/RECORD +65 -0
  43. {etlplus-0.9.2.dist-info → etlplus-0.10.1.dist-info}/WHEEL +1 -1
  44. etlplus/README.md +0 -37
  45. etlplus/api/enums.py +0 -51
  46. etlplus/cli/README.md +0 -40
  47. etlplus/database/README.md +0 -48
  48. etlplus/file/README.md +0 -105
  49. etlplus/file/__init__.py +0 -25
  50. etlplus/file/_imports.py +0 -141
  51. etlplus/file/_io.py +0 -160
  52. etlplus/file/accdb.py +0 -78
  53. etlplus/file/arrow.py +0 -78
  54. etlplus/file/avro.py +0 -176
  55. etlplus/file/bson.py +0 -77
  56. etlplus/file/cbor.py +0 -78
  57. etlplus/file/cfg.py +0 -79
  58. etlplus/file/conf.py +0 -80
  59. etlplus/file/core.py +0 -322
  60. etlplus/file/csv.py +0 -79
  61. etlplus/file/dat.py +0 -78
  62. etlplus/file/dta.py +0 -77
  63. etlplus/file/duckdb.py +0 -78
  64. etlplus/file/enums.py +0 -343
  65. etlplus/file/feather.py +0 -111
  66. etlplus/file/fwf.py +0 -77
  67. etlplus/file/gz.py +0 -123
  68. etlplus/file/hbs.py +0 -78
  69. etlplus/file/hdf5.py +0 -78
  70. etlplus/file/ini.py +0 -79
  71. etlplus/file/ion.py +0 -78
  72. etlplus/file/jinja2.py +0 -78
  73. etlplus/file/json.py +0 -98
  74. etlplus/file/log.py +0 -78
  75. etlplus/file/mat.py +0 -78
  76. etlplus/file/mdb.py +0 -78
  77. etlplus/file/msgpack.py +0 -78
  78. etlplus/file/mustache.py +0 -78
  79. etlplus/file/nc.py +0 -78
  80. etlplus/file/ndjson.py +0 -108
  81. etlplus/file/numbers.py +0 -75
  82. etlplus/file/ods.py +0 -79
  83. etlplus/file/orc.py +0 -111
  84. etlplus/file/parquet.py +0 -113
  85. etlplus/file/pb.py +0 -78
  86. etlplus/file/pbf.py +0 -77
  87. etlplus/file/properties.py +0 -78
  88. etlplus/file/proto.py +0 -77
  89. etlplus/file/psv.py +0 -79
  90. etlplus/file/rda.py +0 -78
  91. etlplus/file/rds.py +0 -78
  92. etlplus/file/sas7bdat.py +0 -78
  93. etlplus/file/sav.py +0 -77
  94. etlplus/file/sqlite.py +0 -78
  95. etlplus/file/stub.py +0 -84
  96. etlplus/file/sylk.py +0 -77
  97. etlplus/file/tab.py +0 -81
  98. etlplus/file/toml.py +0 -78
  99. etlplus/file/tsv.py +0 -80
  100. etlplus/file/txt.py +0 -102
  101. etlplus/file/vm.py +0 -78
  102. etlplus/file/wks.py +0 -77
  103. etlplus/file/xls.py +0 -88
  104. etlplus/file/xlsm.py +0 -79
  105. etlplus/file/xlsx.py +0 -99
  106. etlplus/file/xml.py +0 -185
  107. etlplus/file/xpt.py +0 -78
  108. etlplus/file/yaml.py +0 -95
  109. etlplus/file/zip.py +0 -175
  110. etlplus/file/zsav.py +0 -77
  111. etlplus/ops/README.md +0 -50
  112. etlplus/ops/__init__.py +0 -61
  113. etlplus/templates/README.md +0 -46
  114. etlplus/workflow/README.md +0 -52
  115. etlplus/workflow/dag.py +0 -105
  116. etlplus/workflow/types.py +0 -115
  117. etlplus-0.9.2.dist-info/RECORD +0 -134
  118. {etlplus-0.9.2.dist-info → etlplus-0.10.1.dist-info}/entry_points.txt +0 -0
  119. {etlplus-0.9.2.dist-info → etlplus-0.10.1.dist-info}/licenses/LICENSE +0 -0
  120. {etlplus-0.9.2.dist-info → etlplus-0.10.1.dist-info}/top_level.txt +0 -0
@@ -1,13 +1,30 @@
1
1
  """
2
- :mod:`etlplus.api.utils` module.
3
-
4
- Shared HTTP helpers for API clients that communicate with REST endpoints.
2
+ :mod:`etlplus.run_helpers` module.
3
+
4
+ Helper functions and small utilities used by ``etlplus.run`` to compose API
5
+ request/load environments, pagination configs, session objects, and endpoint
6
+ clients. Extracted to keep ``run.py`` focused on orchestration while enabling
7
+ reuse and testability.
8
+
9
+ Public (re-export safe) helpers:
10
+ - build_pagination_cfg(pagination, overrides)
11
+ - build_session(cfg)
12
+ - compose_api_request_env(cfg, source_obj, extract_opts)
13
+ - compose_api_target_env(cfg, target_obj, overrides)
14
+ - build_endpoint_client(base_url, base_path, endpoints, env)
15
+ - compute_rl_sleep_seconds(rate_limit, overrides)
16
+ - paginate_with_client(client, endpoint_key, params, headers,
17
+ timeout, pagination, sleep_seconds)
18
+
19
+ Notes
20
+ -----
21
+ These helpers intentionally accept permissive ``Any``/``Mapping`` inputs to
22
+ avoid tight coupling with config dataclasses while keeping runtime flexible.
5
23
  """
6
24
 
7
25
  from __future__ import annotations
8
26
 
9
27
  import inspect
10
- from collections.abc import Callable
11
28
  from collections.abc import Mapping
12
29
  from typing import Any
13
30
  from typing import TypedDict
@@ -15,34 +32,24 @@ from typing import cast
15
32
 
16
33
  import requests # type: ignore[import]
17
34
 
18
- from ..types import Timeout
19
- from ..utils import coerce_dict
20
- from .config import ApiConfig
21
- from .config import EndpointConfig
22
- from .endpoint_client import EndpointClient
23
- from .enums import HttpMethod
24
- from .pagination import PaginationConfig
25
- from .pagination import PaginationConfigMap
26
- from .rate_limiting import RateLimitConfig
27
- from .rate_limiting import RateLimitConfigMap
28
- from .rate_limiting import RateLimiter
29
- from .retry_manager import RetryPolicy
30
- from .types import Headers
31
- from .types import Params
32
- from .types import Url
33
-
34
- # SECTION: CONSTANTS ======================================================== #
35
-
36
-
37
- DEFAULT_TIMEOUT: float = 10.0
38
-
35
+ from .api import ApiConfig
36
+ from .api import EndpointClient
37
+ from .api import EndpointConfig
38
+ from .api import Headers
39
+ from .api import PaginationConfig
40
+ from .api import PaginationConfigMap
41
+ from .api import Params
42
+ from .api import RateLimitConfig
43
+ from .api import RateLimitConfigMap
44
+ from .api import RateLimiter
45
+ from .api import RetryPolicy
46
+ from .api import Url
47
+ from .types import Timeout
39
48
 
40
49
  # SECTION: EXPORTS ========================================================== #
41
50
 
42
51
 
43
52
  __all__ = [
44
- # Constants
45
- 'DEFAULT_TIMEOUT',
46
53
  # Functions
47
54
  'build_endpoint_client',
48
55
  'build_pagination_cfg',
@@ -51,7 +58,6 @@ __all__ = [
51
58
  'compose_api_target_env',
52
59
  'compute_rl_sleep_seconds',
53
60
  'paginate_with_client',
54
- 'resolve_request',
55
61
  # Typed Dicts
56
62
  'ApiRequestEnv',
57
63
  'ApiTargetEnv',
@@ -62,83 +68,43 @@ __all__ = [
62
68
  # SECTION: TYPED DICTS ====================================================== #
63
69
 
64
70
 
65
- class BaseApiHttpEnv(TypedDict, total=False):
66
- """
67
- Common HTTP request environment for API interactions.
68
-
69
- Fields shared by both source-side and target-side API operations.
70
- """
71
+ class ApiRequestEnv(TypedDict, total=False):
72
+ """API request environment configuration."""
71
73
 
72
- # Request details
73
74
  url: Url | None
74
75
  headers: dict[str, str]
75
76
  timeout: Timeout
76
-
77
- # Session
78
77
  session: requests.Session | None
79
-
80
-
81
- class ApiRequestEnv(BaseApiHttpEnv, total=False):
82
- """
83
- Composed HTTP request environment configuration for REST API sources.
84
-
85
- Returned by :func:`compose_api_request_env` and consumed by the API extract
86
- branch. Values are fully merged with endpoint/API defaults and job-level
87
- overrides, preserving the original precedence and behavior.
88
- """
89
-
90
- # Client
91
78
  use_endpoints: bool
92
79
  base_url: str | None
93
80
  base_path: str | None
94
81
  endpoints_map: dict[str, str] | None
95
82
  endpoint_key: str | None
96
-
97
- # Request
98
83
  params: dict[str, Any]
99
84
  pagination: PaginationConfigMap | None
100
85
  sleep_seconds: float
101
-
102
- # Reliability
103
86
  retry: RetryPolicy | None
104
87
  retry_network_errors: bool
105
88
 
106
89
 
107
- class ApiTargetEnv(BaseApiHttpEnv, total=False):
108
- """
109
- Composed HTTP request environment configuration for REST API targets.
110
-
111
- Returned by :func:`compose_api_target_env` and consumed by the API load
112
- branch. Values are merged from the target object, optional API/endpoint
113
- reference, and job-level overrides, preserving original precedence and
114
- behavior.
115
-
116
- Notes
117
- -----
118
- - Precedence for inherited values matches original logic:
119
- overrides -> target -> API profile defaults.
120
- - Target composition does not include pagination/rate-limit/retry since
121
- loads are single-request operations; only headers/timeout/session
122
- apply.
123
- """
90
+ class ApiTargetEnv(TypedDict, total=False):
91
+ """API target environment configuration."""
124
92
 
125
- # Request
93
+ url: Url | None
94
+ headers: dict[str, str]
95
+ timeout: Timeout
96
+ session: requests.Session | None
126
97
  method: str | None
127
98
 
128
99
 
129
100
  class SessionConfig(TypedDict, total=False):
130
- """
131
- Minimal session configuration schema accepted by the
132
- :class:`requests.Session` runner.
133
-
134
- Keys mirror common :class:`requests.Session` options; all are optional.
135
- """
101
+ """Configuration for requests.Session."""
136
102
 
137
103
  headers: Mapping[str, Any]
138
104
  params: Mapping[str, Any]
139
- auth: Any # (user, pass) tuple or requests-compatible auth object
105
+ auth: Any
140
106
  verify: bool | str
141
- cert: Any # str or (cert, key)
107
+ cert: Any
142
108
  proxies: Mapping[str, Any]
143
109
  cookies: Mapping[str, Any]
144
110
  trust_env: bool
@@ -147,47 +113,7 @@ class SessionConfig(TypedDict, total=False):
147
113
  # SECTION: INTERNAL FUNCTIONS ============================================== #
148
114
 
149
115
 
150
- def _build_session_optional(
151
- cfg: SessionConfig | None,
152
- ) -> requests.Session | None:
153
- """
154
- Return a configured session when *cfg* is a mapping.
155
-
156
- Parameters
157
- ----------
158
- cfg : SessionConfig | None
159
- Session configuration mapping.
160
-
161
- Returns
162
- -------
163
- requests.Session | None
164
- Configured session or ``None``.
165
- """
166
- if isinstance(cfg, Mapping):
167
- return build_session(cast(SessionConfig, cfg))
168
- return None
169
-
170
-
171
- def _coalesce(
172
- *args: Any,
173
- ) -> Any | None:
174
- """
175
- Return the first non-``None`` value from ``args``.
176
-
177
- Parameters
178
- ----------
179
- *args : Any
180
- Candidate values in descending precedence order.
181
-
182
- Returns
183
- -------
184
- Any | None
185
- The first non-``None`` value, or ``None`` if all are ``None``.
186
- """
187
- for arg in args:
188
- if arg is not None:
189
- return arg
190
- return None
116
+ # -- API Environment Composition -- #
191
117
 
192
118
 
193
119
  def _get_api_cfg_and_endpoint(
@@ -291,15 +217,37 @@ def _merge_session_cfg_three(
291
217
  api_sess = getattr(api_cfg, 'session', None)
292
218
  ep_sess = getattr(ep, 'session', None)
293
219
  merged: dict[str, Any] = {}
294
- if isinstance(api_sess, Mapping):
220
+ if isinstance(api_sess, dict):
295
221
  merged.update(api_sess)
296
- if isinstance(ep_sess, Mapping):
222
+ if isinstance(ep_sess, dict):
297
223
  merged.update(ep_sess)
298
- if isinstance(source_session_cfg, Mapping):
224
+ if isinstance(source_session_cfg, dict):
299
225
  merged.update(source_session_cfg)
300
226
  return cast(SessionConfig | None, (merged or None))
301
227
 
302
228
 
229
+ # -- Mapping Helpers -- #
230
+
231
+
232
+ def _copy_mapping(
233
+ mapping: Mapping[str, Any] | None,
234
+ ) -> dict[str, Any]:
235
+ """
236
+ Return a shallow copy of *mapping* or an empty dict.
237
+
238
+ Parameters
239
+ ----------
240
+ mapping : Mapping[str, Any] | None
241
+ The mapping to copy.
242
+
243
+ Returns
244
+ -------
245
+ dict[str, Any]
246
+ A shallow copy of the mapping or an empty dict.
247
+ """
248
+ return dict(mapping) if isinstance(mapping, Mapping) else {}
249
+
250
+
303
251
  def _update_mapping(
304
252
  target: dict[str, Any],
305
253
  extra: Mapping[str, Any] | None,
@@ -318,9 +266,37 @@ def _update_mapping(
318
266
  target.update(extra)
319
267
 
320
268
 
269
+ # -- Session -- #
270
+
271
+
272
+ def _build_session_optional(
273
+ cfg: SessionConfig | None,
274
+ ) -> requests.Session | None:
275
+ """
276
+ Return a configured session when *cfg* is a mapping.
277
+
278
+ Parameters
279
+ ----------
280
+ cfg : SessionConfig | None
281
+ Session configuration mapping.
282
+
283
+ Returns
284
+ -------
285
+ requests.Session | None
286
+ Configured session or ``None``.
287
+ """
288
+
289
+ if isinstance(cfg, dict):
290
+ return build_session(cfg)
291
+ return None
292
+
293
+
321
294
  # SECTION: FUNCTIONS ======================================================== #
322
295
 
323
296
 
297
+ # -- API Environment Composition -- #
298
+
299
+
324
300
  def build_endpoint_client(
325
301
  *,
326
302
  base_url: str,
@@ -347,7 +323,15 @@ def build_endpoint_client(
347
323
  EndpointClient
348
324
  The constructed endpoint client.
349
325
  """
350
- return EndpointClient(
326
+ # Allow tests to monkeypatch etlplus.run.EndpointClient and have it
327
+ # propagate here by preferring the class on the run module if present.
328
+ try:
329
+ from . import run as run_mod # local import to avoid cycles
330
+
331
+ ClientClass = getattr(run_mod, 'EndpointClient', EndpointClient)
332
+ except (ImportError, AttributeError): # pragma: no cover - fallback path
333
+ ClientClass = EndpointClient
334
+ return ClientClass(
351
335
  base_url=base_url,
352
336
  base_path=base_path,
353
337
  endpoints=endpoints,
@@ -385,19 +369,21 @@ def compose_api_request_env(
385
369
  Mapping[str, Any] | None,
386
370
  getattr(source_obj, 'query_params', None),
387
371
  )
388
- params: dict[str, Any] = coerce_dict(source_params)
372
+ params: dict[str, Any] = _copy_mapping(source_params)
389
373
  source_headers = cast(
390
374
  Mapping[str, str] | None,
391
375
  getattr(source_obj, 'headers', None),
392
376
  )
393
- headers: dict[str, str] = cast(dict[str, str], coerce_dict(source_headers))
377
+ headers: dict[str, str] = _copy_mapping(source_headers)
394
378
  pagination = getattr(source_obj, 'pagination', None)
395
379
  rate_limit = getattr(source_obj, 'rate_limit', None)
396
380
  retry: RetryPolicy | None = cast(
397
381
  RetryPolicy | None,
398
382
  getattr(source_obj, 'retry', None),
399
383
  )
400
- retry_network_errors = getattr(source_obj, 'retry_network_errors', None)
384
+ retry_network_errors = bool(
385
+ getattr(source_obj, 'retry_network_errors', False),
386
+ )
401
387
  session_cfg = cast(
402
388
  SessionConfig | None,
403
389
  getattr(source_obj, 'session', None),
@@ -419,33 +405,33 @@ def compose_api_request_env(
419
405
  session_cfg,
420
406
  force_url=True,
421
407
  )
422
- ep_params: dict[str, Any] = coerce_dict(
408
+ ep_params: dict[str, Any] = _copy_mapping(
423
409
  cast(Mapping[str, Any] | None, getattr(ep, 'query_params', None)),
424
410
  )
425
411
  _update_mapping(ep_params, params)
426
412
  params = ep_params
427
- pagination = _coalesce(
428
- pagination,
429
- ep.pagination,
430
- api_cfg.effective_pagination_defaults(),
413
+ pagination = (
414
+ pagination
415
+ or ep.pagination
416
+ or api_cfg.effective_pagination_defaults()
431
417
  )
432
- rate_limit = _coalesce(
433
- rate_limit,
434
- ep.rate_limit,
435
- api_cfg.effective_rate_limit_defaults(),
418
+ rate_limit = (
419
+ rate_limit
420
+ or ep.rate_limit
421
+ or api_cfg.effective_rate_limit_defaults()
436
422
  )
437
423
  retry = cast(
438
424
  RetryPolicy | None,
439
- _coalesce(
440
- retry,
441
- getattr(ep, 'retry', None),
442
- getattr(api_cfg, 'retry', None),
425
+ (
426
+ retry
427
+ or getattr(ep, 'retry', None)
428
+ or getattr(api_cfg, 'retry', None)
443
429
  ),
444
430
  )
445
- retry_network_errors = _coalesce(
446
- retry_network_errors,
447
- getattr(ep, 'retry_network_errors', None),
448
- getattr(api_cfg, 'retry_network_errors', None),
431
+ retry_network_errors = (
432
+ retry_network_errors
433
+ or bool(getattr(ep, 'retry_network_errors', False))
434
+ or bool(getattr(api_cfg, 'retry_network_errors', False))
449
435
  )
450
436
  use_client_endpoints = True
451
437
  client_base_url = api_cfg.base_url
@@ -480,10 +466,8 @@ def compose_api_request_env(
480
466
  retry = rty_ov
481
467
  if rne_ov is not None:
482
468
  retry_network_errors = bool(rne_ov)
483
- if isinstance(sess_ov, Mapping):
484
- base_cfg: dict[str, Any] = dict(
485
- cast(Mapping[str, Any], session_cfg or {}),
486
- )
469
+ if isinstance(sess_ov, dict):
470
+ base_cfg: dict[str, Any] = dict(cast(dict, session_cfg or {}))
487
471
  base_cfg.update(sess_ov)
488
472
  session_cfg = cast(SessionConfig, base_cfg)
489
473
  pag_cfg: PaginationConfigMap | None = build_pagination_cfg(
@@ -504,7 +488,7 @@ def compose_api_request_env(
504
488
  'pagination': pag_cfg,
505
489
  'sleep_seconds': sleep_s,
506
490
  'retry': retry,
507
- 'retry_network_errors': bool(retry_network_errors),
491
+ 'retry_network_errors': retry_network_errors,
508
492
  'session': sess_obj,
509
493
  }
510
494
 
@@ -540,14 +524,8 @@ def compose_api_target_env(
540
524
  str | None,
541
525
  ov.get('method') or getattr(target_obj, 'method', 'post'),
542
526
  )
543
- headers = cast(
544
- dict[str, str],
545
- coerce_dict(
546
- cast(
547
- Mapping[str, str] | None,
548
- getattr(target_obj, 'headers', None),
549
- ),
550
- ),
527
+ headers = _copy_mapping(
528
+ cast(Mapping[str, str] | None, getattr(target_obj, 'headers', None)),
551
529
  )
552
530
  _update_mapping(headers, cast(Mapping[str, str] | None, ov.get('headers')))
553
531
  timeout: Timeout = (
@@ -580,6 +558,9 @@ def compose_api_target_env(
580
558
  }
581
559
 
582
560
 
561
+ # -- Pagination -- #
562
+
563
+
583
564
  def build_pagination_cfg(
584
565
  pagination: PaginationConfig | None,
585
566
  overrides: Mapping[str, Any] | None,
@@ -686,6 +667,9 @@ def build_pagination_cfg(
686
667
  return cast(PaginationConfigMap, cfg)
687
668
 
688
669
 
670
+ # -- Pagination Invocation -- #
671
+
672
+
689
673
  def paginate_with_client(
690
674
  client: Any,
691
675
  endpoint_key: str,
@@ -743,6 +727,9 @@ def paginate_with_client(
743
727
  return client.paginate(endpoint_key, **kw_pag)
744
728
 
745
729
 
730
+ # -- Rate Limit -- #
731
+
732
+
746
733
  def compute_rl_sleep_seconds(
747
734
  rate_limit: RateLimitConfig | Mapping[str, Any] | None,
748
735
  overrides: Mapping[str, Any] | None,
@@ -795,6 +782,9 @@ def compute_rl_sleep_seconds(
795
782
  )
796
783
 
797
784
 
785
+ # -- Session -- #
786
+
787
+
798
788
  def build_session(
799
789
  cfg: SessionConfig | None,
800
790
  ) -> requests.Session:
@@ -815,12 +805,12 @@ def build_session(
815
805
  if not cfg:
816
806
  return s
817
807
  headers = cfg.get('headers')
818
- if isinstance(headers, Mapping):
808
+ if isinstance(headers, dict):
819
809
  s.headers.update(headers)
820
810
  params = cfg.get('params')
821
- if isinstance(params, Mapping):
811
+ if isinstance(params, dict):
822
812
  try:
823
- s.params = dict(params)
813
+ s.params = params
824
814
  except (AttributeError, TypeError):
825
815
  pass
826
816
  auth = cfg.get('auth')
@@ -835,12 +825,12 @@ def build_session(
835
825
  if cert is not None:
836
826
  s.cert = cert # type: ignore[assignment]
837
827
  proxies = cfg.get('proxies')
838
- if isinstance(proxies, Mapping):
828
+ if isinstance(proxies, dict):
839
829
  s.proxies.update(proxies)
840
830
  cookies = cfg.get('cookies')
841
- if isinstance(cookies, Mapping):
831
+ if isinstance(cookies, dict):
842
832
  try:
843
- s.cookies.update(cast(Mapping[str, Any], cookies))
833
+ s.cookies.update(cookies)
844
834
  except (TypeError, ValueError):
845
835
  pass
846
836
  if 'trust_env' in cfg:
@@ -851,49 +841,3 @@ def build_session(
851
841
  pass
852
842
 
853
843
  return s
854
-
855
-
856
- def resolve_request(
857
- method: HttpMethod | str,
858
- *,
859
- session: Any | None = None,
860
- timeout: Timeout = None,
861
- ) -> tuple[Callable[..., requests.Response], float, HttpMethod]:
862
- """
863
- Resolve a request callable and effective timeout for an HTTP method.
864
-
865
- Parameters
866
- ----------
867
- method : HttpMethod | str
868
- HTTP method to execute.
869
- session : Any | None, optional
870
- Requests-compatible session object. Defaults to module-level
871
- ``requests``.
872
- timeout : Timeout, optional
873
- Timeout in seconds for the request. Uses ``DEFAULT_TIMEOUT`` when
874
- omitted.
875
-
876
- Returns
877
- -------
878
- tuple[Callable[..., requests.Response], float, HttpMethod]
879
- Tuple of (callable, timeout_seconds, resolved_method).
880
-
881
- Raises
882
- ------
883
- TypeError
884
- If the session object does not expose the requested HTTP method.
885
- """
886
- http_method = HttpMethod.coerce(method)
887
- request_timeout = DEFAULT_TIMEOUT if timeout is None else timeout
888
- requester = session or requests
889
- request_callable = getattr(requester, http_method.value, None)
890
- if not callable(request_callable):
891
- raise TypeError(
892
- 'Session object must supply a callable '
893
- f'"{http_method.value}" method',
894
- )
895
- typed_request_callable = cast(
896
- Callable[..., requests.Response],
897
- request_callable,
898
- )
899
- return typed_request_callable, request_timeout, http_method