ygg 0.1.30__py3-none-any.whl → 0.1.32__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 (62) hide show
  1. {ygg-0.1.30.dist-info → ygg-0.1.32.dist-info}/METADATA +1 -1
  2. ygg-0.1.32.dist-info/RECORD +60 -0
  3. yggdrasil/__init__.py +2 -0
  4. yggdrasil/databricks/__init__.py +2 -0
  5. yggdrasil/databricks/compute/__init__.py +2 -0
  6. yggdrasil/databricks/compute/cluster.py +241 -2
  7. yggdrasil/databricks/compute/execution_context.py +100 -11
  8. yggdrasil/databricks/compute/remote.py +16 -0
  9. yggdrasil/databricks/jobs/__init__.py +5 -0
  10. yggdrasil/databricks/jobs/config.py +31 -34
  11. yggdrasil/databricks/sql/__init__.py +2 -0
  12. yggdrasil/databricks/sql/engine.py +217 -36
  13. yggdrasil/databricks/sql/exceptions.py +1 -0
  14. yggdrasil/databricks/sql/statement_result.py +148 -1
  15. yggdrasil/databricks/sql/types.py +49 -1
  16. yggdrasil/databricks/workspaces/__init__.py +4 -1
  17. yggdrasil/databricks/workspaces/filesytem.py +344 -0
  18. yggdrasil/databricks/workspaces/io.py +1123 -0
  19. yggdrasil/databricks/workspaces/path.py +1415 -0
  20. yggdrasil/databricks/workspaces/path_kind.py +13 -0
  21. yggdrasil/databricks/workspaces/workspace.py +298 -154
  22. yggdrasil/dataclasses/__init__.py +2 -0
  23. yggdrasil/dataclasses/dataclass.py +42 -1
  24. yggdrasil/libs/__init__.py +2 -0
  25. yggdrasil/libs/databrickslib.py +9 -0
  26. yggdrasil/libs/extensions/__init__.py +2 -0
  27. yggdrasil/libs/extensions/polars_extensions.py +72 -0
  28. yggdrasil/libs/extensions/spark_extensions.py +116 -0
  29. yggdrasil/libs/pandaslib.py +7 -0
  30. yggdrasil/libs/polarslib.py +7 -0
  31. yggdrasil/libs/sparklib.py +41 -0
  32. yggdrasil/pyutils/__init__.py +4 -0
  33. yggdrasil/pyutils/callable_serde.py +106 -0
  34. yggdrasil/pyutils/exceptions.py +16 -0
  35. yggdrasil/pyutils/modules.py +44 -1
  36. yggdrasil/pyutils/parallel.py +29 -0
  37. yggdrasil/pyutils/python_env.py +301 -0
  38. yggdrasil/pyutils/retry.py +57 -0
  39. yggdrasil/requests/__init__.py +4 -0
  40. yggdrasil/requests/msal.py +124 -3
  41. yggdrasil/requests/session.py +18 -0
  42. yggdrasil/types/__init__.py +2 -0
  43. yggdrasil/types/cast/__init__.py +2 -1
  44. yggdrasil/types/cast/arrow_cast.py +131 -0
  45. yggdrasil/types/cast/cast_options.py +119 -1
  46. yggdrasil/types/cast/pandas_cast.py +29 -0
  47. yggdrasil/types/cast/polars_cast.py +47 -0
  48. yggdrasil/types/cast/polars_pandas_cast.py +29 -0
  49. yggdrasil/types/cast/registry.py +176 -0
  50. yggdrasil/types/cast/spark_cast.py +76 -0
  51. yggdrasil/types/cast/spark_pandas_cast.py +29 -0
  52. yggdrasil/types/cast/spark_polars_cast.py +28 -0
  53. yggdrasil/types/libs.py +2 -0
  54. yggdrasil/types/python_arrow.py +191 -0
  55. yggdrasil/types/python_defaults.py +73 -0
  56. yggdrasil/version.py +1 -0
  57. ygg-0.1.30.dist-info/RECORD +0 -56
  58. yggdrasil/databricks/workspaces/databricks_path.py +0 -784
  59. {ygg-0.1.30.dist-info → ygg-0.1.32.dist-info}/WHEEL +0 -0
  60. {ygg-0.1.30.dist-info → ygg-0.1.32.dist-info}/entry_points.txt +0 -0
  61. {ygg-0.1.30.dist-info → ygg-0.1.32.dist-info}/licenses/LICENSE +0 -0
  62. {ygg-0.1.30.dist-info → ygg-0.1.32.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,5 @@
1
+ """Casting options for Arrow- and engine-aware conversions."""
2
+
1
3
  import dataclasses
2
4
  from typing import Optional, Union, List, Any
3
5
 
@@ -69,6 +71,22 @@ class CastOptions:
69
71
  target_field: pa.Field | pa.Schema | pa.DataType | None = None,
70
72
  **kwargs
71
73
  ):
