pycldf 2.0.2__tar.gz → 2.1.0__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.
- {pycldf-2.0.2 → pycldf-2.1.0}/CHANGELOG.md +7 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/PKG-INFO +2 -2
- {pycldf-2.0.2 → pycldf-2.1.0}/RELEASING.md +1 -1
- {pycldf-2.0.2 → pycldf-2.1.0}/setup.cfg +2 -2
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/__init__.py +1 -1
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/ext/discovery.py +7 -3
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/media.py +11 -4
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf.egg-info/PKG-INFO +2 -2
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf.egg-info/requires.txt +3 -1
- {pycldf-2.0.2 → pycldf-2.1.0}/tests/test_ext_discovery.py +2 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/tests/test_media.py +8 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/CONTRIBUTING.md +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/LICENSE +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/MANIFEST.in +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/README.md +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/pyproject.toml +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/setup.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/__main__.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/_compat.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/cli_util.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/commands/__init__.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/commands/catmedia.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/commands/check.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/commands/createdb.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/commands/downloadmedia.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/commands/dumpdb.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/commands/markdown.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/commands/splitmedia.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/commands/stats.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/commands/validate.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/components/BorrowingTable-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/components/CodeTable-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/components/CognateTable-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/components/CognatesetTable-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/components/ContributionTable-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/components/EntryTable-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/components/ExampleTable-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/components/FormTable-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/components/FunctionalEquivalentTable-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/components/FunctionalEquivalentsetTable-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/components/LanguageTable-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/components/MediaTable-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/components/ParameterNetwork-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/components/ParameterTable-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/components/SenseTable-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/components/TreeTable-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/components/ValueTable-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/constraints.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/dataset.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/db.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/ext/__init__.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/ext/markdown.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/ext/sql.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/fileutil.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/markdown.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/module.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/modules/Dictionary-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/modules/Generic-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/modules/ParallelText-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/modules/StructureDataset-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/modules/TextCorpus-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/modules/Wordlist-metadata.json +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/orm.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/schemautil.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/sliceutil.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/sources.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/stats.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/terms.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/terms.rdf +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/trees.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/urlutil.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/util.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/validators.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf.egg-info/SOURCES.txt +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf.egg-info/dependency_links.txt +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf.egg-info/entry_points.txt +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf.egg-info/not-zip-safe +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf.egg-info/top_level.txt +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/test.md +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/tests/test_cli.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/tests/test_cli_util.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/tests/test_dataset.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/tests/test_db.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/tests/test_ext_markdown.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/tests/test_ext_sql.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/tests/test_misc.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/tests/test_orm.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/tests/test_paralleltext.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/tests/test_sources.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/tests/test_terms.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/tests/test_trees.py +0 -0
- {pycldf-2.0.2 → pycldf-2.1.0}/tests/test_util.py +0 -0
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
The `pycldf` package adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
## [2.1.0] - 2026-07-17
|
|
7
|
+
|
|
8
|
+
- Added support for reading media file data from locally downloaded zip archives. This helps with the
|
|
9
|
+
use case of datasets linking to media in separate Zenodo deposits.
|
|
10
|
+
- Added support for discovering multiple datasets from the same locator.
|
|
11
|
+
|
|
12
|
+
|
|
6
13
|
## [2.0.2] - 2026-05-14
|
|
7
14
|
|
|
8
15
|
- Fix bug whereby pipes in regular expression patterns would screw up table
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pycldf
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: A python library to read and write CLDF datasets
|
|
5
5
|
Home-page: https://github.com/cldf/pycldf
|
|
6
6
|
Author: Robert Forkel
|
|
@@ -27,6 +27,7 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
27
27
|
Requires-Python: >=3.9
|
|
28
28
|
Description-Content-Type: text/markdown
|
|
29
29
|
License-File: LICENSE
|
|
30
|
+
Requires-Dist: python-frontmatter<1.2; python_version < "3.10"
|
|
30
31
|
Requires-Dist: csvw>=4.0
|
|
31
32
|
Requires-Dist: clldutils>=4.0
|
|
32
33
|
Requires-Dist: uritemplate>=3.0
|
|
@@ -34,7 +35,6 @@ Requires-Dist: python-dateutil
|
|
|
34
35
|
Requires-Dist: simplepybtex
|
|
35
36
|
Requires-Dist: newick
|
|
36
37
|
Requires-Dist: commonnexus>=1.2.0
|
|
37
|
-
Requires-Dist: python-frontmatter
|
|
38
38
|
Requires-Dist: termcolor
|
|
39
39
|
Requires-Dist: PyYAML
|
|
40
40
|
Requires-Dist: jmespath
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[metadata]
|
|
2
2
|
name = pycldf
|
|
3
|
-
version = 2.0
|
|
3
|
+
version = 2.1.0
|
|
4
4
|
author = Robert Forkel
|
|
5
5
|
author_email = robert_forkel@eva.mpg.de
|
|
6
6
|
description = A python library to read and write CLDF datasets
|
|
@@ -37,6 +37,7 @@ package_dir =
|
|
|
37
37
|
= src
|
|
38
38
|
python_requires = >=3.9
|
|
39
39
|
install_requires =
|
|
40
|
+
python-frontmatter<1.2;python_version<"3.10"
|
|
40
41
|
csvw>=4.0
|
|
41
42
|
clldutils>=4.0
|
|
42
43
|
uritemplate>=3.0
|
|
@@ -44,7 +45,6 @@ install_requires =
|
|
|
44
45
|
simplepybtex
|
|
45
46
|
newick
|
|
46
47
|
commonnexus>=1.2.0
|
|
47
|
-
python-frontmatter
|
|
48
48
|
termcolor
|
|
49
49
|
PyYAML
|
|
50
50
|
jmespath
|
|
@@ -157,13 +157,16 @@ def get_resolvers() -> list[type]:
|
|
|
157
157
|
def _get_dataset(
|
|
158
158
|
locator: DatasetLocator,
|
|
159
159
|
location: Union[None, Dataset, pathlib.Path],
|
|
160
|
-
|
|
160
|
+
get_all: bool = False,
|
|
161
|
+
) -> Optional[Union[Dataset, list[Dataset]]]:
|
|
161
162
|
"""Determine whether locator matches location and if so, resolve to a Dataset instance."""
|
|
162
163
|
if isinstance(location, Dataset):
|
|
163
164
|
if locator.match(location):
|
|
164
165
|
return location
|
|
165
166
|
return None
|
|
166
167
|
if location.is_dir():
|
|
168
|
+
if get_all:
|
|
169
|
+
return [ds for ds in iter_datasets(location) if locator.match(ds)]
|
|
167
170
|
for ds in iter_datasets(location):
|
|
168
171
|
if locator.match(ds):
|
|
169
172
|
return ds
|
|
@@ -176,7 +179,8 @@ def _get_dataset(
|
|
|
176
179
|
|
|
177
180
|
def get_dataset(locator: str,
|
|
178
181
|
download_dir: pathlib.Path,
|
|
179
|
-
base: Optional[pathlib.Path] = None
|
|
182
|
+
base: Optional[pathlib.Path] = None,
|
|
183
|
+
get_all: bool = False) -> Union[Dataset, list[Dataset]]:
|
|
180
184
|
"""
|
|
181
185
|
:param locator: Dataset locator as specified in "Dataset discovery".
|
|
182
186
|
:param download_dir: Directory to which to download remote data if necessary.
|
|
@@ -191,7 +195,7 @@ def get_dataset(locator: str,
|
|
|
191
195
|
else:
|
|
192
196
|
res = resolver(locator.url_without_fragment, download_dir)
|
|
193
197
|
if res:
|
|
194
|
-
res = _get_dataset(locator, res)
|
|
198
|
+
res = _get_dataset(locator, res, get_all=get_all)
|
|
195
199
|
if res:
|
|
196
200
|
return res
|
|
197
201
|
raise ValueError(f'Could not resolve dataset locator {locator}')
|
|
@@ -139,12 +139,19 @@ class File: # pylint: disable=too-many-instance-attributes
|
|
|
139
139
|
|
|
140
140
|
def local_path(self, d: pathlib.Path = None) -> Optional[pathlib.Path]:
|
|
141
141
|
"""
|
|
142
|
-
:return: The expected path of the file in the directory `d
|
|
142
|
+
:return: The expected path of the file in the directory `d` in the case of files \
|
|
143
|
+
downloaded using the `downloadmedia` command. If `d` is a file it is accepted as full \
|
|
144
|
+
local path if it has the same name as the filename in the URL.
|
|
143
145
|
"""
|
|
144
146
|
if d is None:
|
|
145
147
|
if self.scheme == 'file':
|
|
146
148
|
return self._dsdir / urllib.parse.unquote(self.relpath)
|
|
147
149
|
return None
|
|
150
|
+
if d.is_file() and self.parsed_url:
|
|
151
|
+
if d.name == pathlib.Path(self.parsed_url.path).name:
|
|
152
|
+
# Support the use case of files in zip archives, where the archives are available
|
|
153
|
+
# locally, e.g. as download of a separate media file deposit from Zenodo.
|
|
154
|
+
return d
|
|
148
155
|
zip_ext = '.zip' if self.path_in_zip else (self.mimetype.extension or '')
|
|
149
156
|
return d.joinpath(f'{self.id}{zip_ext}')
|
|
150
157
|
|
|
@@ -155,14 +162,14 @@ class File: # pylint: disable=too-many-instance-attributes
|
|
|
155
162
|
|
|
156
163
|
def read(self, d: Optional[pathlib.Path] = None) -> Optional[StrOrBytes]:
|
|
157
164
|
"""
|
|
158
|
-
:param d: A local
|
|
159
|
-
will be read from the file's URL.
|
|
165
|
+
:param d: A local path where the file has been saved before - as expected by `local_path`. \
|
|
166
|
+
If `None`, the content will be read from the file's URL.
|
|
160
167
|
"""
|
|
161
168
|
if self.path_in_zip:
|
|
162
169
|
zipcontent = None
|
|
163
170
|
if d:
|
|
164
171
|
zipcontent = self.local_path(d).read_bytes()
|
|
165
|
-
if self.url:
|
|
172
|
+
if zipcontent is None and self.url:
|
|
166
173
|
zipcontent = self.url_reader[self.scheme](
|
|
167
174
|
self.parsed_url, Mimetype('application/zip'))
|
|
168
175
|
if zipcontent:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pycldf
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: A python library to read and write CLDF datasets
|
|
5
5
|
Home-page: https://github.com/cldf/pycldf
|
|
6
6
|
Author: Robert Forkel
|
|
@@ -27,6 +27,7 @@ Classifier: License :: OSI Approved :: Apache Software License
|
|
|
27
27
|
Requires-Python: >=3.9
|
|
28
28
|
Description-Content-Type: text/markdown
|
|
29
29
|
License-File: LICENSE
|
|
30
|
+
Requires-Dist: python-frontmatter<1.2; python_version < "3.10"
|
|
30
31
|
Requires-Dist: csvw>=4.0
|
|
31
32
|
Requires-Dist: clldutils>=4.0
|
|
32
33
|
Requires-Dist: uritemplate>=3.0
|
|
@@ -34,7 +35,6 @@ Requires-Dist: python-dateutil
|
|
|
34
35
|
Requires-Dist: simplepybtex
|
|
35
36
|
Requires-Dist: newick
|
|
36
37
|
Requires-Dist: commonnexus>=1.2.0
|
|
37
|
-
Requires-Dist: python-frontmatter
|
|
38
38
|
Requires-Dist: termcolor
|
|
39
39
|
Requires-Dist: PyYAML
|
|
40
40
|
Requires-Dist: jmespath
|
|
@@ -10,6 +10,8 @@ from pycldf.ext.discovery import *
|
|
|
10
10
|
|
|
11
11
|
def test_get_dataset_local(data, tmp_path):
|
|
12
12
|
assert get_dataset('structuredataset_with_examples', tmp_path, base=data)
|
|
13
|
+
res = get_dataset('structuredataset_with_examples', tmp_path, base=data, get_all=True)
|
|
14
|
+
assert isinstance(res, list) and isinstance(res[0], Dataset)
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
def test_get_dataset_github(data, tmp_path, mocker):
|
|
@@ -194,6 +194,14 @@ def test_Media(tmp_path, ds_factory):
|
|
|
194
194
|
assert list(MediaTable(ds))[0].read() == 'äöü'
|
|
195
195
|
assert list(MediaTable(ds))[0].read(d=tmp_path) == 'äöü'
|
|
196
196
|
|
|
197
|
+
ds = ds_factory(dict(
|
|
198
|
+
ID='x',
|
|
199
|
+
Download_URL="http://example.com/path/123.zip",
|
|
200
|
+
Media_Type='text/plain',
|
|
201
|
+
Path_In_Zip='arc/name',
|
|
202
|
+
))
|
|
203
|
+
assert list(MediaTable(ds))[0].read(d=tmp_path / '123.zip') == 'äöü'
|
|
204
|
+
|
|
197
205
|
|
|
198
206
|
def test_save_read_zipped_media(dataset_with_trees, tmp_path):
|
|
199
207
|
zipped = None
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pycldf-2.0.2 → pycldf-2.1.0}/src/pycldf/components/FunctionalEquivalentsetTable-metadata.json
RENAMED
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|