etlplus 0.15.0__py3-none-any.whl → 0.16.6__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 (130) hide show
  1. etlplus/README.md +25 -3
  2. etlplus/__init__.py +2 -0
  3. etlplus/api/README.md +31 -0
  4. etlplus/api/__init__.py +14 -14
  5. etlplus/api/auth.py +10 -7
  6. etlplus/api/config.py +8 -13
  7. etlplus/api/endpoint_client.py +20 -20
  8. etlplus/api/errors.py +4 -4
  9. etlplus/api/pagination/__init__.py +6 -6
  10. etlplus/api/pagination/config.py +12 -10
  11. etlplus/api/pagination/paginator.py +6 -7
  12. etlplus/api/rate_limiting/__init__.py +2 -2
  13. etlplus/api/rate_limiting/config.py +14 -14
  14. etlplus/api/rate_limiting/rate_limiter.py +3 -3
  15. etlplus/api/request_manager.py +4 -4
  16. etlplus/api/retry_manager.py +8 -8
  17. etlplus/api/transport.py +11 -11
  18. etlplus/api/types.py +131 -11
  19. etlplus/api/utils.py +50 -50
  20. etlplus/cli/commands.py +93 -60
  21. etlplus/cli/constants.py +1 -1
  22. etlplus/cli/handlers.py +43 -26
  23. etlplus/cli/io.py +2 -2
  24. etlplus/cli/main.py +2 -2
  25. etlplus/cli/state.py +4 -7
  26. etlplus/{workflow/pipeline.py → config.py} +62 -99
  27. etlplus/connector/__init__.py +43 -0
  28. etlplus/connector/api.py +161 -0
  29. etlplus/connector/connector.py +26 -0
  30. etlplus/connector/core.py +132 -0
  31. etlplus/connector/database.py +122 -0
  32. etlplus/connector/enums.py +52 -0
  33. etlplus/connector/file.py +120 -0
  34. etlplus/connector/types.py +40 -0
  35. etlplus/connector/utils.py +122 -0
  36. etlplus/database/ddl.py +2 -2
  37. etlplus/database/engine.py +19 -3
  38. etlplus/database/orm.py +2 -0
  39. etlplus/enums.py +36 -200
  40. etlplus/file/_imports.py +1 -0
  41. etlplus/file/_io.py +52 -4
  42. etlplus/file/accdb.py +3 -2
  43. etlplus/file/arrow.py +3 -2
  44. etlplus/file/avro.py +3 -2
  45. etlplus/file/bson.py +3 -2
  46. etlplus/file/cbor.py +3 -2
  47. etlplus/file/cfg.py +3 -2
  48. etlplus/file/conf.py +3 -2
  49. etlplus/file/core.py +11 -8
  50. etlplus/file/csv.py +3 -2
  51. etlplus/file/dat.py +3 -2
  52. etlplus/file/dta.py +3 -2
  53. etlplus/file/duckdb.py +3 -2
  54. etlplus/file/enums.py +1 -1
  55. etlplus/file/feather.py +3 -2
  56. etlplus/file/fwf.py +3 -2
  57. etlplus/file/gz.py +3 -2
  58. etlplus/file/hbs.py +3 -2
  59. etlplus/file/hdf5.py +3 -2
  60. etlplus/file/ini.py +3 -2
  61. etlplus/file/ion.py +3 -2
  62. etlplus/file/jinja2.py +3 -2
  63. etlplus/file/json.py +5 -16
  64. etlplus/file/log.py +3 -2
  65. etlplus/file/mat.py +3 -2
  66. etlplus/file/mdb.py +3 -2
  67. etlplus/file/msgpack.py +3 -2
  68. etlplus/file/mustache.py +3 -2
  69. etlplus/file/nc.py +3 -2
  70. etlplus/file/ndjson.py +3 -2
  71. etlplus/file/numbers.py +3 -2
  72. etlplus/file/ods.py +3 -2
  73. etlplus/file/orc.py +3 -2
  74. etlplus/file/parquet.py +3 -2
  75. etlplus/file/pb.py +3 -2
  76. etlplus/file/pbf.py +3 -2
  77. etlplus/file/properties.py +3 -2
  78. etlplus/file/proto.py +3 -2
  79. etlplus/file/psv.py +3 -2
  80. etlplus/file/rda.py +3 -2
  81. etlplus/file/rds.py +3 -2
  82. etlplus/file/sas7bdat.py +3 -2
  83. etlplus/file/sav.py +3 -2
  84. etlplus/file/sqlite.py +3 -2
  85. etlplus/file/stub.py +1 -0
  86. etlplus/file/sylk.py +3 -2
  87. etlplus/file/tab.py +3 -2
  88. etlplus/file/toml.py +3 -2
  89. etlplus/file/tsv.py +3 -2
  90. etlplus/file/txt.py +4 -3
  91. etlplus/file/vm.py +3 -2
  92. etlplus/file/wks.py +3 -2
  93. etlplus/file/xls.py +3 -2
  94. etlplus/file/xlsm.py +3 -2
  95. etlplus/file/xlsx.py +3 -2
  96. etlplus/file/xml.py +9 -3
  97. etlplus/file/xpt.py +3 -2
  98. etlplus/file/yaml.py +5 -16
  99. etlplus/file/zip.py +3 -2
  100. etlplus/file/zsav.py +3 -2
  101. etlplus/ops/__init__.py +1 -0
  102. etlplus/ops/enums.py +173 -0
  103. etlplus/ops/extract.py +222 -23
  104. etlplus/ops/load.py +155 -36
  105. etlplus/ops/run.py +92 -107
  106. etlplus/ops/transform.py +48 -29
  107. etlplus/ops/types.py +147 -0
  108. etlplus/ops/utils.py +11 -40
  109. etlplus/ops/validate.py +16 -16
  110. etlplus/types.py +6 -102
  111. etlplus/utils.py +163 -29
  112. etlplus/workflow/README.md +0 -24
  113. etlplus/workflow/__init__.py +2 -15
  114. etlplus/workflow/dag.py +23 -1
  115. etlplus/workflow/jobs.py +83 -39
  116. etlplus/workflow/profile.py +4 -2
  117. {etlplus-0.15.0.dist-info → etlplus-0.16.6.dist-info}/METADATA +4 -4
  118. etlplus-0.16.6.dist-info/RECORD +143 -0
  119. {etlplus-0.15.0.dist-info → etlplus-0.16.6.dist-info}/WHEEL +1 -1
  120. etlplus/config/README.md +0 -50
  121. etlplus/config/__init__.py +0 -33
  122. etlplus/config/types.py +0 -140
  123. etlplus/dag.py +0 -103
  124. etlplus/workflow/connector.py +0 -373
  125. etlplus/workflow/types.py +0 -115
  126. etlplus/workflow/utils.py +0 -120
  127. etlplus-0.15.0.dist-info/RECORD +0 -139
  128. {etlplus-0.15.0.dist-info → etlplus-0.16.6.dist-info}/entry_points.txt +0 -0
  129. {etlplus-0.15.0.dist-info → etlplus-0.16.6.dist-info}/licenses/LICENSE +0 -0
  130. {etlplus-0.15.0.dist-info → etlplus-0.16.6.dist-info}/top_level.txt +0 -0