74
+ """Build a CastOptions instance with optional source/target fields.
75
+
76
+ Args:
77
+ safe: Enable safe casting if True.
78
+ add_missing_columns: Add missing columns if True.
79
+ strict_match_names: Require exact field name matches if True.
80
+ allow_add_columns: Allow extra columns if True.
81
+ eager: Enable eager casting behavior if True.
82
+ datetime_patterns: Optional datetime parsing patterns.
83
+ source_field: Optional source Arrow field/schema/type.
84
+ target_field: Optional target Arrow field/schema/type.
85
+ **kwargs: Additional CastOptions fields.
86
+
87
+ Returns:
88
+ CastOptions instance.
89
+ """
72
90
  built = CastOptions(
73
91
  safe=safe,
74
92
  add_missing_columns=add_missing_columns,
@@ -169,6 +187,14 @@ class CastOptions:
169
187
  return result
170
188
 
171
189
  def check_source(self, obj: Any):
190
+ """Set the source field if not already configured.
191
+
192
+ Args:
193
+ obj: Source object to infer from.
194
+
195
+ Returns:
196
+ Self.
197
+ """
172
198
  if self.source_field is not None or obj is None:
173
199
  return self
174
200
 
@@ -177,6 +203,14 @@ class CastOptions:
177
203
  return self
178
204
 
179
205
  def need_arrow_type_cast(self, source_obj: Any):
206
+ """Return True when Arrow type casting is required.
207
+
208
+ Args:
209
+ source_obj: Source object to compare types against.
210
+
211
+ Returns:
212
+ True if Arrow type cast needed.
213
+ """
180
214
  if self.target_field is None:
181
215
  return False
182
216
 
@@ -185,6 +219,14 @@ class CastOptions:
185
219
  return self.source_field.type != self.target_field.type
186
220
 
187
221
  def need_polars_type_cast(self, source_obj: Any):
222
+ """Return True when Polars dtype casting is required.
223
+
224
+ Args:
225
+ source_obj: Source object to compare types against.
226
+
227
+ Returns:
228
+ True if Polars type cast needed.
229
+ """
188
230
  if self.target_polars_field is None:
189
231
  return False
190
232
 
@@ -193,6 +235,14 @@ class CastOptions:
193
235
  return self.source_polars_field.dtype != self.target_polars_field.dtype
194
236
 
195
237
  def need_spark_type_cast(self, source_obj: Any):
238
+ """Return True when Spark datatype casting is required.
239
+
240
+ Args:
241
+ source_obj: Source object to compare types against.
242
+
243
+ Returns:
244
+ True if Spark type cast needed.
245
+ """
196
246
  if self.target_spark_field is None:
197
247
  return False
198
248
 
@@ -201,6 +251,14 @@ class CastOptions:
201
251
  return self.source_spark_field.dataType != self.target_spark_field.dataType
202
252
 
203
253
  def need_nullability_check(self, source_obj: Any):
254
+ """Return True when nullability checks are required.
255
+
256
+ Args:
257
+ source_obj: Source object to compare nullability against.
258
+
259
+ Returns:
260
+ True if nullability check needed.
261
+ """
204
262
  if self.target_field is None:
205
263
  return False
206
264
 
@@ -213,6 +271,15 @@ class CastOptions:
213
271
  arrow_field: pa.Field,
214
272
  index: int
215
273
  ):
274
+ """Return a child Arrow field by index for nested types.
275
+
276
+ Args:
277
+ arrow_field: Parent Arrow field.
278
+ index: Child index.
279
+
280
+ Returns:
281
+ Child Arrow field.
282
+ """
216
283
  source_type: Union[
217
284
  pa.DataType, pa.ListType, pa.StructType, pa.MapType
218
285
  ] = arrow_field.type
