dsff 1.2.2__tar.gz → 1.2.3__tar.gz

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 (40) hide show
  1. {dsff-1.2.2/src/dsff.egg-info → dsff-1.2.3}/PKG-INFO +1 -1
  2. dsff-1.2.3/src/dsff/VERSION.txt +1 -0
  3. {dsff-1.2.2 → dsff-1.2.3}/src/dsff/formats/__init__.py +1 -1
  4. {dsff-1.2.2 → dsff-1.2.3}/src/dsff/formats/arff.py +21 -13
  5. {dsff-1.2.2 → dsff-1.2.3}/src/dsff/formats/csv.py +14 -13
  6. {dsff-1.2.2 → dsff-1.2.3}/src/dsff/formats/dataset.py +22 -8
  7. {dsff-1.2.2 → dsff-1.2.3}/src/dsff/formats/db.py +32 -25
  8. dsff-1.2.3/src/dsff/formats/pa.py +46 -0
  9. {dsff-1.2.2 → dsff-1.2.3/src/dsff.egg-info}/PKG-INFO +1 -1
  10. {dsff-1.2.2 → dsff-1.2.3}/tests/test_dsff.py +10 -4
  11. dsff-1.2.2/src/dsff/VERSION.txt +0 -1
  12. dsff-1.2.2/src/dsff/formats/pa.py +0 -36
  13. {dsff-1.2.2 → dsff-1.2.3}/.coveragerc +0 -0
  14. {dsff-1.2.2 → dsff-1.2.3}/.github/workflows/python-package.yml +0 -0
  15. {dsff-1.2.2 → dsff-1.2.3}/.gitignore +0 -0
  16. {dsff-1.2.2 → dsff-1.2.3}/.readthedocs.yml +0 -0
  17. {dsff-1.2.2 → dsff-1.2.3}/LICENSE +0 -0
  18. {dsff-1.2.2 → dsff-1.2.3}/README.md +0 -0
  19. {dsff-1.2.2 → dsff-1.2.3}/docs/coverage.svg +0 -0
  20. {dsff-1.2.2 → dsff-1.2.3}/docs/mkdocs.yml +0 -0
  21. {dsff-1.2.2 → dsff-1.2.3}/docs/pages/imgs/dsff-from.png +0 -0
  22. {dsff-1.2.2 → dsff-1.2.3}/docs/pages/imgs/dsff-to.png +0 -0
  23. {dsff-1.2.2 → dsff-1.2.3}/docs/pages/imgs/icon.png +0 -0
  24. {dsff-1.2.2 → dsff-1.2.3}/docs/pages/imgs/logo.png +0 -0
  25. {dsff-1.2.2 → dsff-1.2.3}/docs/pages/index.md +0 -0
  26. {dsff-1.2.2 → dsff-1.2.3}/docs/pages/usage.md +0 -0
  27. {dsff-1.2.2 → dsff-1.2.3}/docs/requirements.txt +0 -0
  28. {dsff-1.2.2 → dsff-1.2.3}/pyproject.toml +0 -0
  29. {dsff-1.2.2 → dsff-1.2.3}/pytest.ini +0 -0
  30. {dsff-1.2.2 → dsff-1.2.3}/requirements.txt +0 -0
  31. {dsff-1.2.2 → dsff-1.2.3}/setup.cfg +0 -0
  32. {dsff-1.2.2 → dsff-1.2.3}/src/dsff/__info__.py +0 -0
  33. {dsff-1.2.2 → dsff-1.2.3}/src/dsff/__init__.py +0 -0
  34. {dsff-1.2.2 → dsff-1.2.3}/src/dsff/formats/__common__.py +0 -0
  35. {dsff-1.2.2 → dsff-1.2.3}/src/dsff.egg-info/SOURCES.txt +0 -0
  36. {dsff-1.2.2 → dsff-1.2.3}/src/dsff.egg-info/dependency_links.txt +0 -0
  37. {dsff-1.2.2 → dsff-1.2.3}/src/dsff.egg-info/requires.txt +0 -0
  38. {dsff-1.2.2 → dsff-1.2.3}/src/dsff.egg-info/top_level.txt +0 -0
  39. {dsff-1.2.2 → dsff-1.2.3}/tests/__init__.py +0 -0
  40. {dsff-1.2.2 → dsff-1.2.3}/tests/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dsff
3
- Version: 1.2.2
3
+ Version: 1.2.3
4
4
  Summary: DataSet File Format (DSFF)