etlplus/enums.py CHANGED
@@ -1,18 +1,14 @@
1
1
  """
2
2
  :mod:`etlplus.enums` module.
3
3
 
4
- Shared enumeration types used across ETLPlus modules.
4
+ Shared enumeration base class.
5
5
  """
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
9
  import enum
10
- import operator as _op
11
- from statistics import fmean
12
10
  from typing import Self
13
11
 
14
- from .types import AggregateFunc
15
- from .types import OperatorFunc
16
12
  from .types import StrStrMap
17
13
 
18
14
  # SECTION: EXPORTS ========================================================== #
@@ -20,11 +16,7 @@ from .types import StrStrMap
20
16
 
21
17
  __all__ = [
22
18
  # Enums
23
- 'AggregateName',
24
19
  'CoercibleStrEnum',
25
- 'DataConnectorType',
26
- 'OperatorName',
27
- 'PipelineStep',
28
20
  ]
29
21
 
30
22
 
@@ -42,6 +34,7 @@ class CoercibleStrEnum(enum.StrEnum):
42
34
  Notes
43
35
  -----
44
36
  - Values are normalized via ``str(value).strip().casefold()``.
37
+ - If value matching fails, the raw string is tried as a member name.
45
38
  - Error messages enumerate allowed values for easier debugging.