@@ -235,6 +302,11 @@ class CastOptions:
235
302
 
236
303
  @property
237
304
  def source_field(self):
305
+ """Return the configured source Arrow field.
306
+
307
+ Returns:
308
+ Source Arrow field.
309
+ """
238
310
  return self.source_arrow_field
239
311
 
240
312
  @source_field.setter
@@ -248,10 +320,23 @@ class CastOptions:
248
320
  object.__setattr__(self, "source_arrow_field", value)
249
321
 
250
322
  def source_child_arrow_field(self, index: int):
323
+ """Return a child source Arrow field by index.
324
+
325
+ Args:
326
+ index: Child index.
327
+
328
+ Returns:
329
+ Child Arrow field.
330
+ """
251
331
  return self._child_arrow_field(self.source_arrow_field, index=index)
252
332
 
253
333
  @property
254
334
  def source_polars_field(self):
335
+ """Return or compute the cached Polars field for the source.
336
+
337
+ Returns:
338
+ Polars field or None.
339
+ """
255
340
  if self.source_arrow_field is not None and self._source_polars_field is None:
256
341
  from ...types.cast.polars_cast import arrow_field_to_polars_field
257
342
 
@@ -260,6 +345,11 @@ class CastOptions:
260
345
 
261
346
  @property
262
347
  def source_spark_field(self):
348
+ """Return or compute the cached Spark field for the source.
349
+
350
+ Returns:
351
+ Spark field or None.
352
+ """
263
353
  if self.source_arrow_field is not None and self._source_spark_field is None:
264
354
  from ...types.cast.spark_cast import arrow_field_to_spark_field
265
355
 
@@ -275,6 +365,11 @@ class CastOptions:
275
365
 
276
366
  @property
277
367
  def target_field_name(self):
368
+ """Return the effective target field name.
369
+
370
+ Returns:
371
+ Target field name or None.
372
+ """
278
373
  if self.target_field is None:
279
374
  if self.source_field is not None:
280
375
  return self.source_field.name
@@ -295,10 +390,23 @@ class CastOptions:
295
390
  object.__setattr__(self, "target_arrow_field", value)
296
391
 
297
392
  def target_child_arrow_field(self, index: int):
393
+ """Return a child target Arrow field by index.
394
+
395
+ Args:
396
+ index: Child index.
397
+
398
+ Returns:
399
+ Child Arrow field.
400
+ """
298
401
  return self._child_arrow_field(self.target_arrow_field, index=index)
299
402
 
300
403
  @property
301
404
  def target_polars_field(self):
405
+ """Return or compute the cached Polars field for the target.
406
+
407
+ Returns:
408
+ Polars field or None.
409
+ """
302
410
  if self.target_arrow_field is not None and self._target_polars_field is None:
303
411
  from ...types.cast.polars_cast import arrow_field_to_polars_field
304
412
 
@@ -307,6 +415,11 @@ class CastOptions:
307
415
 
308
416
  @property
309
417
  def target_spark_field(self):
418
+ """Return or compute the cached Spark field for the target.
419
+
420
+ Returns:
421
+ Spark field or None.
422
+ """
310
423
  if self.target_arrow_field is not None and self._target_spark_field is None:
311
424
  from ...types.cast.spark_cast import arrow_field_to_spark_field
312
425
 
@@ -329,6 +442,11 @@ class CastOptions:
329
442
 
330
443
  @property
331
444
  def target_spark_schema(self) -> Optional["pyspark.sql.types.StructType"]:
445
+ """Return a Spark schema view of the target Arrow schema.
446
+
447
+ Returns:
448
+ Spark StructType schema or None.
449
+ """
332
450
  arrow_schema = self.target_arrow_schema
333
451
 
334
452
  if arrow_schema is not None:
@@ -338,4 +456,4 @@ class CastOptions:
338
456
  return arrow_schema
339
457
 
340
458
 
341
- DEFAULT_INSTANCE = CastOptions()
459
+ DEFAULT_INSTANCE = CastOptions()
@@ -1,3 +1,5 @@
1
+ """Pandas <-> Arrow casting helpers and converters."""
2
+
1
3
  from typing import Optional
2
4
 
3
5
  import pyarrow as pa
