etlplus 0.17.2__py3-none-any.whl → 0.17.3__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.
- etlplus/file/_imports.py +35 -20
- etlplus/file/_io.py +138 -15
- etlplus/file/_r.py +48 -0
- etlplus/file/_sql.py +224 -0
- etlplus/file/accdb.py +7 -6
- etlplus/file/arrow.py +13 -24
- etlplus/file/avro.py +13 -10
- etlplus/file/bson.py +61 -22
- etlplus/file/cbor.py +13 -25
- etlplus/file/cfg.py +7 -6
- etlplus/file/conf.py +7 -6
- etlplus/file/core.py +1 -1
- etlplus/file/csv.py +8 -7
- etlplus/file/dat.py +9 -6
- etlplus/file/dta.py +15 -30
- etlplus/file/duckdb.py +29 -122
- etlplus/file/feather.py +15 -30
- etlplus/file/fwf.py +16 -14
- etlplus/file/gz.py +12 -7
- etlplus/file/hbs.py +7 -6
- etlplus/file/hdf5.py +31 -6
- etlplus/file/ini.py +17 -24
- etlplus/file/ion.py +7 -6
- etlplus/file/jinja2.py +7 -6
- etlplus/file/json.py +10 -11
- etlplus/file/log.py +7 -6
- etlplus/file/mat.py +7 -6
- etlplus/file/mdb.py +7 -6
- etlplus/file/msgpack.py +13 -25
- etlplus/file/mustache.py +7 -6
- etlplus/file/nc.py +30 -21
- etlplus/file/ndjson.py +10 -6
- etlplus/file/numbers.py +7 -6
- etlplus/file/ods.py +10 -6
- etlplus/file/orc.py +15 -30
- etlplus/file/parquet.py +10 -6
- etlplus/file/pb.py +22 -23
- etlplus/file/pbf.py +7 -6
- etlplus/file/properties.py +15 -29
- etlplus/file/proto.py +14 -20
- etlplus/file/psv.py +8 -7
- etlplus/file/rda.py +19 -51
- etlplus/file/rds.py +19 -51
- etlplus/file/sas7bdat.py +10 -30
- etlplus/file/sav.py +13 -24
- etlplus/file/sqlite.py +25 -83
- etlplus/file/stub.py +8 -6
- etlplus/file/sylk.py +7 -6
- etlplus/file/tab.py +8 -7
- etlplus/file/toml.py +14 -17
- etlplus/file/tsv.py +8 -7
- etlplus/file/txt.py +10 -7
- etlplus/file/vm.py +7 -6
- etlplus/file/wks.py +7 -6
- etlplus/file/xls.py +8 -5
- etlplus/file/xlsm.py +10 -6
- etlplus/file/xlsx.py +10 -6
- etlplus/file/xml.py +11 -9
- etlplus/file/xpt.py +13 -33
- etlplus/file/yaml.py +10 -11
- etlplus/file/zip.py +10 -5
- etlplus/file/zsav.py +7 -6
- {etlplus-0.17.2.dist-info → etlplus-0.17.3.dist-info}/METADATA +1 -1
- {etlplus-0.17.2.dist-info → etlplus-0.17.3.dist-info}/RECORD +68 -66
- {etlplus-0.17.2.dist-info → etlplus-0.17.3.dist-info}/WHEEL +0 -0
- {etlplus-0.17.2.dist-info → etlplus-0.17.3.dist-info}/entry_points.txt +0 -0
- {etlplus-0.17.2.dist-info → etlplus-0.17.3.dist-info}/licenses/LICENSE +0 -0
- {etlplus-0.17.2.dist-info → etlplus-0.17.3.dist-info}/top_level.txt +0 -0
etlplus/file/hdf5.py
CHANGED
|
@@ -19,13 +19,14 @@ Notes
|
|
|
19
19
|
|
|
20
20
|
from __future__ import annotations
|
|
21
21
|
|
|
22
|
-
from pathlib import Path
|
|
23
22
|
from typing import cast
|
|
24
23
|
|
|
25
24
|
from ..types import JSONData
|
|
26
25
|
from ..types import JSONList
|
|
26
|
+
from ..types import StrPath
|
|
27
27
|
from . import stub
|
|
28
28
|
from ._imports import get_pandas
|
|
29
|
+
from ._io import coerce_path
|
|
29
30
|
|
|
30
31
|
# SECTION: EXPORTS ========================================================== #
|
|
31
32
|
|
|
@@ -46,7 +47,23 @@ DEFAULT_KEY = 'data'
|
|
|
46
47
|
# SECTION: INTERNAL FUNCTIONS =============================================== #
|
|
47
48
|
|
|
48
49
|
|
|
49
|
-
def _raise_tables_error(
|
|
50
|
+
def _raise_tables_error(
|
|
51
|
+
err: ImportError,
|
|
52
|
+
) -> None:
|
|
53
|
+
"""
|
|
54
|
+
Raise a consistent ImportError for missing PyTables support.
|
|
55
|
+
|
|
56
|
+
Parameters
|
|
57
|
+
----------
|
|
58
|
+
err : ImportError
|
|
59
|
+
The original ImportError raised when trying to use HDF5 support without
|
|
60
|
+
the required dependency.
|
|
61
|
+
|
|
62
|
+
Raises
|
|
63
|
+
------
|
|
64
|
+
ImportError
|
|
65
|
+
Consistent ImportError indicating that PyTables is required.
|
|
66
|
+
"""
|
|
50
67
|
raise ImportError(
|
|
51
68
|
'HDF5 support requires optional dependency "tables".\n'
|
|
52
69
|
'Install with: pip install tables',
|
|
@@ -57,21 +74,28 @@ def _raise_tables_error(err: ImportError) -> None:
|
|
|
57
74
|
|
|
58
75
|
|
|
59
76
|
def read(
|
|
60
|
-
path:
|
|
77
|
+
path: StrPath,
|
|
61
78
|
) -> JSONList:
|
|
62
79
|
"""
|
|
63
80
|
Read HDF5 content from *path*.
|
|
64
81
|
|
|
65
82
|
Parameters
|
|
66
83
|
----------
|
|
67
|
-
path :
|
|
84
|
+
path : StrPath
|
|
68
85
|
Path to the HDF5 file on disk.
|
|
69
86
|
|
|
70
87
|
Returns
|
|
71
88
|
-------
|
|
72
89
|
JSONList
|
|
73
90
|
The list of dictionaries read from the HDF5 file.
|
|
91
|
+
|
|
92
|
+
Raises
|
|
93
|
+
------
|
|
94
|
+
ValueError
|
|
95
|
+
If multiple datasets are found in the HDF5 file without a clear key to
|
|
96
|
+
use.
|
|
74
97
|
"""
|
|
98
|
+
path = coerce_path(path)
|
|
75
99
|
pandas = get_pandas('HDF5')
|
|
76
100
|
try:
|
|
77
101
|
store = pandas.HDFStore(path)
|
|
@@ -96,7 +120,7 @@ def read(
|
|
|
96
120
|
|
|
97
121
|
|
|
98
122
|
def write(
|
|
99
|
-
path:
|
|
123
|
+
path: StrPath,
|
|
100
124
|
data: JSONData,
|
|
101
125
|
) -> int:
|
|
102
126
|
"""
|
|
@@ -104,7 +128,7 @@ def write(
|
|
|
104
128
|
|
|
105
129
|
Parameters
|
|
106
130
|
----------
|
|
107
|
-
path :
|
|
131
|
+
path : StrPath
|
|
108
132
|
Path to the HDF5 file on disk.
|
|
109
133
|
data : JSONData
|
|
110
134
|
Data to write as HDF5 file. Should be a list of dictionaries or a
|
|
@@ -115,4 +139,5 @@ def write(
|
|
|
115
139
|
int
|
|
116
140
|
The number of rows written to the HDF5 file.
|
|
117
141
|
"""
|
|
142
|
+
path = coerce_path(path)
|
|
118
143
|
return stub.write(path, data, format_name='HDF5')
|
etlplus/file/ini.py
CHANGED
|
@@ -20,11 +20,14 @@ Notes
|
|
|
20
20
|
from __future__ import annotations
|
|
21
21
|
|
|
22
22
|
import configparser
|
|
23
|
-
from pathlib import Path
|
|
24
|
-
from typing import Any
|
|
25
23
|
|
|
26
24
|
from ..types import JSONData
|
|
27
25
|
from ..types import JSONDict
|
|
26
|
+
from ..types import StrPath
|
|
27
|
+
from ._io import coerce_path
|
|
28
|
+
from ._io import ensure_parent_dir
|
|
29
|
+
from ._io import require_dict_payload
|
|
30
|
+
from ._io import stringify_value
|
|
28
31
|
|
|
29
32
|
# SECTION: EXPORTS ========================================================== #
|
|
30
33
|
|
|
@@ -36,28 +39,18 @@ __all__ = [
|
|
|
36
39
|
]
|
|
37
40
|
|
|
38
41
|
|
|
39
|
-
# SECTION: INTERNAL FUNCTIONS =============================================== #
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def _stringify(value: Any) -> str:
|
|
43
|
-
"""Normalize INI values into strings."""
|
|
44
|
-
if value is None:
|
|
45
|
-
return ''
|
|
46
|
-
return str(value)
|
|
47
|
-
|
|
48
|
-
|
|
49
42
|
# SECTION: FUNCTIONS ======================================================== #
|
|
50
43
|
|
|
51
44
|
|
|
52
45
|
def read(
|
|
53
|
-
path:
|
|
46
|
+
path: StrPath,
|
|
54
47
|
) -> JSONData:
|
|
55
48
|
"""
|
|
56
49
|
Read INI content from *path*.
|
|
57
50
|
|
|
58
51
|
Parameters
|
|
59
52
|
----------
|
|
60
|
-
path :
|
|
53
|
+
path : StrPath
|
|
61
54
|
Path to the INI file on disk.
|
|
62
55
|
|
|
63
56
|
Returns
|
|
@@ -65,6 +58,7 @@ def read(
|
|
|
65
58
|
JSONData
|
|
66
59
|
The structured data read from the INI file.
|
|
67
60
|
"""
|
|
61
|
+
path = coerce_path(path)
|
|
68
62
|
parser = configparser.ConfigParser()
|
|
69
63
|
parser.read(path, encoding='utf-8')
|
|
70
64
|
|
|
@@ -81,7 +75,7 @@ def read(
|
|
|
81
75
|
|
|
82
76
|
|
|
83
77
|
def write(
|
|
84
|
-
path:
|
|
78
|
+
path: StrPath,
|
|
85
79
|
data: JSONData,
|
|
86
80
|
) -> int:
|
|
87
81
|
"""
|
|
@@ -89,7 +83,7 @@ def write(
|
|
|
89
83
|
|
|
90
84
|
Parameters
|
|
91
85
|
----------
|
|
92
|
-
path :
|
|
86
|
+
path : StrPath
|
|
93
87
|
Path to the INI file on disk.
|
|
94
88
|
data : JSONData
|
|
95
89
|
Data to write as INI. Should be a dictionary.
|
|
@@ -104,17 +98,16 @@ def write(
|
|
|
104
98
|
TypeError
|
|
105
99
|
If *data* is not a dictionary.
|
|
106
100
|
"""
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if not isinstance(data, dict):
|
|
110
|
-
raise TypeError('INI payloads must be a dict')
|
|
101
|
+
path = coerce_path(path)
|
|
102
|
+
payload = require_dict_payload(data, format_name='INI')
|
|
111
103
|
|
|
112
104
|
parser = configparser.ConfigParser()
|
|
113
|
-
for section, values in
|
|
105
|
+
for section, values in payload.items():
|
|
114
106
|
if section == 'DEFAULT':
|
|
115
107
|
if isinstance(values, dict):
|
|
116
108
|
parser['DEFAULT'] = {
|
|
117
|
-
key:
|
|
109
|
+
key: stringify_value(value)
|
|
110
|
+
for key, value in values.items()
|
|
118
111
|
}
|
|
119
112
|
else:
|
|
120
113
|
raise TypeError('INI DEFAULT section must be a dict')
|
|
@@ -122,10 +115,10 @@ def write(
|
|
|
122
115
|
if not isinstance(values, dict):
|
|
123
116
|
raise TypeError('INI sections must map to dicts')
|
|
124
117
|
parser[section] = {
|
|
125
|
-
key:
|
|
118
|
+
key: stringify_value(value) for key, value in values.items()
|
|
126
119
|
}
|
|
127
120
|
|
|
128
|
-
path
|
|
121
|
+
ensure_parent_dir(path)
|
|
129
122
|
with path.open('w', encoding='utf-8', newline='') as handle:
|
|
130
123
|
parser.write(handle)
|
|
131
124
|
return 1
|
etlplus/file/ion.py
CHANGED
|
@@ -18,11 +18,11 @@ Notes
|
|
|
18
18
|
|
|
19
19
|
from __future__ import annotations
|
|
20
20
|
|
|
21
|
-
from pathlib import Path
|
|
22
|
-
|
|
23
21
|
from ..types import JSONData
|
|
24
22
|
from ..types import JSONList
|
|
23
|
+
from ..types import StrPath
|
|
25
24
|
from . import stub
|
|
25
|
+
from ._io import coerce_path
|
|
26
26
|
|
|
27
27
|
# SECTION: EXPORTS ========================================================== #
|
|
28
28
|
|
|
@@ -38,14 +38,14 @@ __all__ = [
|
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
def read(
|
|
41
|
-
path:
|
|
41
|
+
path: StrPath,
|
|
42
42
|
) -> JSONList:
|
|
43
43
|
"""
|
|
44
44
|
Read ION content from *path*.
|
|
45
45
|
|
|
46
46
|
Parameters
|
|
47
47
|
----------
|
|
48
|
-
path :
|
|
48
|
+
path : StrPath
|
|
49
49
|
Path to the ION file on disk.
|
|
50
50
|
|
|
51
51
|
Returns
|
|
@@ -57,7 +57,7 @@ def read(
|
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
def write(
|
|
60
|
-
path:
|
|
60
|
+
path: StrPath,
|
|
61
61
|
data: JSONData,
|
|
62
62
|
) -> int:
|
|
63
63
|
"""
|
|
@@ -65,7 +65,7 @@ def write(
|
|
|
65
65
|
|
|
66
66
|
Parameters
|
|
67
67
|
----------
|
|
68
|
-
path :
|
|
68
|
+
path : StrPath
|
|
69
69
|
Path to the ION file on disk.
|
|
70
70
|
data : JSONData
|
|
71
71
|
Data to write as ION. Should be a list of dictionaries or a
|
|
@@ -76,4 +76,5 @@ def write(
|
|
|
76
76
|
int
|
|
77
77
|
The number of rows written to the ION file.
|
|
78
78
|
"""
|
|
79
|
+
path = coerce_path(path)
|
|
79
80
|
return stub.write(path, data, format_name='ION')
|
etlplus/file/jinja2.py
CHANGED
|
@@ -19,11 +19,11 @@ Notes
|
|
|
19
19
|
|
|
20
20
|
from __future__ import annotations
|
|
21
21
|
|
|
22
|
-
from pathlib import Path
|
|
23
|
-
|
|
24
22
|
from ..types import JSONData
|
|
25
23
|
from ..types import JSONList
|
|
24
|
+
from ..types import StrPath
|
|
26
25
|
from . import stub
|
|
26
|
+
from ._io import coerce_path
|
|
27
27
|
|
|
28
28
|
# SECTION: EXPORTS ========================================================== #
|
|
29
29
|
|
|
@@ -39,14 +39,14 @@ __all__ = [
|
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
def read(
|
|
42
|
-
path:
|
|
42
|
+
path: StrPath,
|
|
43
43
|
) -> JSONList:
|
|
44
44
|
"""
|
|
45
45
|
Read JINJA2 content from *path*.
|
|
46
46
|
|
|
47
47
|
Parameters
|
|
48
48
|
----------
|
|
49
|
-
path :
|
|
49
|
+
path : StrPath
|
|
50
50
|
Path to the JINJA2 file on disk.
|
|
51
51
|
|
|
52
52
|
Returns
|
|
@@ -58,7 +58,7 @@ def read(
|
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
def write(
|
|
61
|
-
path:
|
|
61
|
+
path: StrPath,
|
|
62
62
|
data: JSONData,
|
|
63
63
|
) -> int:
|
|
64
64
|
"""
|
|
@@ -66,7 +66,7 @@ def write(
|
|
|
66
66
|
|
|
67
67
|
Parameters
|
|
68
68
|
----------
|
|
69
|
-
path :
|
|
69
|
+
path : StrPath
|
|
70
70
|
Path to the JINJA2 file on disk.
|
|
71
71
|
data : JSONData
|
|
72
72
|
Data to write as JINJA2 file. Should be a list of dictionaries or a
|
|
@@ -77,4 +77,5 @@ def write(
|
|
|
77
77
|
int
|
|
78
78
|
The number of rows written to the JINJA2 file.
|
|
79
79
|
"""
|
|
80
|
+
path = coerce_path(path)
|
|
80
81
|
return stub.write(path, data, format_name='JINJA2')
|
etlplus/file/json.py
CHANGED
|
@@ -19,11 +19,13 @@ Notes
|
|
|
19
19
|
from __future__ import annotations
|
|
20
20
|
|
|
21
21
|
import json
|
|
22
|
-
from pathlib import Path
|
|
23
22
|
|
|
24
23
|
from ..types import JSONData
|
|
24
|
+
from ..types import StrPath
|
|
25
25
|
from ..utils import count_records
|
|
26
|
+
from ._io import coerce_path
|
|
26
27
|
from ._io import coerce_record_payload
|
|
28
|
+
from ._io import ensure_parent_dir
|
|
27
29
|
|
|
28
30
|
# SECTION: EXPORTS ========================================================== #
|
|
29
31
|
|
|
@@ -39,7 +41,7 @@ __all__ = [
|
|
|
39
41
|
|
|
40
42
|
|
|
41
43
|
def read(
|
|
42
|
-
path:
|
|
44
|
+
path: StrPath,
|
|
43
45
|
) -> JSONData:
|
|
44
46
|
"""
|
|
45
47
|
Read JSON content from *path*.
|
|
@@ -48,19 +50,15 @@ def read(
|
|
|
48
50
|
|
|
49
51
|
Parameters
|
|
50
52
|
----------
|
|
51
|
-
path :
|
|
53
|
+
path : StrPath
|
|
52
54
|
Path to the JSON file on disk.
|
|
53
55
|
|
|
54
56
|
Returns
|
|
55
57
|
-------
|
|
56
58
|
JSONData
|
|
57
59
|
The structured data read from the JSON file.
|
|
58
|
-
|
|
59
|
-
Raises
|
|
60
|
-
------
|
|
61
|
-
TypeError
|
|
62
|
-
If the JSON root is not an object or an array of objects.
|
|
63
60
|
"""
|
|
61
|
+
path = coerce_path(path)
|
|
64
62
|
with path.open('r', encoding='utf-8') as handle:
|
|
65
63
|
loaded = json.load(handle)
|
|
66
64
|
|
|
@@ -68,7 +66,7 @@ def read(
|
|
|
68
66
|
|
|
69
67
|
|
|
70
68
|
def write(
|
|
71
|
-
path:
|
|
69
|
+
path: StrPath,
|
|
72
70
|
data: JSONData,
|
|
73
71
|
) -> int:
|
|
74
72
|
"""
|
|
@@ -76,7 +74,7 @@ def write(
|
|
|
76
74
|
|
|
77
75
|
Parameters
|
|
78
76
|
----------
|
|
79
|
-
path :
|
|
77
|
+
path : StrPath
|
|
80
78
|
Path to the JSON file on disk.
|
|
81
79
|
data : JSONData
|
|
82
80
|
Data to serialize as JSON.
|
|
@@ -86,7 +84,8 @@ def write(
|
|
|
86
84
|
int
|
|
87
85
|
The number of records written to the JSON file.
|
|
88
86
|
"""
|
|
89
|
-
path
|
|
87
|
+
path = coerce_path(path)
|
|
88
|
+
ensure_parent_dir(path)
|
|
90
89
|
with path.open('w', encoding='utf-8') as handle:
|
|
91
90
|
json.dump(
|
|
92
91
|
data,
|
etlplus/file/log.py
CHANGED
|
@@ -18,11 +18,11 @@ Notes
|
|
|
18
18
|
|
|
19
19
|
from __future__ import annotations
|
|
20
20
|
|
|
21
|
-
from pathlib import Path
|
|
22
|
-
|
|
23
21
|
from ..types import JSONData
|
|
24
22
|
from ..types import JSONList
|
|
23
|
+
from ..types import StrPath
|
|
25
24
|
from . import stub
|
|
25
|
+
from ._io import coerce_path
|
|
26
26
|
|
|
27
27
|
# SECTION: EXPORTS ========================================================== #
|
|
28
28
|
|
|
@@ -38,14 +38,14 @@ __all__ = [
|
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
def read(
|
|
41
|
-
path:
|
|
41
|
+
path: StrPath,
|
|
42
42
|
) -> JSONList:
|
|
43
43
|
"""
|
|
44
44
|
Read LOG content from *path*.
|
|
45
45
|
|
|
46
46
|
Parameters
|
|
47
47
|
----------
|
|
48
|
-
path :
|
|
48
|
+
path : StrPath
|
|
49
49
|
Path to the LOG file on disk.
|
|
50
50
|
|
|
51
51
|
Returns
|
|
@@ -57,7 +57,7 @@ def read(
|
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
def write(
|
|
60
|
-
path:
|
|
60
|
+
path: StrPath,
|
|
61
61
|
data: JSONData,
|
|
62
62
|
) -> int:
|
|
63
63
|
"""
|
|
@@ -65,7 +65,7 @@ def write(
|
|
|
65
65
|
|
|
66
66
|
Parameters
|
|
67
67
|
----------
|
|
68
|
-
path :
|
|
68
|
+
path : StrPath
|
|
69
69
|
Path to the LOG file on disk.
|
|
70
70
|
data : JSONData
|
|
71
71
|
Data to write as LOG. Should be a list of dictionaries or a
|
|
@@ -76,4 +76,5 @@ def write(
|
|
|
76
76
|
int
|
|
77
77
|
The number of rows written to the LOG file.
|
|
78
78
|
"""
|
|
79
|
+
path = coerce_path(path)
|
|
79
80
|
return stub.write(path, data, format_name='LOG')
|
etlplus/file/mat.py
CHANGED
|
@@ -18,11 +18,11 @@ Notes
|
|
|
18
18
|
|
|
19
19
|
from __future__ import annotations
|
|
20
20
|
|
|
21
|
-
from pathlib import Path
|
|
22
|
-
|
|
23
21
|
from ..types import JSONData
|
|
24
22
|
from ..types import JSONList
|
|
23
|
+
from ..types import StrPath
|
|
25
24
|
from . import stub
|
|
25
|
+
from ._io import coerce_path
|
|
26
26
|
|
|
27
27
|
# SECTION: EXPORTS ========================================================== #
|
|
28
28
|
|
|
@@ -38,14 +38,14 @@ __all__ = [
|
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
def read(
|
|
41
|
-
path:
|
|
41
|
+
path: StrPath,
|
|
42
42
|
) -> JSONList:
|
|
43
43
|
"""
|
|
44
44
|
Read MAT content from *path*.
|
|
45
45
|
|
|
46
46
|
Parameters
|
|
47
47
|
----------
|
|
48
|
-
path :
|
|
48
|
+
path : StrPath
|
|
49
49
|
Path to the MAT file on disk.
|
|
50
50
|
|
|
51
51
|
Returns
|
|
@@ -57,7 +57,7 @@ def read(
|
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
def write(
|
|
60
|
-
path:
|
|
60
|
+
path: StrPath,
|
|
61
61
|
data: JSONData,
|
|
62
62
|
) -> int:
|
|
63
63
|
"""
|
|
@@ -65,7 +65,7 @@ def write(
|
|
|
65
65
|
|
|
66
66
|
Parameters
|
|
67
67
|
----------
|
|
68
|
-
path :
|
|
68
|
+
path : StrPath
|
|
69
69
|
Path to the MAT file on disk.
|
|
70
70
|
data : JSONData
|
|
71
71
|
Data to write as MAT file. Should be a list of dictionaries or a
|
|
@@ -76,4 +76,5 @@ def write(
|
|
|
76
76
|
int
|
|
77
77
|
The number of rows written to the MAT file.
|
|
78
78
|
"""
|
|
79
|
+
path = coerce_path(path)
|
|
79
80
|
return stub.write(path, data, format_name='MAT')
|
etlplus/file/mdb.py
CHANGED
|
@@ -19,11 +19,11 @@ Notes
|
|
|
19
19
|
|
|
20
20
|
from __future__ import annotations
|
|
21
21
|
|
|
22
|
-
from pathlib import Path
|
|
23
|
-
|
|
24
22
|
from ..types import JSONData
|
|
25
23
|
from ..types import JSONList
|
|
24
|
+
from ..types import StrPath
|
|
26
25
|
from . import stub
|
|
26
|
+
from ._io import coerce_path
|
|
27
27
|
|
|
28
28
|
# SECTION: EXPORTS ========================================================== #
|
|
29
29
|
|
|
@@ -39,14 +39,14 @@ __all__ = [
|
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
def read(
|
|
42
|
-
path:
|
|
42
|
+
path: StrPath,
|
|
43
43
|
) -> JSONList:
|
|
44
44
|
"""
|
|
45
45
|
Read CSV content from *path*.
|
|
46
46
|
|
|
47
47
|
Parameters
|
|
48
48
|
----------
|
|
49
|
-
path :
|
|
49
|
+
path : StrPath
|
|
50
50
|
Path to the CSV file on disk.
|
|
51
51
|
|
|
52
52
|
Returns
|
|
@@ -58,7 +58,7 @@ def read(
|
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
def write(
|
|
61
|
-
path:
|
|
61
|
+
path: StrPath,
|
|
62
62
|
data: JSONData,
|
|
63
63
|
) -> int:
|
|
64
64
|
"""
|
|
@@ -66,7 +66,7 @@ def write(
|
|
|
66
66
|
|
|
67
67
|
Parameters
|
|
68
68
|
----------
|
|
69
|
-
path :
|
|
69
|
+
path : StrPath
|
|
70
70
|
Path to the CSV file on disk.
|
|
71
71
|
data : JSONData
|
|
72
72
|
Data to write as CSV. Should be a list of dictionaries or a
|
|
@@ -77,4 +77,5 @@ def write(
|
|
|
77
77
|
int
|
|
78
78
|
The number of rows written to the CSV file.
|
|
79
79
|
"""
|
|
80
|
+
path = coerce_path(path)
|
|
80
81
|
return stub.write(path, data, format_name='DAT')
|
etlplus/file/msgpack.py
CHANGED
|
@@ -18,12 +18,12 @@ Notes
|
|
|
18
18
|
|
|
19
19
|
from __future__ import annotations
|
|
20
20
|
|
|
21
|
-
from pathlib import Path
|
|
22
|
-
from typing import Any
|
|
23
|
-
|
|
24
21
|
from ..types import JSONData
|
|
25
|
-
from
|
|
22
|
+
from ..types import StrPath
|
|
23
|
+
from ._imports import get_dependency
|
|
24
|
+
from ._io import coerce_path
|
|
26
25
|
from ._io import coerce_record_payload
|
|
26
|
+
from ._io import ensure_parent_dir
|
|
27
27
|
from ._io import normalize_records
|
|
28
28
|
|
|
29
29
|
# SECTION: EXPORTS ========================================================== #
|
|
@@ -36,32 +36,18 @@ __all__ = [
|
|
|
36
36
|
]
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
# SECTION: INTERNAL FUNCTIONS =============================================== #
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def _get_msgpack() -> Any:
|
|
43
|
-
"""Return the msgpack module, importing it on first use."""
|
|
44
|
-
return get_optional_module(
|
|
45
|
-
'msgpack',
|
|
46
|
-
error_message=(
|
|
47
|
-
'MSGPACK support requires optional dependency "msgpack".\n'
|
|
48
|
-
'Install with: pip install msgpack'
|
|
49
|
-
),
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
|
|
53
39
|
# SECTION: FUNCTIONS ======================================================== #
|
|
54
40
|
|
|
55
41
|
|
|
56
42
|
def read(
|
|
57
|
-
path:
|
|
43
|
+
path: StrPath,
|
|
58
44
|
) -> JSONData:
|
|
59
45
|
"""
|
|
60
46
|
Read MsgPack content from *path*.
|
|
61
47
|
|
|
62
48
|
Parameters
|
|
63
49
|
----------
|
|
64
|
-
path :
|
|
50
|
+
path : StrPath
|
|
65
51
|
Path to the MsgPack file on disk.
|
|
66
52
|
|
|
67
53
|
Returns
|
|
@@ -69,14 +55,15 @@ def read(
|
|
|
69
55
|
JSONData
|
|
70
56
|
The structured data read from the MsgPack file.
|
|
71
57
|
"""
|
|
72
|
-
|
|
58
|
+
path = coerce_path(path)
|
|
59
|
+
msgpack = get_dependency('msgpack', format_name='MSGPACK')
|
|
73
60
|
with path.open('rb') as handle:
|
|
74
61
|
payload = msgpack.unpackb(handle.read(), raw=False)
|
|
75
62
|
return coerce_record_payload(payload, format_name='MSGPACK')
|
|
76
63
|
|
|
77
64
|
|
|
78
65
|
def write(
|
|
79
|
-
path:
|
|
66
|
+
path: StrPath,
|
|
80
67
|
data: JSONData,
|
|
81
68
|
) -> int:
|
|
82
69
|
"""
|
|
@@ -84,7 +71,7 @@ def write(
|
|
|
84
71
|
|
|
85
72
|
Parameters
|
|
86
73
|
----------
|
|
87
|
-
path :
|
|
74
|
+
path : StrPath
|
|
88
75
|
Path to the MsgPack file on disk.
|
|
89
76
|
data : JSONData
|
|
90
77
|
Data to write as MsgPack. Should be a list of dictionaries or a
|
|
@@ -95,10 +82,11 @@ def write(
|
|
|
95
82
|
int
|
|
96
83
|
The number of rows written to the MsgPack file.
|
|
97
84
|
"""
|
|
98
|
-
|
|
85
|
+
path = coerce_path(path)
|
|
86
|
+
msgpack = get_dependency('msgpack', format_name='MSGPACK')
|
|
99
87
|
records = normalize_records(data, 'MSGPACK')
|
|
100
88
|
payload: JSONData = records if isinstance(data, list) else records[0]
|
|
101
|
-
path
|
|
89
|
+
ensure_parent_dir(path)
|
|
102
90
|
with path.open('wb') as handle:
|
|
103
91
|
handle.write(msgpack.packb(payload, use_bin_type=True))
|
|
104
92
|
return len(records)
|
etlplus/file/mustache.py
CHANGED
|
@@ -19,11 +19,11 @@ Notes
|
|
|
19
19
|
|
|
20
20
|
from __future__ import annotations
|
|
21
21
|
|
|
22
|
-
from pathlib import Path
|
|
23
|
-
|
|
24
22
|
from ..types import JSONData
|
|
25
23
|
from ..types import JSONList
|
|
24
|
+
from ..types import StrPath
|
|
26
25
|
from . import stub
|
|
26
|
+
from ._io import coerce_path
|
|
27
27
|
|
|
28
28
|
# SECTION: EXPORTS ========================================================== #
|
|
29
29
|
|
|
@@ -39,14 +39,14 @@ __all__ = [
|
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
def read(
|
|
42
|
-
path:
|
|
42
|
+
path: StrPath,
|
|
43
43
|
) -> JSONList:
|
|
44
44
|
"""
|
|
45
45
|
Read MUSTACHE content from *path*.
|
|
46
46
|
|
|
47
47
|
Parameters
|
|
48
48
|
----------
|
|
49
|
-
path :
|
|
49
|
+
path : StrPath
|
|
50
50
|
Path to the MUSTACHE file on disk.
|
|
51
51
|
|
|
52
52
|
Returns
|
|
@@ -58,7 +58,7 @@ def read(
|
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
def write(
|
|
61
|
-
path:
|
|
61
|
+
path: StrPath,
|
|
62
62
|
data: JSONData,
|
|
63
63
|
) -> int:
|
|
64
64
|
"""
|
|
@@ -66,7 +66,7 @@ def write(
|
|
|
66
66
|
|
|
67
67
|
Parameters
|
|
68
68
|
----------
|
|
69
|
-
path :
|
|
69
|
+
path : StrPath
|
|
70
70
|
Path to the MUSTACHE file on disk.
|
|
71
71
|
data : JSONData
|
|
72
72
|
Data to write as MUSTACHE file. Should be a list of dictionaries or a
|
|
@@ -77,4 +77,5 @@ def write(
|
|
|
77
77
|
int
|
|
78
78
|
The number of rows written to the MUSTACHE file.
|
|
79
79
|
"""
|
|
80
|
+
path = coerce_path(path)
|
|
80
81
|
return stub.write(path, data, format_name='MUSTACHE')
|