Skip to content

Commit

Permalink
Merge pull request #183 from simleo/crate_from_dict
Browse files Browse the repository at this point in the history
Add ro-crate instantiation from a dictionary
  • Loading branch information
simleo committed May 10, 2024
2 parents a551acb + 2fd0ec2 commit a70891b
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 18 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
strategy:
matrix:
os: ['ubuntu-latest', 'macos-latest', 'windows-latest']
python-version: ['3.7', '3.8', '3.9', '3.10']
python-version: ['3.8', '3.9', '3.10', '3.11']

runs-on: ${{ matrix.os }}

Expand Down
7 changes: 5 additions & 2 deletions rocrate/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ def read_metadata(metadata_path):
Return a tuple of two elements: the context; a dictionary that maps entity
ids to the entities themselves.
"""
with open(metadata_path) as f:
metadata = json.load(f)
if isinstance(metadata_path, dict):
metadata = metadata_path
else:
with open(metadata_path) as f:
metadata = json.load(f)
try:
context = metadata['@context']
graph = metadata['@graph']
Expand Down
35 changes: 20 additions & 15 deletions rocrate/rocrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,26 +113,31 @@ def __init_from_tree(self, top_dir, gen_preview=False):
self.add(Preview(self, source))

def __read(self, source, gen_preview=False):
source = Path(source)
if not source.exists():
raise FileNotFoundError(errno.ENOENT, f"'{source}' not found")
if zipfile.is_zipfile(source):
zip_path = tempfile.mkdtemp(prefix="rocrate_")
atexit.register(shutil.rmtree, zip_path)
with zipfile.ZipFile(source, "r") as zf:
zf.extractall(zip_path)
source = Path(zip_path)
metadata_path = source / Metadata.BASENAME
if not metadata_path.is_file():
metadata_path = source / LegacyMetadata.BASENAME
if not metadata_path.is_file():
raise ValueError(f"Not a valid RO-Crate: missing {Metadata.BASENAME}")
if isinstance(source, dict):
metadata_path = source
else:
source = Path(source)
if not source.exists():
raise FileNotFoundError(errno.ENOENT, f"'{source}' not found")
if zipfile.is_zipfile(source):
zip_path = tempfile.mkdtemp(prefix="rocrate_")
atexit.register(shutil.rmtree, zip_path)
with zipfile.ZipFile(source, "r") as zf:
zf.extractall(zip_path)
source = Path(zip_path)
metadata_path = source / Metadata.BASENAME
if not metadata_path.is_file():
metadata_path = source / LegacyMetadata.BASENAME
if not metadata_path.is_file():
raise ValueError(f"Not a valid RO-Crate: missing {Metadata.BASENAME}")
_, entities = read_metadata(metadata_path)
self.__read_data_entities(entities, source, gen_preview)
self.__read_contextual_entities(entities)
return source

def __read_data_entities(self, entities, source, gen_preview):
if isinstance(source, dict):
source = Path("")
metadata_id, root_id = find_root_entity_id(entities)
root_entity = entities.pop(root_id)
assert root_id == root_entity.pop('@id')
Expand Down Expand Up @@ -447,7 +452,7 @@ def _copy_unlisted(self, top, base_path):
def write(self, base_path):
base_path = Path(base_path)
base_path.mkdir(parents=True, exist_ok=True)
if self.source:
if self.source and not isinstance(self.source, dict):
self._copy_unlisted(self.source, base_path)
for writable_entity in self.data_entities + self.default_entities:
writable_entity.write(base_path)
Expand Down
58 changes: 58 additions & 0 deletions test/test_read.py
Original file line number Diff line number Diff line change
Expand Up @@ -535,3 +535,61 @@ def test_indirect_data_entity(tmpdir):
d2_e = crate.dereference("d1/d2")
assert d2_e
assert d2_e in crate.data_entities


@pytest.mark.filterwarnings("ignore")
def test_from_dict(tmpdir):
metadata = {
"@context": "https://w3id.org/ro/crate/1.1/context",
"@graph": [
{
"@id": "ro-crate-metadata.json",
"@type": "CreativeWork",
"about": {"@id": "./"},
"conformsTo": {"@id": "https://w3id.org/ro/crate/1.1"}
},
{
"@id": "./",
"@type": "Dataset",
"creator": {"@id": "#josiah"},
"hasPart": {"@id": "d1"}
},
{
"@id": "d1",
"@type": "Dataset",
"hasPart": {"@id": "d1/d2"}
},
{
"@id": "d1/d2",
"@type": "Dataset",
"hasPart": {"@id": "d1/d2/f1"}
},
{
"@id": "d1/d2/f1",
"@type": "File"
},
{
"@id": "#josiah",
"@type": "Person",
'name': 'Josiah Carberry'
},
]
}
crate = ROCrate(metadata)
d1 = crate.dereference("d1")
assert d1
d2 = crate.dereference("d1/d2")
assert d2
f1 = crate.dereference("d1/d2/f1")
assert f1
p = crate.dereference("#josiah")
assert p
assert set(crate.data_entities) == {d1, d2, f1}
assert set(crate.contextual_entities) == {p}
out_path = tmpdir / 'out_crate'
with pytest.raises(OSError):
crate.write(out_path)
# make it writable
for entity in d1, d2, f1:
entity.source = None
crate.write(out_path)

0 comments on commit a70891b

Please sign in to comment.