@@ -33,18 +35,45 @@ if pandas is not None:
33
35
  PandasDataFrame = pandas.DataFrame
34
36
 
35
37
  def pandas_converter(*args, **kwargs):
38
+ """Return a register_converter wrapper when pandas is available.
39
+
40
+ Args:
41
+ *args: Converter registration args.
42
+ **kwargs: Converter registration kwargs.
43
+
44
+ Returns:
45
+ Converter decorator.
46
+ """
36
47
  return register_converter(*args, **kwargs)
37
48
 
38
49
  else:
39
50
  # Dummy types so annotations/decorators don't explode without pandas
40
51
  class _PandasDummy: # pragma: no cover - only used when pandas not installed
52
+ """Placeholder type for pandas symbols when pandas is unavailable."""
41
53
  pass
42
54
 
43
55
  PandasSeries = _PandasDummy
44
56
  PandasDataFrame = _PandasDummy
45
57
 
46
58
  def pandas_converter(*_args, **_kwargs): # pragma: no cover - no-op decorator
59
+ """Return a no-op decorator when pandas is unavailable.
60
+
61
+ Args:
62
+ *_args: Ignored positional args.
63
+ **_kwargs: Ignored keyword args.
64
+
65
+ Returns:
66
+ No-op decorator.
67
+ """
47
68
  def _decorator(func):
69
+ """Return the function unchanged.
70
+
71
+ Args:
72
+ func: Callable to return.
73
+
74
+ Returns:
75
+ Unchanged callable.
76
+ """
48
77
  return func
49
78
 
50
79
  return _decorator
@@ -1,3 +1,5 @@
1
+ """Polars <-> Arrow casting helpers and converters."""
2
+
1
3
  from typing import Optional, Tuple, Union, Dict, Any
2
4
 
3
5
  import pyarrow as pa
@@ -79,12 +81,22 @@ if polars is not None:
79
81
  }
80
82
 
81
83
  def polars_converter(*args, **kwargs):
84
+ """Return a register_converter wrapper when polars is available.
85
+
86
+ Args:
87
+ *args: Converter registration args.
88
+ **kwargs: Converter registration kwargs.
89
+
90
+ Returns:
91
+ Converter decorator.
92
+ """
82
93
  return register_converter(*args, **kwargs)
83
94
  else:
84
95
  ARROW_TO_POLARS = {}
85
96
 
86
97
  # Dummy types so annotations/decorators don't explode without Polars
87
98
  class _PolarsDummy: # pragma: no cover - only used when Polars not installed
99
+ """Placeholder type for polars symbols when polars is unavailable."""
88
100
  pass
89
101
 
90
102
  PolarsSeries = _PolarsDummy
@@ -95,7 +107,24 @@ else:
95
107
  PolarsDataType = _PolarsDummy
96
108
 
97
109
  def polars_converter(*_args, **_kwargs): # pragma: no cover - no-op decorator
110
+ """Return a no-op decorator when polars is unavailable.
111
+
112
+ Args:
113
+ *_args: Ignored positional args.
114
+ **_kwargs: Ignored keyword args.
115
+
116
+ Returns:
117
+ No-op decorator.
118
+ """
98
119
  def _decorator(func):
120
+ """Return the function unchanged.
121
+
122
+ Args:
123
+ func: Callable to return.
124
+
125
+ Returns:
126
+ Unchanged callable.
127
+ """
99
128
  return func
100
129
  return _decorator
101
130
 
@@ -171,6 +200,15 @@ def cast_to_list_array(
171
200
  array: PolarsSeries,
172
201
  options: Optional["CastOptions"] = None,
173
202
  ) -> PolarsSeries:
203
+ """Cast a Polars list series to a target list Arrow type.
204
+
205
+ Args:
206
+ array: Polars Series with list dtype.
207
+ options: Optional cast options.
208
+
209
+ Returns:
210
+ Casted Polars Series.
211
+ """
174
212
  options = CastOptions.check_arg(options)
175
213
 
176
214
  if not options.need_polars_type_cast(source_obj=array):
@@ -796,6 +834,15 @@ def polars_array_to_arrow_field(
796
834
  array: Union[PolarsSeries, PolarsExpr],
797
835
  options: Optional[CastOptions] = None
798
836
  ) -> pa.Field:
837
+ """Infer an Arrow field from a Polars Series or Expr.
838
+
839
+ Args:
840
+ array: Polars Series or Expr.
841
+ options: Optional cast options.
842
+
843
+ Returns:
844
+ Arrow field.
845
+ """
799
846
  options = CastOptions.check_arg(options)
800
847
 
801
848
  if options.source_arrow_field:
@@ -1,3 +1,5 @@
1
+ """Polars <-> pandas conversion helpers via Arrow."""
2
+
1
3
  from typing import Optional
2
4
 
3
5
  from .arrow_cast import CastOptions
@@ -35,18 +37,45 @@ if polars is not None and pandas is not None:
35
37
  PandasDataFrame = pandas.DataFrame
36
38
 
37
39
  def polars_pandas_converter(*args, **kwargs):
40
+ """Return a register_converter wrapper when both libs are available.
41
+
42
+ Args:
43
+ *args: Converter registration args.
44
+ **kwargs: Converter registration kwargs.
45
+
46
+ Returns:
47
+ Converter decorator.
48
+ """
38
49
  return register_converter(*args, **kwargs)
39
50
 
40
51
  else:
41
52
  # Dummy stand-ins so decorators/annotations don't explode if one lib is absent
42
53
  class _Dummy: # pragma: no cover - only used when Polars or pandas not installed
54
+ """Placeholder type when Polars or pandas are unavailable."""
43
55
  pass
44
56
 
45
57
  PolarsDataFrame = _Dummy
46
58
  PandasDataFrame = _Dummy
47
59
 
48
60
  def polars_pandas_converter(*_args, **_kwargs): # pragma: no cover - no-op decorator
61
+ """Return a no-op decorator when dependencies are missing.
62
+
63
+ Args:
64
+ *_args: Ignored positional args.
65
+ **_kwargs: Ignored keyword args.
66
+
67
+ Returns:
68
+ No-op decorator.
69
+ """
49
70
  def _decorator(func):
71
+ """Return the function unchanged.
72
+
73
+ Args:
74
+ func: Callable to return.
75
+
76
+ Returns:
77
+ Unchanged callable.
78
+ """
50
79
  return func
51
80
 
52
81
  return _decorator
@@ -1,3 +1,5 @@
1
+ """Type conversion registry and default converters."""
2
+
1
3
  from __future__ import annotations
2
4
 
3
5
  import dataclasses as _dataclasses