46
39
  """
47
40
 
@@ -57,7 +50,13 @@ class CoercibleStrEnum(enum.StrEnum):
57
50
  Returns
58
51
  -------
59
52
  StrStrMap
60
- A mapping of alias names to their corresponding enum member names.
53
+ A mapping of alias strings to their corresponding enum member
54
+ values or names.
55
+
56
+ Notes
57
+ -----
58
+ - Alias keys are normalized via ``str(key).strip().casefold()``.
59
+ - Alias values should be member values or member names.
61
60
  """
62
61
  return {}
63
62
 
@@ -76,12 +75,12 @@ class CoercibleStrEnum(enum.StrEnum):
76
75
  @classmethod
77
76
  def coerce(cls, value: Self | str | object) -> Self:
78
77
  """
79
- Convert an enum member or string-like input to a member of ``cls``.
78
+ Convert an enum member or string-like input to a member of *cls*.
80
79
 
81
80
  Parameters
82
81
  ----------
83
82
  value : Self | str | object
84
- An existing enum member or a text value to normalize.
83
+ An existing enum member or a string-like value to normalize.
85
84
 
86
85
  Returns
87
86
  -------
@@ -96,10 +95,26 @@ class CoercibleStrEnum(enum.StrEnum):
96
95
  if isinstance(value, cls):
97
96
  return value
98
97
  try:
99
- normalized = str(value).strip().casefold()
100
- resolved = cls.aliases().get(normalized, normalized)
101
- return cls(resolved) # type: ignore[arg-type]
102
- except (ValueError, TypeError) as e:
98
+ raw = str(value).strip()
99
+ normalized = raw.casefold()
100
+ aliases = {
101
+ str(key).strip().casefold(): alias
102
+ for key, alias in cls.aliases().items()
103
+ }
104
+ resolved = aliases.get(normalized)
105
+ if resolved is None:
106
+ try:
107
+ return cls(normalized) # type: ignore[arg-type]
108
+ except (ValueError, TypeError):
109
+ return cls[raw] # type: ignore[index]
110
+ if isinstance(resolved, cls):
111
+ return resolved
112
+ try:
113
+ return cls(resolved) # type: ignore[arg-type]
114
+ except (ValueError, TypeError):
115
+ # Allow aliases to reference member names.
116
+ return cls[resolved] # type: ignore[index]
117
+ except (ValueError, TypeError, KeyError) as e:
103
118
  allowed = ', '.join(cls.choices())
104
119
  raise ValueError(
105
120
  f'Invalid {cls.__name__} value: {value!r}. Allowed: {allowed}',
@@ -108,15 +123,15 @@ class CoercibleStrEnum(enum.StrEnum):
108
123
  @classmethod
109
124
  def try_coerce(
110
125
  cls,
111
- value: object,
126
+ value: Self | str | object,
112
127
  ) -> Self | None:
113
128
  """
114
- Best-effort parse; return ``None`` on failure instead of raising.
129
+ Attempt to coerce a value into the enum; return ``None`` on failure.
115
130
 
116
131
  Parameters
117
132
  ----------
118
- value : object
119
- An existing enum member or a text value to normalize.
133
+ value : Self | str | object
134
+ An existing enum member or a string-like value to normalize.
120
135
 
121
136
  Returns
122
137
  -------
@@ -125,184 +140,5 @@ class CoercibleStrEnum(enum.StrEnum):
125
140
  """
126
141
  try:
127
142
  return cls.coerce(value)
128
- except ValueError:
143
+ except (ValueError, TypeError, KeyError):
129
144
  return None
130
-
131
-
132
- # SECTION: ENUMS ============================================================ #
133
-
134
-
135
- class AggregateName(CoercibleStrEnum):
136
- """Supported aggregations with helpers."""
137
-
138
- # -- Constants -- #
139
-
140
- AVG = 'avg'
141
- COUNT = 'count'
142
- MAX = 'max'
143
- MIN = 'min'
144
- SUM = 'sum'
145
-
146
- # -- Class Methods -- #
147
-
148
- @property
149
- def func(self) -> AggregateFunc:
150
- """
151
- Get the aggregation function for this aggregation type.
152
-
153
- Returns
154
- -------
155
- AggregateFunc
156
- The aggregation function corresponding to this aggregation type.
157
- """
158
- if self is AggregateName.COUNT:
159
- return lambda xs, n: n
160
- if self is AggregateName.MAX:
161
- return lambda xs, n: (max(xs) if xs else None)
162
- if self is AggregateName.MIN:
163
- return lambda xs, n: (min(xs) if xs else None)
164
- if self is AggregateName.SUM:
165
- return lambda xs, n: sum(xs)
166
-
167
- # AVG
168
- return lambda xs, n: (fmean(xs) if xs else 0.0)
169
-
170
-
171
- class DataConnectorType(CoercibleStrEnum):
172
- """Supported data connector types."""
173
-
174
- # -- Constants -- #
175
-
176
- API = 'api'
177
- DATABASE = 'database'
178
- FILE = 'file'
179
-
180
- # -- Class Methods -- #
181
-
182
- @classmethod
183
- def aliases(cls) -> StrStrMap:
184
- """
185
- Return a mapping of common aliases for each enum member.
186
-
187
- Returns
188
- -------
189
- StrStrMap
190
- A mapping of alias names to their corresponding enum member names.
191
- """
192
- return {
193
- 'http': 'api',
194
- 'https': 'api',
195
- 'rest': 'api',
196
- 'db': 'database',
197
- 'filesystem': 'file',
198
- 'fs': 'file',
199
- }
200
-
201
-
202
- class OperatorName(CoercibleStrEnum):
203
- """Supported comparison operators with helpers."""
204
-
205
- # -- Constants -- #
206
-
207
- EQ = 'eq'
208
- NE = 'ne'
209
- GT = 'gt'
210
- GTE = 'gte'
211
- LT = 'lt'
212
- LTE = 'lte'
213
- IN = 'in'
214
- CONTAINS = 'contains'
215
-
216
- # -- Getters -- #
217
-
218
- @property
219
- def func(self) -> OperatorFunc:
220
- """
221
- Get the comparison function for this operator.
222
-
223
- Returns
224
- -------
225
- OperatorFunc
226
- The comparison function corresponding to this operator.
227
- """
228
- match self:
229
- case OperatorName.EQ:
230
- return _op.eq
231
- case OperatorName.NE:
232
- return _op.ne
233
- case OperatorName.GT:
234
- return _op.gt
235
- case OperatorName.GTE:
236
- return _op.ge
237
- case OperatorName.LT:
238
- return _op.lt
239
- case OperatorName.LTE:
240
- return _op.le
241
- case OperatorName.IN:
242
- return lambda a, b: a in b
243
- case OperatorName.CONTAINS:
244
- return lambda a, b: b in a
245
-
246
- # -- Class Methods -- #
247
-
248
- @classmethod
249
- def aliases(cls) -> StrStrMap:
250
- """
251
- Return a mapping of common aliases for each enum member.
252
-
253
- Returns
254
- -------
255
- StrStrMap
256
- A mapping of alias names to their corresponding enum member names.
257
- """
258
- return {
259
- '==': 'eq',
260
- '=': 'eq',
261
- '!=': 'ne',
262
- '<>': 'ne',
263
- '>=': 'gte',
264
- '≥': 'gte',
265
- '<=': 'lte',
266
- '≤': 'lte',
267
- '>': 'gt',
268
- '<': 'lt',
269
- }
270
-
271
-
272
- class PipelineStep(CoercibleStrEnum):
273
- """Pipeline step names as an enum for internal orchestration."""
274
-
275
- # -- Constants -- #
276
-
277
- FILTER = 'filter'
278
- MAP = 'map'
279
- SELECT = 'select'
280
- SORT = 'sort'
281
- AGGREGATE = 'aggregate'
282
-
283
- # -- Getters -- #
284
-
285
- @property
286
- def order(self) -> int:
287
- """
288
- Get the execution order of this pipeline step.
289
-
290
- Returns
291
- -------
292
- int
293
- The execution order of this pipeline step.
294
- """
295
- return _PIPELINE_ORDER_INDEX[self]
296
-
297
-
298
- # SECTION: INTERNAL CONSTANTS ============================================== #
299
-
300
-
301
- # Precomputed order index for PipelineStep; avoids recomputing on each access.
302
- _PIPELINE_ORDER_INDEX: dict[PipelineStep, int] = {
303
- PipelineStep.FILTER: 0,
304
- PipelineStep.MAP: 1,
305
- PipelineStep.SELECT: 2,
306
- PipelineStep.SORT: 3,
307
- PipelineStep.AGGREGATE: 4,
308
- }
etlplus/file/_imports.py CHANGED
@@ -12,6 +12,7 @@ from typing import Any
12
12
  # SECTION: INTERNAL CONSTANTS =============================================== #
13
13
 
14
14
 
15
+ # Optional Python module support (lazy-loaded to avoid hard dependency)
15
16
  _MODULE_CACHE: dict[str, Any] = {}
16
17
 
17
18
 
etlplus/file/_io.py CHANGED
@@ -8,6 +8,7 @@ from __future__ import annotations
8
8
 
9
9
  import csv
10
10
  from pathlib import Path
11
+ from typing import Any
11
12
  from typing import cast
12
13
 
13
14
  from ..types import JSONData
@@ -17,6 +18,44 @@ from ..types import JSONList
17
18
  # SECTION: FUNCTIONS ======================================================== #
18
19
 
19
20
 
21
+ def coerce_record_payload(
22
+ payload: Any,
23
+ *,
24
+ format_name: str,
25
+ ) -> JSONData:
26
+ """
27
+ Validate that *payload* is an object or list of objects.
28
+
29
+ Parameters
30
+ ----------
31
+ payload : Any
32
+ Parsed payload to validate.
33
+ format_name : str
34
+ Human-readable format name for error messages.
35
+
36
+ Returns
37
+ -------
38
+ JSONData
39
+ *payload* when it is a dict or a list of dicts.
40
+
41
+ Raises
42
+ ------
43
+ TypeError
44
+ If the payload is not a dict or list of dicts.
45
+ """
46
+ if isinstance(payload, dict):
47
+ return cast(JSONDict, payload)
48
+ if isinstance(payload, list):
49
+ if all(isinstance(item, dict) for item in payload):
50
+ return cast(JSONList, payload)
51
+ raise TypeError(
52
+ f'{format_name} array must contain only objects (dicts)',
53
+ )
54
+ raise TypeError(
55
+ f'{format_name} root must be an object or an array of objects',
56
+ )
57
+
58
+
20
59
  def normalize_records(
21
60
  data: JSONData,
22
61
  format_name: str,
@@ -50,9 +89,13 @@ def normalize_records(
50
89
  return [cast(JSONDict, data)]
51
90
 
52
91
 
53
- def read_delimited(path: Path, *, delimiter: str) -> JSONList:
92
+ def read_delimited(
93
+ path: Path,
94
+ *,
95
+ delimiter: str,
96
+ ) -> JSONList:
54
97
  """
55
- Read delimited content from ``path``.
98
+ Read delimited content from *path*.
56
99
 
57
100
  Parameters
58
101
  ----------
@@ -79,9 +122,14 @@ def read_delimited(path: Path, *, delimiter: str) -> JSONList:
79
122
  return rows
80
123
 
81
124
 
82
- def write_delimited(path: Path, data: JSONData, *, delimiter: str) -> int:
125
+ def write_delimited(
126
+ path: Path,
127
+ data: JSONData,
128
+ *,
129
+ delimiter: str,
130
+ ) -> int:
83
131
  """
84
- Write ``data`` to a delimited file and return record count.
132
+ Write *data* to a delimited file and return record count.
85
133
 
86
134
  Parameters
87
135
  ----------
etlplus/file/accdb.py CHANGED
@@ -28,6 +28,7 @@ from . import stub
28
28
 
29
29
 
30
30
  __all__ = [
31
+ # Functions
31
32
  'read',
32
33
  'write',
33
34
  ]
@@ -40,7 +41,7 @@ def read(
40
41
  path: Path,
41
42
  ) -> JSONList:
42
43
  """
43
- Read ACCDB content from ``path``.
44
+ Read ACCDB content from *path*.
44
45
 
45
46
  Parameters
46
47
  ----------
@@ -60,7 +61,7 @@ def write(
60
61
  data: JSONData,
61
62
  ) -> int:
62
63
  """
63
- Write ``data`` to ACCDB at ``path`` and return record count.
64
+ Write *data* to ACCDB at *path* and return record count.
64
65
 
65
66
  Parameters
66
67
  ----------
etlplus/file/arrow.py CHANGED
@@ -28,6 +28,7 @@ from . import stub
28
28
 
29
29
 
30
30
  __all__ = [
31
+ # Functions
31
32
  'read',
32
33
  'write',
33
34
  ]
@@ -40,7 +41,7 @@ def read(
40
41
  path: Path,
41
42
  ) -> JSONList:
42
43
  """
43
- Read ARROW content from ``path``.
44
+ Read ARROW content from *path*.
44
45
 
45
46
  Parameters
46
47
  ----------
@@ -60,7 +61,7 @@ def write(
60
61
  data: JSONData,
61
62
  ) -> int:
62
63
  """
63
- Write ``data`` to ARROW at ``path`` and return record count.
64
+ Write *data* to ARROW at *path* and return record count.
64
65
 
65
66
  Parameters
66
67
  ----------
etlplus/file/avro.py CHANGED
@@ -33,6 +33,7 @@ from ._io import normalize_records
33
33
 
34
34
 
35
35
  __all__ = [
36
+ # Functions
36
37
  'read',
37
38
  'write',
38
39
  ]
@@ -124,7 +125,7 @@ def read(
124
125
  path: Path,
125
126
  ) -> JSONList:
126
127
  """
127
- Read AVRO content from ``path``.
128
+ Read AVRO content from *path*.
128
129
 
129
130
  Parameters
130
131
  ----------
@@ -147,7 +148,7 @@ def write(
147
148
  data: JSONData,
148
149
  ) -> int:
149
150
  """
150
- Write ``data`` to AVRO at ``path`` and return record count.
151
+ Write *data* to AVRO at *path* and return record count.
151
152
 
152
153
  Parameters
153
154
  ----------
etlplus/file/bson.py CHANGED
@@ -27,6 +27,7 @@ from . import stub
27
27
 
28
28
 
29
29
  __all__ = [
30
+ # Functions
30
31
  'read',
31
32
  'write',
32
33
  ]
@@ -39,7 +40,7 @@ def read(
39
40
  path: Path,
40
41
  ) -> JSONList:
41
42
  """