5
5
  Author-email: Alexandre D'Hondt <alexandre.dhondt@gmail.com>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -0,0 +1 @@
1
+ 1.2.3
@@ -23,7 +23,7 @@ if PYARROW: # pragma: no cover
23
23
 
24
24
  __all__ = ["DSFF"]
25
25
  for k in list(globals().keys()):
26
- if k.startswith("is_"):
26
+ if k.startswith("is_") or k.startswith("load_"):
27
27
  __all__.append(k)
28
28
 
29
29
  _FORMAT_TEXT_ALIAS = {'arff': "ARFF", 'csv': "CSV", 'db': "SQL", 'orc': "ORC"}
@@ -2,20 +2,20 @@
2
2
  from .__common__ import *
3
3
 
4
4
 
5
- __all__ = ["from_arff", "is_arff", "to_arff"]
5
+ __all__ = ["from_arff", "is_arff", "load_arff", "to_arff"]
6
6
 
7
7
 
8
- def _parse(text_or_fh, target=TARGET_NAME, missing=MISSING_TOKEN):
8
+ def _parse(text_or_fh, target=TARGET_NAME, missing=MISSING_TOKEN, **kw):
9
9
  d, features, metadata, title = [], {}, {}, ""
10
10
  relation, attributes, data = False, [False, False], False
11
11
  for n, l in enumerate(t.splitlines() if isinstance(t := text_or_fh, str) else t):
12
12
  l, pf = l.strip(), f"Line {n}: "
13
13
  # the file shall start with "@RELATION"
14
14
  if not relation:
15
- if l.startswith("@RELATION "):
15
+ if l.upper().startswith("@RELATION "):
16
16
  relation = True
17
17
  try:
18
- title = re.match(r"@RELATION\s+('[^']*'|\"[^\"]*\")$", l).group(1).strip("'\"")
18
+ title = re.match(r"@RELATION\s+('[^']*'|\"[^\"]*\")$", l, re.I).group(1).strip("'\"")
19
19
  continue
20
20
  except Exception as e:
21
21
  raise BadInputData(f"{pf}failed on @RELATION ({e})")
@@ -34,9 +34,8 @@ def _parse(text_or_fh, target=TARGET_NAME, missing=MISSING_TOKEN):
34
34
  if attributes[0] and not attributes[1]:
35
35
  # close the atributes block
36
36
  attributes[1] = True
37
- n_cols = len(d[0])
38
37
  continue
39
- if l.startswith("@ATTRIBUTE "):
38
+ if l.upper().startswith("@ATTRIBUTE "):
40
39
  if not attributes[0]:
41
40
  attributes[0] = True
42
41
  if len(d) == 0:
@@ -45,21 +44,23 @@ def _parse(text_or_fh, target=TARGET_NAME, missing=MISSING_TOKEN):
45
44
  if attributes[1]:
46
45
  raise BadInputData(f"{pf}found @ATTRIBUTE out of the attributes block)")
47
46
  try:
48
- header = re.match(r"@ATTRIBUTE\s+([^\s]+)\s+[A-Z]+$", l).group(1)
47
+ header = re.match(r"@ATTRIBUTE\s+([^\s]+)\s+(?:[a-zA-Z]+|\{.*?\})$", l, re.I).group(1).strip("'\"")
49
48
  if header == "class":
50
49
  header = target
50
+ else:
51
+ features.setdefault(header, "")
51
52
  d[0].append(header)
52
53
  continue
53
54
  except AttributeError:
54
55
  raise BadInputData(f"{pf}failed on @ATTRIBUTE (bad type)")
55
56
  if not data:
56
- if l == "@DATA":
57
+ if l.upper() == "@DATA":
57
58
  data = True
59
+ n_cols = len(d[0])
58
60
  continue
59
61
  else:
60
62
  raise BadInputData(f"{pf}did not find @DATA where expected")
61
- row = list(map(lambda x: x.strip("'\""), re.split(r",\s+", l)))
62
- if len(row) != n_cols:
63
+ if len(row := list(map(lambda x: x.strip("'\""), re.split(r",\s*", l)))) != n_cols:
63
64
  raise BadInputData(f"{pf}this row does not match the number of columns")
64
65
  d.append(row)
65
66
  for i in range(n_cols):
@@ -78,7 +79,7 @@ def _parse(text_or_fh, target=TARGET_NAME, missing=MISSING_TOKEN):
78
79
  return d, features, metadata, title
79
80
 