@@ -31,6 +33,15 @@ __all__ = [
31
33
 
32
34
 
33
35
  def _identity(x, opt):
36
+ """Return the input value unchanged.
37
+
38
+ Args:
39
+ x: Value to return.
40
+ opt: Unused options parameter.
41
+
42
+ Returns:
43
+ The input value.
44
+ """
34
45
  return x
35
46
 
36
47
  ReturnType = TypeVar("ReturnType")
@@ -49,6 +60,14 @@ def register_converter(
49
60
  """
50
61
 
51
62
  def decorator(func: Callable[..., ReturnType]) -> Converter:
63
+ """Validate and register a converter function.
64
+
65
+ Args:
66
+ func: Converter function to register.
67
+
68
+ Returns:
69
+ Registered converter.
70
+ """
52
71
  sig = inspect.signature(func)
53
72
  params = list(sig.parameters.values())
54
73
  if any(
@@ -75,6 +94,14 @@ def register_converter(
75
94
 
76
95
 
77
96
  def _unwrap_optional(hint: Any) -> Tuple[bool, Any]:
97
+ """Return whether a hint is Optional and the underlying hint.
98
+
99
+ Args:
100
+ hint: Type hint to inspect.
101
+
102
+ Returns:
103
+ Tuple of (is_optional, base_hint).
104
+ """
78
105
  origin = get_origin(hint)
79
106
  if origin in {Union, types.UnionType}:
80
107
  args = get_args(hint)
@@ -114,6 +141,15 @@ def find_converter(
114
141
  from_type: Any,
115
142
  to_hint: Any
116
143
  ) -> Optional[Converter]:
144
+ """Find a registered converter for the requested type pair.
145
+
146
+ Args:
147
+ from_type: Source type.
148
+ to_hint: Target type hint.
149
+
150
+ Returns:
151
+ Converter function or None.
152
+ """
117
153
 
118
154
  # 0) Fast path: exact key
119
155
  conv = _registry.get((from_type, to_hint))
@@ -177,6 +213,17 @@ def find_converter(
177
213
 
178
214
  # Build composite converter once we find the first viable chain.
179
215
  def composed(value, options=None, _c1=conv1, _c2=conv2):
216
+ """Compose two converters into one.
217
+
218
+ Args:
219
+ value: Value to convert.
220
+ options: Cast options.
221
+ _c1: First converter.
222
+ _c2: Second converter.
223
+
224
+ Returns:
225
+ Converted value.
226
+ """
180
227
  intermediate = _c1(value, options)
181
228
  return _c2(intermediate, options)
182
229
 
@@ -190,6 +237,14 @@ def find_converter(
190
237
 
191
238
 
192
239
  def _normalize_fractional_seconds(value: str) -> str:
240
+ """Normalize fractional seconds to microsecond precision.
241
+
242
+ Args:
243
+ value: Datetime string to normalize.
244
+
245
+ Returns:
246
+ Normalized datetime string.
247
+ """
193
248
  match = re.search(r"(\.)(\d+)(?=(?:[+-]\d{2}:?\d{2})?$)", value)
194
249
  if not match:
195
250
  return value
@@ -201,6 +256,14 @@ def _normalize_fractional_seconds(value: str) -> str:
201
256
 
202
257
 
203
258
  def is_runtime_value(x) -> bool:
259
+ """Return True when x is a runtime value, not a type hint.
260
+
261
+ Args:
262
+ x: Value or type hint to inspect.
263
+
264
+ Returns:
265
+ True if runtime value.
266
+ """
204
267
  # True for "42", [], MyClass(), etc.
205
268
  # False for MyClass, list[int], dict[str, int], etc.
206
269
  if inspect.isclass(x):
@@ -305,6 +368,16 @@ def convert_to_python_enum(
305
368
  target_hint: type,
306
369
  options: Optional[CastOptions] = None,
307
370
  ):
371
+ """Convert values into a Python Enum member.
372
+
373
+ Args:
374
+ value: Value to convert.
375
+ target_hint: Enum type.
376
+ options: Optional cast options.
377
+
378
+ Returns:
379
+ Enum member.
380
+ """
308
381
  if isinstance(value, target_hint):
309
382
  return value
310
383
 
@@ -343,6 +416,16 @@ def convert_to_python_dataclass(
343
416
  target_hint: type,
344
417
  options: Optional[CastOptions] = None,
345
418
  ):
419
+ """Convert a mapping into a dataclass instance.
420
+
421
+ Args:
422
+ value: Mapping of field values.
423
+ target_hint: Dataclass type.
424
+ options: Optional cast options.
425
+
426
+ Returns:
427
+ Dataclass instance.
428
+ """
346
429
  from yggdrasil.types.python_defaults import default_scalar
347
430
 
348
431
  if isinstance(value, target_hint):
@@ -385,6 +468,18 @@ def convert_to_python_iterable(
385
468
  target_args,
386
469
  options: Optional[CastOptions] = None,
387
470
  ):
471
+ """Convert iterable-like values into typed Python collections.
472
+
473
+ Args:
474
+ value: Iterable-like input value.
475
+ target_hint: Target type hint.
476
+ target_origin: Target container origin type.
477
+ target_args: Target type arguments.
478
+ options: Optional cast options.
479
+
480
+ Returns:
481
+ Converted iterable container.
482
+ """
388
483
  if isinstance(value, (str, bytes)):
389
484
  raise TypeError(f"No converter registered for {type(value)} -> {target_hint}")
390
485
 
@@ -411,6 +506,15 @@ def convert_to_python_iterable(
411
506
 
412
507
  @register_converter(str, int)
413
508
  def _str_to_int(value: str, cast_options: Any) -> int:
509
+ """Convert a string into an integer.
510
+
511
+ Args:
512
+ value: String to convert.
513
+ cast_options: Cast options.
514
+
515
+ Returns:
516
+ Integer value.
517
+ """
414
518
  if value == "":
415
519
  return 0
416
520
  return int(value)
@@ -418,6 +522,15 @@ def _str_to_int(value: str, cast_options: Any) -> int:
418
522
 
419
523
  @register_converter(str, float)
420
524
  def _str_to_float(value: str, cast_options: Any) -> float:
525
+ """Convert a string into a float.
526
+
527
+ Args:
528
+ value: String to convert.
529
+ cast_options: Cast options.
530
+
531
+ Returns:
532
+ Float value.
533
+ """
421
534
  default_value = getattr(cast_options, "default_value", None)
422
535
  if value == "" and default_value is not None:
423
536
  return default_value
@@ -426,6 +539,15 @@ def _str_to_float(value: str, cast_options: Any) -> float:
426
539
 
427
540
  @register_converter(str, bool)
428
541
  def _str_to_bool(value: str, cast_options: Any) -> bool:
542
+ """Convert a string into a boolean.
543
+
544
+ Args:
545
+ value: String to convert.
546
+ cast_options: Cast options.
547
+
548
+ Returns:
549
+ Boolean value.
550
+ """
429
551
  default_value = getattr(cast_options, "default_value", None)
430
552
  if value == "" and default_value is not None:
431
553
  return default_value
@@ -441,11 +563,29 @@ def _str_to_bool(value: str, cast_options: Any) -> bool:
441
563
 
442
564
  @register_converter(str, _datetime.date)
443
565
  def _str_to_date(value: str, cast_options: Any) -> _datetime.date:
566
+ """Convert a string into a date.
567
+
568
+ Args:
569
+ value: String to convert.
570
+ cast_options: Cast options.
571
+
572
+ Returns:
573
+ Date value.
574
+ """
444
575
  return _str_to_datetime(value, cast_options).date()
445
576
 
446
577
 
447
578
  @register_converter(str, _datetime.datetime)
448
579
  def _str_to_datetime(value: str, cast_options: Any) -> _datetime.datetime:
580
+ """Convert a string into a datetime.
581
+
582
+ Args:
583
+ value: String to convert.
584
+ cast_options: Cast options.
585
+
586
+ Returns:
587
+ Datetime value.
588
+ """
449
589
  default_value = getattr(cast_options, "default_value", None)
450
590
  if value == "" and default_value is not None:
451
591
  return default_value
@@ -488,6 +628,15 @@ def _str_to_datetime(value: str, cast_options: Any) -> _datetime.datetime:
488
628
 
489
629
  @register_converter(str, _datetime.timedelta)
490
630
  def _str_to_timedelta(value: str, cast_options: Any) -> _datetime.timedelta:
631
+ """Convert a string into a timedelta.
632
+
633
+ Args:
634
+ value: String to convert.
635
+ cast_options: Cast options.
636
+
637
+ Returns:
638
+ Timedelta value.
639
+ """
491
640
  default_value = getattr(cast_options, "default_value", None)
492
641
  stripped = value.strip()
493
642
 
@@ -545,6 +694,15 @@ def _str_to_timedelta(value: str, cast_options: Any) -> _datetime.timedelta:
545
694
 
546
695
  @register_converter(str, _datetime.time)
547
696
  def _str_to_time(value: str, cast_options: Any) -> _datetime.time:
697
+ """Convert a string into a time.
698
+
699
+ Args:
700
+ value: String to convert.
701
+ cast_options: Cast options.
702
+
703
+ Returns:
704
+ Time value.
705
+ """
548
706
  default_value = getattr(cast_options, "default_value", None)
549
707
  if value == "" and default_value is not None:
550
708
  return default_value
@@ -553,9 +711,27 @@ def _str_to_time(value: str, cast_options: Any) -> _datetime.time:
553
711
 
554
712
  @register_converter(_datetime.datetime, _datetime.date)
555
713
  def _datetime_to_date(value: _datetime.datetime, cast_options: Any) -> _datetime.date:
714
+ """Convert a datetime into a date.
715
+
716
+ Args:
717
+ value: Datetime value.
718
+ cast_options: Cast options.
719
+
720
+ Returns:
721
+ Date value.
722
+ """
556
723
  return value.date()
557
724
 
558
725
 
559
726
  @register_converter(int, str)
560
727
  def _int_to_str(value: int, cast_options: Any) -> str:
728
+ """Convert an integer into a string.
729
+
730
+ Args:
731
+ value: Integer to convert.
732
+ cast_options: Cast options.
733
+
734
+ Returns:
735
+ String value.
736
+ """
561
737
  return str(value)