42
- Read BSON content from ``path``.
43
+ Read BSON content from *path*.
43
44
 
44
45
  Parameters
45
46
  ----------
@@ -59,7 +60,7 @@ def write(
59
60
  data: JSONData,
60
61
  ) -> int:
61
62
  """
62
- Write ``data`` to BSON at ``path`` and return record count.
63
+ Write *data* to BSON at *path* and return record count.
63
64
 
64
65
  Parameters
65
66
  ----------
etlplus/file/cbor.py CHANGED
@@ -28,6 +28,7 @@ from . import stub
28
28
 
29
29
 
30
30
  __all__ = [
31
+ # Functions
31
32
  'read',
32
33
  'write',
33
34
  ]
@@ -40,7 +41,7 @@ def read(
40
41
  path: Path,
41
42
  ) -> JSONList:
42
43
  """
43
- Read CBOR content from ``path``.
44
+ Read CBOR content from *path*.
44
45
 
45
46
  Parameters
46
47
  ----------
@@ -60,7 +61,7 @@ def write(
60
61
  data: JSONData,
61
62
  ) -> int:
62
63
  """
63
- Write ``data`` to CBOR at ``path`` and return record count.
64
+ Write *data* to CBOR at *path* and return record count.
64
65
 
65
66
  Parameters
66
67
  ----------
etlplus/file/cfg.py CHANGED
@@ -29,6 +29,7 @@ from . import stub
29
29
 
30
30
 
31
31
  __all__ = [
32
+ # Functions
32
33
  'read',
33
34
  'write',
34
35
  ]
@@ -41,7 +42,7 @@ def read(
41
42
  path: Path,
42
43
  ) -> JSONList:
43
44
  """
44
- Read CFG content from ``path``.
45
+ Read CFG content from *path*.
45
46
 
46
47
  Parameters
47
48
  ----------
@@ -61,7 +62,7 @@ def write(
61
62
  data: JSONData,
62
63
  ) -> int:
63
64
  """
64
- Write ``data`` to CFG file at ``path`` and return record count.
65
+ Write *data* to CFG file at *path* and return record count.
65
66
 
66
67
  Parameters
67
68
  ----------
etlplus/file/conf.py CHANGED
@@ -30,6 +30,7 @@ from . import stub
30
30
 
31
31
 
32
32
  __all__ = [
33
+ # Functions
33
34
  'read',
34
35
  'write',
35
36
  ]
@@ -42,7 +43,7 @@ def read(
42
43
  path: Path,
43
44
  ) -> JSONList:
44
45
  """
45
- Read CONF content from ``path``.
46
+ Read CONF content from *path*.
46
47
 
47
48
  Parameters
48
49
  ----------
@@ -62,7 +63,7 @@ def write(
62
63
  data: JSONData,
63
64
  ) -> int:
64
65
  """
65
- Write ``data`` to CONF at ``path`` and return record count.
66
+ Write *data* to CONF at *path* and return record count.
66
67
 
67
68
  Parameters
68
69
  ----------
etlplus/file/core.py CHANGED
@@ -22,7 +22,10 @@ from .enums import infer_file_format_and_compression
22
22
  # SECTION: EXPORTS ========================================================== #
23
23
 
24
24
 
25
- __all__ = ['File']
25
+ __all__ = [
26
+ # Classes
27
+ 'File',
28
+ ]
26
29
 
27
30
 
28
31
  # SECTION: INTERNAL FUNCTIONS =============================================== #
@@ -30,7 +33,7 @@ __all__ = ['File']
30
33
 
31
34
  def _accepts_root_tag(handler: object) -> bool:
32
35
  """