80
81
 
81
- def from_arff(dsff, path=None, target=TARGET_NAME, missing=MISSING_TOKEN):
82
+ def from_arff(dsff, path=None, target=TARGET_NAME, missing=MISSING_TOKEN, **kw):
82
83
  """ Populate the DSFF file from an ARFF file. """
83
84
  with open(path) as f:
84
85
  d, ft, md, t = _parse(f, target, missing)
@@ -87,7 +88,7 @@ def from_arff(dsff, path=None, target=TARGET_NAME, missing=MISSING_TOKEN):
87
88
 
88
89
 
89
90
  @text_or_path
90
- def is_arff(text):
91
+ def is_arff(text, target=TARGET_NAME, missing=MISSING_TOKEN, **kw):
91
92
  """ Check if the input text or path is a valid ARFF. """
92
93
  try:
93
94
  _parse(ensure_str(text))
@@ -96,7 +97,14 @@ def is_arff(text):
96
97
  return False
97
98
 
98
99
 
99
- def to_arff(dsff, path=None, target=TARGET_NAME, exclude=DEFAULT_EXCL, missing=MISSING_TOKEN, text=False):
100
+ def load_arff(path, target=TARGET_NAME, missing=MISSING_TOKEN, **kw):
101
+ """ Load an ARFF file as a dictionary with data, features and metadata. """
102
+ with open(path) as f:
103
+ d, ft, md, _ = _parse(f, target, missing)
104
+ return {'data': d, 'features': ft, 'metadata': md}
105
+
106
+
107
+ def to_arff(dsff, path=None, target=TARGET_NAME, exclude=DEFAULT_EXCL, missing=MISSING_TOKEN, text=False, **kw):
100
108
  """ Output the dataset in ARFF format, suitable for use with the Weka framework, saved as a file or output as a
101
109
  string. """
102
110
  name = splitext(basename(path))[0]
@@ -2,24 +2,16 @@
2
2
  from .__common__ import *
3
3
 
4
4
 
5
- __all__ = ["from_csv", "is_csv", "to_csv"]
5
+ __all__ = ["from_csv", "is_csv", "load_csv", "to_csv"]
6
6
 
7
7
 
8
- def from_csv(dsff, path=None, exclude=DEFAULT_EXCL):
8
+ def from_csv(dsff, path=None, exclude=DEFAULT_EXCL, **kw):
9
9
  """ Populate the DSFF file from a CSV file. """
10
- dsff.write(path)
11
- features = {}
12
- for headers in dsff['data'].rows:
13
- for header in headers:
14
- if header.value in exclude:
15
- continue
16
- features[header.value] = ""
17
- break
18
- dsff.write(features=features)
10
+ dsff.write(**load_csv(path))
19
11
 
20
12
 
21
13
  @text_or_path
22
- def is_csv(text):
14
+ def is_csv(text, **kw):
23
15
  """ Check if the input text or path is a valid CSV. """
24
16
  try:
25
17
  dialect = csvmod.Sniffer().sniff(text := ensure_str(text))
@@ -29,7 +21,16 @@ def is_csv(text):
29
21
  return False
30
22
 
31
23
 
32
- def to_csv(dsff, path=None, text=False):
24
+ def load_csv(path, exclude=DEFAULT_EXCL, **kw):
25
+ """ Load a CSV file as a dictionary with data, features and metadata. """
26
+ data = {'metadata': {}}
27
+ with open(expanduser(path)) as f:
28
+ data['data'] = [r for r in csvmod.reader(f, delimiter=CSV_DELIMITER)]
29
+ data['features'] = {h: "" for h in data['data'][0] if h not in exclude}
30
+ return data
31
+
32
+
33
+ def to_csv(dsff, path=None, text=False, **kw):
33
34
  """ Create a CSV from the data worksheet, saved as a file or output as a string. """
34
35
  with (StringIO() if text else open(path, 'w+')) as f:
35
36
  writer = csvmod.writer(f, delimiter=";")
@@ -1,25 +1,25 @@
1
1
  # -*- coding: UTF-8 -*-
2
2
  from .__common__ import *
3
+ from .csv import load_csv
3
4
 
4
5
 
5
- __all__ = ["from_dataset", "is_dataset", "to_dataset"]
6
+ __all__ = ["from_dataset", "is_dataset", "load_dataset", "to_dataset"]
6
7
 
7
8
 
8
9
  def _parse(path):
