Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,17 @@ For more detail see #29.
- addition of a `Link` class, to allow making reference to remote graph nodes defined by their `@id`
that are not present locally.
- improved CI testing: we now test v3 and v4, as well as "latest".

## Release 0.4.0 (2025-11-18)

- drop support for Python 3.8, add support for Python 3.14.
- more forgiving import of JSON-LD:
- an option to allow additional (non-openMINDS) keys in a JSON-LD document [#63](https://github.com/openMetadataInitiative/openMINDS_Python/pull/63)
- support fully-expanded IRIs as keys in JSON-LD documents [#64](https://github.com/openMetadataInitiative/openMINDS_Python/pull/64)
- accept `datetime` strings for properties with type `date` [#65](https://github.com/openMetadataInitiative/openMINDS_Python/pull/65)
- accept `"@type": [<IRI>]` as well as `"@type": <IRI>` [#66](https://github.com/openMetadataInitiative/openMINDS_Python/pull/66)
- make the class registry reusable by other packages [#70](https://github.com/openMetadataInitiative/openMINDS_Python/pull/70)
- bug fix: prevent infinite recursion in `validate()` where there are loops in the graph [#76](https://github.com/openMetadataInitiative/openMINDS_Python/pull/76)
- allow the user to specify which openMINDS version should be used by `Collection.load()` [#77](https://github.com/openMetadataInitiative/openMINDS_Python/pull/77)
- add the option to group files into subdirectories by schema when saving [#80](https://github.com/openMetadataInitiative/openMINDS_Python/pull/80)
- improvements to the `by_name()` method [#81](https://github.com/openMetadataInitiative/openMINDS_Python/pull/81)
2 changes: 1 addition & 1 deletion build.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@

env = Environment(loader=FileSystemLoader(os.path.dirname(os.path.realpath(__file__))), autoescape=select_autoescape())
context = {
"version": "0.3.1",
"version": "0.4.0",
}
if args.branch == "development":
context["version"] += ".dev"
Expand Down
1 change: 1 addition & 0 deletions pipeline/src/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ def to_jsonld(self):
"@id": self.identifier
}


class IRI:
"""
Representation of an International Resource Identifier
Expand Down
49 changes: 47 additions & 2 deletions pipeline/src/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
The collection can be saved to and loaded from disk, in JSON-LD format.
"""

from collections import Counter
from glob import glob
from importlib import import_module
import json
import os
from .registry import lookup_type
Expand Down Expand Up @@ -70,6 +72,30 @@ def _sort_nodes_by_id(self):
sorted_nodes = dict(sorted(self.nodes.items()))
self.nodes = sorted_nodes

def generate_ids(self, id_generator):
"""
Generate an IRI id for all nodes in the graph that do not possess one.

Args
----

id_generator (function):
a function that takes the node as an argument, and returns a unique IRI
"""
for node_id in list(self.nodes.keys()):
if node_id.startswith("_:"):
node = self.nodes.pop(node_id)
node.id = id_generator(node)
self.nodes[node.id] = node

@property
def complete(self):
"""Do all nodes have an IRI?"""
for node_id in self.nodes:
if node_id.startswith("_:"):
return False
return True

def save(self, path, individual_files=False, include_empty_properties=False, group_by_schema=False):
"""
Save the node collection to disk in JSON-LD format.
Expand Down Expand Up @@ -171,8 +197,18 @@ def load(self, *paths, version=DEFAULT_VERSION):
2) one or more JSON-LD files, which will all be loaded.

By default, openMINDS v4 will be used.
If the JSON-LD files use a different openMINDS version, specify it with the `version` argument.
If the JSON-LD files use a different openMINDS version, specify it
with the `version` argument, e.g.::

import openminds.latest

c = Collection()
c.load("/path/to/my/metadata.jsonld", version="latest")

"""

import_module(f"openminds.{version}")

if len(paths) == 1 and os.path.isdir(paths[0]):
data_dir = paths[0]
json_paths = (
Expand All @@ -199,7 +235,7 @@ def load(self, *paths, version=DEFAULT_VERSION):
self.add(node)
else:
if "@type" in data:
cls = lookup_type(data["@type"])
cls = lookup_type(data["@type"], version=version)
node = cls.from_jsonld(data)
else:
# allow links to metadata instances outside this collection
Expand Down Expand Up @@ -260,3 +296,12 @@ def sort_nodes_for_upload(self):
newly_sorted.append(node_id)
unsorted -= set(newly_sorted)
return [self.nodes[node_id] for node_id in sorted]

def statistics(self):
"""
Return a counter containing the number of nodes of each type.
"""
stats = Counter(
node.__class__.__name__ for node in self.nodes.values()
)
return stats