33
- Return True when ``handler`` supports a ``root_tag`` argument.
36
+ Return True when *handler* supports a ``root_tag`` argument.
34
37
 
35
38
  Parameters
36
39
  ----------
@@ -57,7 +60,7 @@ def _accepts_root_tag(handler: object) -> bool:
57
60
  @cache
58
61
  def _module_for_format(file_format: FileFormat) -> ModuleType:
59
62
  """
60
- Import and return the module for ``file_format``.
63
+ Import and return the module for *file_format*.
61
64
 
62
65
  Parameters
63
66
  ----------
@@ -112,8 +115,8 @@ class File:
112
115
  """
113
116
  Auto-detect and set the file format on initialization.
114
117
 
115
- If no explicit ``file_format`` is provided, attempt to infer it from
116
- the file path's extension and update :attr:`file_format`. If the
118
+ If no explicit :attr:`file_format` is provided, attempt to infer it
119
+ from the file path's extension and update :attr:`file_format`. If the
117
120
  extension is unknown, the attribute is left as ``None`` and will be
118
121
  validated later by :meth:`_ensure_format`.
119
122
  """
@@ -262,7 +265,7 @@ class File:
262
265
 
263
266
  def read(self) -> JSONData:
264
267
  """
265
- Read structured data from :attr:`path` using :attr:`file_format`.
268
+ Read structured data from :attr:path` using :attr:`file_format`.
266
269
 
267
270
  Returns
268
271
  -------
@@ -291,7 +294,7 @@ class File:
291
294
  root_tag: str = xml.DEFAULT_XML_ROOT,
292
295
  ) -> int:
293
296
  """
294
- Write ``data`` to :attr:`path` using :attr:`file_format`.
297
+ Write *data* to *path* using :attr:`file_format`.
295
298
 
296
299
  Parameters
297
300
  ----------
@@ -299,7 +302,7 @@ class File:
299
302
  Data to write to the file.
300
303
  root_tag : str, optional
301
304
  Root tag name to use when writing XML files. Defaults to
302
- ``'root'``.
305
+ ``xml.DEFAULT_XML_ROOT``.
303
306
 
304
307
  Returns
305
308
  -------
etlplus/file/csv.py CHANGED
@@ -29,6 +29,7 @@ from ._io import write_delimited
29
29
 
30
30
 
31
31
  __all__ = [
32
+ # Functions
32
33
  'read',
33
34
  'write',
34
35
  ]
@@ -41,7 +42,7 @@ def read(
41
42
  path: Path,
42
43
  ) -> JSONList:
43
44
  """
44
- Read CSV content from ``path``.
45
+ Read CSV content from *path*.
45
46
 
46
47
  Parameters
47
48
  ----------
@@ -61,7 +62,7 @@ def write(
61
62
  data: JSONData,
62
63
  ) -> int:
63
64
  """
64
- Write ``data`` to CSV at ``path`` and return record count.
65
+ Write *data* to CSV at *path* and return record count.
65
66
 
66
67
  Parameters
67
68
  ----------
etlplus/file/dat.py CHANGED
@@ -28,6 +28,7 @@ from . import stub
28
28
 
29
29
 
30
30
  __all__ = [
31
+ # Functions
31
32
  'read',
32
33
  'write',
33
34
  ]
@@ -40,7 +41,7 @@ def read(
40
41
  path: Path,
41
42
  ) -> JSONList:
42
43
  """
43
- Read DAT content from ``path``.
44
+ Read DAT content from *path*.
44
45
 
45
46
  Parameters
46
47
  ----------
@@ -60,7 +61,7 @@ def write(
60
61
  data: JSONData,
61
62
  ) -> int:
62
63
  """
63
- Write ``data`` to DAT file at ``path`` and return record count.
64
+ Write *data* to DAT file at *path* and return record count.
64
65
 
65
66
  Parameters
66
67
  ----------