9
- if not isdir(path):
10
+ if not isdir(expanduser(path)):
10
11
  raise BadInputData("Not a folder")
11
- else:
12
- if len(missing := [f for f in ["data.csv", "features.json", "metadata.json"] if not isfile(join(path, f))]) > 0:
13
- raise BadInputData(f"Not a valid dataset folder (missing: {', '.join(missing)})")
12
+ if len(missing := [f for f in ["data.csv", "features.json", "metadata.json"] if not isfile(join(path, f))]) > 0:
13
+ raise BadInputData(f"Not a valid dataset folder (missing: {', '.join(missing)})")
14
14
 
15
15
 
16
- def from_dataset(dsff, path=None):
16
+ def from_dataset(dsff, path=None, **kw):
17
17
  """ Populate the DSFF file from a Dataset structure. """
18
18
  _parse(path)
19
19
  dsff.write(path)
20
20
 
21
21
 
22
- def is_dataset(path):
22
+ def is_dataset(path, **kw):
23
23
  """ Check if the input path is a valid Dataset. """
24
24
  try:
25
25
  _parse(path)
@@ -28,7 +28,21 @@ def is_dataset(path):
28
28
  return False
29
29
 
30
30
 
31
- def to_dataset(dsff, path=None):
31
+ def load_dataset(path, **kw):
32
+ """ Load a dataset folder as a dictionary with data, features and metadata. """
33
+ if not isdir(d := expanduser(str(path))):
34
+ raise BadInputData("Not a folder")
35
+ dp, fp, mp = join(d, "data.csv"), join(d, "features.json"), join(d, "metadata.json")
36
+ data = {}
37
+ data['data'] = load_csv(dp)['data']
38
+ with open(fp) as f:
39
+ data['features'] = json.load(f)
40
+ with open(mp) as f:
41
+ data['metadata'] = json.load(f)
42
+ return data
43
+
44
+
45
+ def to_dataset(dsff, path=None, **kw):
32
46
  """ Create a dataset folder according to the following structure ;
33
47
  name
34
48
  +-- data.csv
@@ -2,36 +2,16 @@
2
2
  from .__common__ import *
3
3
 
4
4
 
5
- __all__ = ["from_db", "is_db", "to_db"]
5
+ __all__ = ["from_db", "is_db", "load_db", "to_db"]
6
6
 
7
7
 
8
- def from_db(dsff, path=None, exclude=DEFAULT_EXCL):
8
+ def from_db(dsff, path=None, **kw):
9
9
  """ Populate the DSFF file from a SQLDB file. """
10
- from json import loads
11
- from sqlite3 import connect
12
- conn = connect(path)
13
- cursor = conn.cursor()
14
- # list tables
15
- cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
16
- tables = [table[0] for table in cursor.fetchall()]
17
- if not all(t in tables for t in ["data", "features", "metadata"]): # pragma: no cover
18
- raise BadInputData("The target SQLDB does not have the right format")
19
- # import data
20
- cursor.execute("PRAGMA table_info('data')")
21
- headers = [[col[1] for col in cursor.fetchall()]]
22
- cursor.execute("SELECT * FROM data;")
23
- dsff.write(headers + [r for r in cursor.fetchall()])
24
- # import feature definitions
25
- cursor.execute("SELECT name,description FROM features;")
26
- dsff.write(features={r[0]: r[1] for r in cursor.fetchall()})
27
- # import metadata
28
- cursor.execute("SELECT key,value FROM metadata;")
29
- dsff.write(metadata={r[0]: loads(r[1]) if isinstance(r[1], str) else r[1] for r in cursor.fetchall()})
30
- conn.close()
10
+ dsff.write(**load_db(path))
31
11
 
32
12
 
33
13
  @text_or_path
34
- def is_db(data):
14
+ def is_db(data, **kw):
35
15
  """ Check if the input data or path is a valid SQL database. """
36
16
  from sqlite3 import connect, Error
37
17
  from sys import version_info
@@ -60,7 +40,34 @@ def is_db(data):
60
40
  return False
61
41
 
62
42
 
63
- def to_db(dsff, path=None, text=False, primary_index=0):
43
+ def load_db(path, **kw):
44
+ """ Load a SQLDB file as a dictionary with data, features and metadata. """
45
+ from json import loads
46
+ from os.path import basename, splitext
47
+ from sqlite3 import connect
48
+ conn = connect(path)
49
+ cursor, data = conn.cursor(), {}
50
+ # list tables
51
+ cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
52
+ tables = [table[0] for table in cursor.fetchall()]
53
+ if not all(t in tables for t in ["data", "features", "metadata"]): # pragma: no cover
54
+ raise BadInputData("The target SQLDB does not have the right format")
55
+ # import data
56
+ cursor.execute("PRAGMA table_info('data')")
57
+ headers = [[col[1] for col in cursor.fetchall()]]
58
+ cursor.execute("SELECT * FROM data;")
59
+ data['data'] = headers + [r for r in cursor.fetchall()]
60
+ # import feature definitions
61
+ cursor.execute("SELECT name,description FROM features;")
62
+ data['features'] = {r[0]: r[1] for r in cursor.fetchall()}
63
+ # import metadata
64
+ cursor.execute("SELECT key,value FROM metadata;")
65
+ data['metadata'] = {r[0]: loads(r[1]) if isinstance(r[1], str) else r[1] for r in cursor.fetchall()}
66
+ conn.close()
67
+ return data
68
+
69
+
70
+ def to_db(dsff, path=None, text=False, primary_index=0, **kw):
64
71
  """ Create a SQLDB from the data worksheet, saved as a file or output as a string. """
65
72
  from json import dumps
66
73
  from sqlite3 import connect
@@ -0,0 +1,46 @@
1
+ # -*- coding: UTF-8 -*-
2
+ from .__common__ import *
3
+
4
+
5
+ __all__ = []
6
+
7
+
8
+ def _nowrite(m):
9
+ raise NotImplementedError(f"none of {m}.write_table and {m}.write_{m} is implemented")
10
+
11
+
12
+ def _parse(ds):
13
+ return {
14
+ 'data': [ds.schema.names] + [list(r.values()) for r in ds.to_pylist()],
15
+ 'features': {k.decode(): v.decode() for k, v in ds.schema.metadata.items()},
16
+ 'metadata': literal_eval(ds.schema.metadata.pop(b'__metadata__', b"{}").decode()),
17
+ }
18
+
19
+
20
+ for module in ["feather", "orc", "parquet"]:
21
+ __all__ += [f"from_{module}", f"is_{module}", f"load_{module}", f"to_{module}"]
22
+ def gen_func(m):
23
+ def from_(dsff, path=None, **kw):
24
+ from os.path import basename, splitext
25
+ dsff.write(**_parse(globals()[m].read_table(path)))
26
+ from_.__name__ = f"from_{m}"
27
+ def is_(data, **kw):
28
+ try:
29
+ globals()[m].read_table(pyarrow.BufferReader(data))
30
+ return True
31
+ except Exception:
32
+ return False
33
+ is_.__name__ = f"is_{m}"
34
+ def load_(path, **kw):
35
+ return _parse(globals()[m].read_table(path))
36
+ load_.__name__ = f"load_{m}"
37
+ def to_(dsff, path=None, text=False, **kw):
38
+ with (BytesIO() if text else open(path, 'wb+')) as f:
39
+ getattr(globals()[m], "write_table", getattr(globals()[m], f"write_{m}", _nowrite))(dsff._to_table(), f)
40
+ if text:
41
+ return f.getvalue()
42
+ to_.__name__ = f"to_{m}"
43
+ return from_, text_or_path(is_), load_, to_
44
+ globals()[f'from_{module}'], globals()[f'is_{module}'], globals()[f'load_{module}'], globals()[f'to_{module}'] = \
45
+ gen_func(module)
46
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dsff
3
- Version: 1.2.2
3
+ Version: 1.2.3
4
4
  Summary: DataSet File Format (DSFF)
5
5
  Author-email: Alexandre D'Hondt <alexandre.dhondt@gmail.com>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -89,6 +89,7 @@ class TestDsff(TestCase):
89
89
  with open(arff := f"{TEST_BASENAME}.arff", 'w') as f:
90
90
  f.write(TEST_ARFF)
91
91
  self.assertTrue(is_arff(arff))
92
+ self.assertIsInstance(load_arff(arff), dict)
92
93
  with DSFF() as f:
93
94
  f.from_arff(TEST_BASENAME)
94
95
  # test for multiple error scenarios
@@ -130,7 +131,8 @@ class TestDsff(TestCase):
130
131
  with DSFF(TEST) as f:
131
132
  self.assertIsNotNone(f.to_csv(text=True))
132
133
  self.assertIsNone(f.to_csv())
133
- self.assertTrue(is_csv(f"{TEST}.csv"))
134
+ self.assertTrue(is_csv(csv := f"{TEST_BASENAME}.csv"))
135
+ self.assertIsInstance(load_csv(csv), dict)
134
136
  # CSV to DSFF
135
137
  with DSFF() as f:
136
138
  f.from_csv(TEST_BASENAME)
@@ -143,7 +145,9 @@ class TestDsff(TestCase):
143
145
  # FilelessDataset to DSFF
144
146
  with DSFF() as f:
145
147
  f.from_dataset(TEST_BASENAME)
146
- self.assertTrue(is_dataset(f"{TEST_BASENAME}"))
148
+ self.assertTrue(is_dataset(TEST_BASENAME))
149
+ self.assertRaises(BadInputData, load_dataset, 0)
150
+ self.assertIsInstance(load_dataset(TEST_BASENAME), dict)
147
151
  # FilelessDataset to DSFF (bad input dataset)
148
152
  os.remove(os.path.join(TEST_BASENAME, "metadata.json"))
149
153
  with DSFF() as f:
@@ -167,7 +171,8 @@ class TestDsff(TestCase):
167
171
  with DSFF(TEST) as f:
168
172
  self.assertIsNotNone(f.to_db(text=True))
169
173
  self.assertIsNone(f.to_db())
170
- self.assertTrue(is_db(f"{TEST_BASENAME}.db"))
174
+ self.assertTrue(is_db(db := f"{TEST_BASENAME}.db"))
175
+ self.assertIsInstance(load_db(db), dict)
171
176
  # SQL database to DSFF
172
177
  with DSFF() as f:
173
178
  f.from_db(TEST_BASENAME)
@@ -183,8 +188,9 @@ class TestDsff(TestCase):
183
188
  self.assertIsNone(getattr(f, f"to_{fmt}")(TEST_BASENAME))
184
189
  self.assertIsNotNone(getattr(f, f"to_{fmt}")(text=True))
185
190
  is_ = globals()[f'is_{fmt}']
186
- self.assertTrue(is_(f"{TEST_BASENAME}.{fmt}"))
191
+ self.assertTrue(is_(fn := f"{TEST_BASENAME}.{fmt}"))
187
192
  self.assertFalse(is_(b"PK\x03\x04\x14\x00\x00\x00\x08\x00P\xb3T\\F\xc7MH"))
193
+ self.assertIsInstance(globals()[f'load_{fmt}'](fn), dict)
188
194
  with DSFF(INMEMORY) as f:
189
195
  self.assertIsNone(getattr(f, f"from_{fmt}")(TEST_BASENAME))
190
196
  f.to_dataset(path=TEST_BASENAME)
@@ -1 +0,0 @@
1
- 1.2.2
@@ -1,36 +0,0 @@
1
- # -*- coding: UTF-8 -*-
2
- from .__common__ import *
3
-
4
-
5
- __all__ = []
6
-
7
-
8
- def _nowrite(m):
9
- raise NotImplementedError(f"none of {m}.write_table and {m}.write_{m} is implemented")
10
-
11
-
12
- for module in ["feather", "orc", "parquet"]:
13
- __all__ += [f"from_{module}", f"is_{module}", f"to_{module}"]
14
- def gen_func(m):
15
- def from_(dsff, path=None, exclude=DEFAULT_EXCL):
16
- dataset = globals()[m].read_table(path)
17
- dsff.write(data=[dataset.schema.names] + [list(r.values()) for r in dataset.to_pylist()],
18
- metadata=literal_eval(dataset.schema.metadata.pop(b'__metadata__', b"{}").decode()),
19
- features={k.decode(): v.decode() for k, v in dataset.schema.metadata.items()})
20
- from_.__name__ = f"from_{m}"
21
- def is_(data):
22
- try:
23
- globals()[m].read_table(pyarrow.BufferReader(data))
24
- return True
25
- except Exception:
26
- return False
27
- is_.__name__ = f"is_{m}"
28
- def to_(dsff, path=None, text=False):
29
- with (BytesIO() if text else open(path, 'wb+')) as f:
30
- getattr(globals()[m], "write_table", getattr(globals()[m], f"write_{m}", _nowrite))(dsff._to_table(), f)
31
- if text:
32
- return f.getvalue()
33
- to_.__name__ = f"to_{m}"
34
- return from_, text_or_path(is_), to_
35
- globals()[f'from_{module}'], globals()[f'is_{module}'], globals()[f'to_{module}'] = gen_func(module)
36
-
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes