From 5ba25e4147d2cf2e13f9b492cf9c443bde4a72f0 Mon Sep 17 00:00:00 2001 From: Andrew Davison Date: Sat, 17 Oct 2026 23:40:32 +0200 Subject: [PATCH 1/2] Apply black formatting --- doc/build_authors.py | 9 +++++---- doc/conf.py | 4 ++-- fairgraph/base.py | 4 +--- fairgraph/client.py | 16 +++++++++++----- fairgraph/collection.py | 4 +++- fairgraph/embedded.py | 4 ++-- fairgraph/introspection.py | 14 ++++++++++---- fairgraph/kgobject.py | 8 ++++---- fairgraph/node.py | 4 +--- fairgraph/queries.py | 7 +++---- fairgraph/registry.py | 3 +-- fairgraph/utility/activity_log.py | 8 +------- fairgraph/utility/name_matching.py | 10 +++++----- test/test_client.py | 22 +++++++--------------- test/test_name_matching.py | 4 ++-- test/test_openminds_computation.py | 8 ++++++-- test/test_openminds_versions.py | 15 +++++++-------- test/test_queries.py | 20 ++++++++------------ test/test_utility.py | 10 +++------- 19 files changed, 82 insertions(+), 92 deletions(-) diff --git a/doc/build_authors.py b/doc/build_authors.py index 2805bd7c..8354ddf7 100644 --- a/doc/build_authors.py +++ b/doc/build_authors.py @@ -6,6 +6,7 @@ import requests from pathlib import Path + def full_name(au): # contributors may give a pseudonym (alternateName) rather than their given and family names return " ".join(filter(None, (au.get("givenName"), au.get("familyName")))) or au["alternateName"] @@ -65,7 +66,9 @@ def get_affiliation_text(affil): def affiliation_number(au, affiliations): - index = list(affiliations.keys()).index(affiliation_key(au["affiliation"][0])) # to do: handle people with multiple affiliations + index = list(affiliations.keys()).index( + affiliation_key(au["affiliation"][0]) + ) # to do: handle people with multiple affiliations return index + 1 @@ -73,9 +76,7 @@ def affiliation_number(au, affiliations): f"{i}. {get_affiliation_text(affil)}" for i, affil in enumerate(affiliations.values(), start=1) ) -authors_text = "\n".join( - [f"- {full_name(au)} [{affiliation_number(au, affiliations)}]" for au in author_data] -) +authors_text = "\n".join([f"- {full_name(au)} [{affiliation_number(au, affiliations)}]" for au in author_data]) with open("authors.rst", "w") as fp: fp.write(template.format(authors=authors_text, affiliations=affiliations_text)) diff --git a/doc/conf.py b/doc/conf.py index 1406fe8d..18abe03d 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -38,7 +38,7 @@ def full_name(au): # The full version, including alpha/beta/rc tags with open("../pyproject.toml", "rb") as fp: - release = tomllib.load(fp)['project']["version"] + release = tomllib.load(fp)["project"]["version"] # The short X.Y version version = ".".join(release.split(".")[:2]) @@ -64,7 +64,7 @@ def full_name(au): templates_path = ["_templates"] # The suffix(es) of source filenames. -source_suffix = {'.rst': 'restructuredtext'} +source_suffix = {".rst": "restructuredtext"} # The master toctree document. master_doc = "index" diff --git a/fairgraph/base.py b/fairgraph/base.py index d1c91402..5b705727 100644 --- a/fairgraph/base.py +++ b/fairgraph/base.py @@ -76,9 +76,7 @@ def uuid(self) -> Union[str, None]: else: return None - def children( - self, client: KGClient, follow_links: Optional[Dict[str, Any]] = None - ) -> List[Releasable]: + def children(self, client: KGClient, follow_links: Optional[Dict[str, Any]] = None) -> List[Releasable]: pass def is_released(self, client: KGClient, with_children: bool = False) -> bool: diff --git a/fairgraph/client.py b/fairgraph/client.py index 08c681a0..d41229be 100644 --- a/fairgraph/client.py +++ b/fairgraph/client.py @@ -263,9 +263,7 @@ def __init__( retry_backoff: float = 5.0, ): if openminds_version not in ("v4", "v5"): - raise ValueError( - f"openminds_version must be 'v4' or 'v5', got {openminds_version!r}" - ) + raise ValueError(f"openminds_version must be 'v4' or 'v5', got {openminds_version!r}") self.openminds_version = openminds_version if not have_kg_core: raise ImportError("Please install the ebrains-kg-core package") @@ -447,7 +445,11 @@ def _query(release_status, from_index, size): ) error_context = f"_query(release_status={release_status} query_id={query_id} filter={filter} instance_id={instance_id} size={size} from_index={from_index})" return self._check_response( - response, error_context=error_context, expected_instance_id=instance_id, id_key=id_key, ignore_not_found=True + response, + error_context=error_context, + expected_instance_id=instance_id, + id_key=id_key, + ignore_not_found=True, ) else: @@ -463,7 +465,11 @@ def _query(release_status, from_index, size): ) error_context = f"_query(release_status={release_status} query_id={query_id} filter={filter} instance_id={instance_id} size={size} from_index={from_index})" return self._check_response( - response, error_context=error_context, expected_instance_id=instance_id, id_key=id_key, ignore_not_found=True + response, + error_context=error_context, + expected_instance_id=instance_id, + id_key=id_key, + ignore_not_found=True, ) if release_status == "any": diff --git a/fairgraph/collection.py b/fairgraph/collection.py index c47387e7..02ef3839 100644 --- a/fairgraph/collection.py +++ b/fairgraph/collection.py @@ -132,7 +132,9 @@ def upload( break except AuthenticationError as err: if attempt < max_retries: - logger.warning("Authentication error, refreshing client (attempt %d/%d)", attempt + 1, max_retries) + logger.warning( + "Authentication error, refreshing client (attempt %d/%d)", attempt + 1, max_retries + ) client.refresh() else: raise diff --git a/fairgraph/embedded.py b/fairgraph/embedded.py index b9863fdc..f89d0f06 100644 --- a/fairgraph/embedded.py +++ b/fairgraph/embedded.py @@ -68,9 +68,9 @@ def __repr__(self): return template.format(self=self) def __eq__(self, other): - return isinstance(other, self.__class__) and self.to_jsonld(embed_linked_nodes=LinkedNodeEmbedding.NEVER) == other.to_jsonld( + return isinstance(other, self.__class__) and self.to_jsonld( embed_linked_nodes=LinkedNodeEmbedding.NEVER - ) + ) == other.to_jsonld(embed_linked_nodes=LinkedNodeEmbedding.NEVER) @classmethod def from_jsonld(cls, data: JSONdict) -> Union[None, KGEmbedded]: diff --git a/fairgraph/introspection.py b/fairgraph/introspection.py index 1dd035fd..36e14a82 100644 --- a/fairgraph/introspection.py +++ b/fairgraph/introspection.py @@ -28,14 +28,20 @@ def list_kg_classes(module): """List all KG classes defined in the given module.""" - return [obj for name, obj in inspect.getmembers(module) - if inspect.isclass(obj) and issubclass(obj, KGObject) and obj.__module__.startswith(module.__name__)] + return [ + obj + for name, obj in inspect.getmembers(module) + if inspect.isclass(obj) and issubclass(obj, KGObject) and obj.__module__.startswith(module.__name__) + ] def list_embedded_metadata_classes(module): """List all embedded metadata classes defined in the given module.""" - return [obj for name, obj in inspect.getmembers(module) - if inspect.isclass(obj) and issubclass(obj, KGEmbedded) and obj.__module__.startswith(module.__name__)] + return [ + obj + for name, obj in inspect.getmembers(module) + if inspect.isclass(obj) and issubclass(obj, KGEmbedded) and obj.__module__.startswith(module.__name__) + ] def set_error_handling(value, module): diff --git a/fairgraph/kgobject.py b/fairgraph/kgobject.py index 748571d0..af11ebc1 100644 --- a/fairgraph/kgobject.py +++ b/fairgraph/kgobject.py @@ -1078,10 +1078,10 @@ def by_name( if not name_properties: raise AttributeError(f"{cls.__name__} doesn't have a name-like property") - # The KG has no way to apply a single filter across several properties, so we query each of them in turn and - # merge the results. - # The regular expression is only a pre-filter. It returns a superset of the matches, since the KG's regex - # matching is always case-insensitive, which is then narrowed down, using the same matching rules as the + # The KG has no way to apply a single filter across several properties, so we query each of them in turn and + # merge the results. + # The regular expression is only a pre-filter. It returns a superset of the matches, since the KG's regex + # matching is always case-insensitive, which is then narrowed down, using the same matching rules as the # openMINDS instance-library search. pattern = Regex( build_name_regex(name, match=match, case_sensitive=case_sensitive, ignore_accents=ignore_accents) diff --git a/fairgraph/node.py b/fairgraph/node.py index 5cfaf228..0bd4503a 100644 --- a/fairgraph/node.py +++ b/fairgraph/node.py @@ -500,9 +500,7 @@ def resolve( resolved_values: List[Any] = [] for value in as_list(values): if isinstance(value, Resolvable): - if isinstance(value, KGNode) and isinstance( - value, Releasable - ): + if isinstance(value, KGNode) and isinstance(value, Releasable): # i.e. isinstance(value, KGObject) - already resolved resolved_values.append(value) else: diff --git a/fairgraph/queries.py b/fairgraph/queries.py index 89d89938..f0695ba3 100644 --- a/fairgraph/queries.py +++ b/fairgraph/queries.py @@ -27,7 +27,6 @@ from openminds.base import IRI, EmbeddedMetadata, LinkedMetadata, Node from .utility import as_list, expand_uri - logger = logging.getLogger("fairgraph") @@ -35,8 +34,8 @@ class Regex(str): """ A regular expression, for use as a filter value in place of a plain string. - Where a plain string filters with the KG's "CONTAINS" operator, a `Regex` filters with "REGEX". - The KG applies the pattern as a search rather than a full match, + Where a plain string filters with the KG's "CONTAINS" operator, a `Regex` filters with "REGEX". + The KG applies the pattern as a search rather than a full match, so a pattern with no anchors matches anywhere in the property value; use "^" and "$" to anchor it. Matching is always case-insensitive, whatever the pattern says. @@ -57,7 +56,7 @@ class Regex(str): def __new__(cls, pattern: str): try: - # The KG's regular expression engine is not Python's, so this does not guarantee the KG will accept + # The KG's regular expression engine is not Python's, so this does not guarantee the KG will accept # the pattern, but it catches common errors such as an unbalanced bracket or parenthesis. re.compile(pattern) except re.error as err: diff --git a/fairgraph/registry.py b/fairgraph/registry.py index ecf796ad..656c4876 100644 --- a/fairgraph/registry.py +++ b/fairgraph/registry.py @@ -65,8 +65,7 @@ def __new__(meta, name, bases, class_dict): else: # Fallback for non-versioned paths or test classes class_dict["class_name"] = ".".join( - module.replace("fairgraph.openminds", f"openminds.{OPENMINDS_VERSION}").split(".")[:3] - + [name] + module.replace("fairgraph.openminds", f"openminds.{OPENMINDS_VERSION}").split(".")[:3] + [name] ) class_dict["preferred_import_path"] = class_dict["class_name"] cls = Registry.__new__(meta, name, bases, class_dict) diff --git a/fairgraph/utility/activity_log.py b/fairgraph/utility/activity_log.py index 194b5ded..5f347584 100644 --- a/fairgraph/utility/activity_log.py +++ b/fairgraph/utility/activity_log.py @@ -56,13 +56,7 @@ def __repr__(self): return f"{self.type}: {self.cls}({self.id}) in '{self.space}'" def as_dict(self): - return { - "cls": self.cls, - "id": self.id, - "delta": self.delta, - "space": self.space, - "type_": self.type - } + return {"cls": self.cls, "id": self.id, "delta": self.delta, "space": self.space, "type_": self.type} class ActivityLog: diff --git a/fairgraph/utility/name_matching.py b/fairgraph/utility/name_matching.py index 3a594d69..fa9cf3c2 100644 --- a/fairgraph/utility/name_matching.py +++ b/fairgraph/utility/name_matching.py @@ -8,9 +8,9 @@ uncomment the import line, and bump ``openminds>=`` in pyproject.toml. Everything after the block is fairgraph-specific: it *calls* the helpers above rather than -restating anything they know, so the swap changes no behaviour. +restating anything they know, so the swap changes no behaviour. -While the copy is in place, ``TestParityWithOpenMINDS`` in ``test_name_matching.py`` +While the copy is in place, ``TestParityWithOpenMINDS`` in ``test_name_matching.py`` guards against it drifting from the original. """ @@ -126,7 +126,7 @@ def matches_name( def _fold_maps() -> Tuple[Dict[str, Set[str]], Dict[str, Set[str]]]: """ - Return (single, multi): mappings from a plain-letter form to the characters that fold onto it, + Return (single, multi): mappings from a plain-letter form to the characters that fold onto it, split by whether that form is one character ("u" <- "ù", "ü", ...) or several ("ss" <- "ß", "ae" <- "æ", ...). Built by calling `remove_accents()`, so it cannot drift from it. @@ -156,8 +156,8 @@ def _expand(text: str, case_sensitive: bool, ignore_accents: bool) -> str: Turn a search string into a regular expression matching every spelling of it that `matches_name()` would consider equal, under the given options. - The KG's REGEX filter is always case-insensitive, so case is not expressed here; - it is enforced by the local `matches_name()` pass instead. + The KG's REGEX filter is always case-insensitive, so case is not expressed here; + it is enforced by the local `matches_name()` pass instead. What must be expressed is the folding of accented and special letters, which the KG does not do. """ single, multi = _fold_maps() diff --git a/test/test_client.py b/test/test_client.py index b7bae622..2c88b8da 100644 --- a/test/test_client.py +++ b/test/test_client.py @@ -488,16 +488,14 @@ def contribute_to_partial_replacement(instance_id, payload, extended_response_co # 2. Re-fetch via from_id. Before the fix, this would have returned # stale cached data with no studiedSpecimen. dsv2 = DatasetVersion.from_id(self.uuid, offline_kg_client, scope="any") - assert dsv2.studied_specimens is not None, ( - "re-fetched object must see the link added by the prior save" - ) + assert dsv2.studied_specimens is not None, "re-fetched object must see the link added by the prior save" # 3. Unlink and save. The PATCH must clear studiedSpecimen on the server. dsv2.studied_specimens = None dsv2.save(offline_kg_client, space="myspace", recursive=False) - assert studied_specimen_path not in server_state, ( - "second save should have sent a PATCH that cleared studiedSpecimen" - ) + assert ( + studied_specimen_path not in server_state + ), "second save should have sent a PATCH that cleared studiedSpecimen" def test_save_marks_raw_remote_data_stale(self, offline_kg_client, mocker): """After a successful update/replace, `_raw_remote_data` must be set @@ -537,9 +535,7 @@ def contribute_to_partial_replacement(instance_id, payload, extended_response_co dsv.short_name = "updated" dsv.save(offline_kg_client, space="myspace", recursive=False) - assert dsv._raw_remote_data is None, ( - "_raw_remote_data must be invalidated after a successful update" - ) + assert dsv._raw_remote_data is None, "_raw_remote_data must be invalidated after a successful update" class TestSpaceInfoOffline: @@ -559,9 +555,7 @@ def _client_listing(self, mocker, mock_client, items): return mock_client def test_maps_known_types_to_classes_and_unknown_types_to_iris(self, mock_client, mocker): - client = self._client_listing( - mocker, mock_client, [(self.known_type, 3), (self.unknown_type, 7)] - ) + client = self._client_listing(mocker, mock_client, [(self.known_type, 3), (self.unknown_type, 7)]) info = KGClient.space_info(client, "myspace", release_status="in progress") @@ -577,9 +571,7 @@ def test_unknown_type_alone_does_not_raise(self, mock_client, mocker): # listing raise ValueError. client = self._client_listing(mocker, mock_client, [(self.unknown_type, 1)]) - assert KGClient.space_info(client, "myspace", release_status="in progress") == { - self.unknown_type: 1 - } + assert KGClient.space_info(client, "myspace", release_status="in progress") == {self.unknown_type: 1} def test_clean_space_lists_both_kinds_then_aborts(self, mock_client, mocker, capsys): # clean_space() renders a label for every entry, so it has to cope with string diff --git a/test/test_name_matching.py b/test/test_name_matching.py index 0dca226b..4d6b3827 100644 --- a/test/test_name_matching.py +++ b/test/test_name_matching.py @@ -3,12 +3,12 @@ Most of this covers fairgraph's own code and is unaffected by where the name-matching helpers come from. -Four classes are tied to the temporary copy of the openMINDS helpers that `name_matching` carries, and +Four classes are tied to the temporary copy of the openMINDS helpers that `name_matching` carries, and should be deleted/renamed as follows when that copy is replaced by an import: - `TestRemoveAccents`, `TestMatchesName` and `TestNormalizeName` test the copied helpers themselves, and become openMINDS' business rather than ours; delete them. -- `TestParityWithOpenMINDS` is the guard against the copy drifting from the original. +- `TestParityWithOpenMINDS` is the guard against the copy drifting from the original. Once there is nothing to drift, it is still valuable as a check that the delegation is wired up and every argument forwarded, but should be renamed accordingly. """ diff --git a/test/test_openminds_computation.py b/test/test_openminds_computation.py index a2b41d85..20ce64f6 100644 --- a/test/test_openminds_computation.py +++ b/test/test_openminds_computation.py @@ -73,7 +73,9 @@ def test_generate_query(self, mock_client): "path": "https://openminds.om-i.org/props/hardware", "propertyName": "Qhardware", "required": True, - "structure": [{"path": "http://schema.org/identifier", "filter": {"op": "CONTAINS", "value": "some_id"}}], + "structure": [ + {"path": "http://schema.org/identifier", "filter": {"op": "CONTAINS", "value": "some_id"}} + ], }, { "path": "https://openminds.om-i.org/props/name", @@ -85,7 +87,9 @@ def test_generate_query(self, mock_client): "path": "https://openminds.om-i.org/props/software", "propertyName": "Qsoftware", "required": True, - "structure": [{"path": "http://schema.org/identifier", "filter": {"op": "CONTAINS", "value": "another_id"}}], + "structure": [ + {"path": "http://schema.org/identifier", "filter": {"op": "CONTAINS", "value": "another_id"}} + ], }, ], } diff --git a/test/test_openminds_versions.py b/test/test_openminds_versions.py index d0cbfa10..58304b6f 100644 --- a/test/test_openminds_versions.py +++ b/test/test_openminds_versions.py @@ -94,12 +94,12 @@ def test_backwards_compat_submodules_are_aliased(): import importlib legacy_to_v4 = [ - ("fairgraph.openminds.core.products.dataset_version", - "fairgraph.openminds.v4.core.products.dataset_version"), - ("fairgraph.openminds.sands.atlas.brain_atlas_version", - "fairgraph.openminds.v4.sands.atlas.brain_atlas_version"), - ("fairgraph.openminds.controlled_terms.species", - "fairgraph.openminds.v4.controlled_terms.species"), + ("fairgraph.openminds.core.products.dataset_version", "fairgraph.openminds.v4.core.products.dataset_version"), + ( + "fairgraph.openminds.sands.atlas.brain_atlas_version", + "fairgraph.openminds.v4.sands.atlas.brain_atlas_version", + ), + ("fairgraph.openminds.controlled_terms.species", "fairgraph.openminds.v4.controlled_terms.species"), ] for legacy_name, v4_name in legacy_to_v4: legacy_mod = importlib.import_module(legacy_name) @@ -187,8 +187,7 @@ def test_from_id_uses_client_version(): """KGObject.from_id passes the client's openminds_version to lookup_type.""" mock_uri = "http://example.org/00000000-0000-0000-0000-000000000000" - for version, expected_module_prefix in (("v4", "fairgraph.openminds.v4"), - ("v5", "fairgraph.openminds.v5")): + for version, expected_module_prefix in (("v4", "fairgraph.openminds.v4"), ("v5", "fairgraph.openminds.v5")): client = MockKGClient(openminds_version=version) sentinel = object() captured = {} diff --git a/test/test_queries.py b/test/test_queries.py index d761dfac..43c84e4d 100644 --- a/test/test_queries.py +++ b/test/test_queries.py @@ -655,10 +655,10 @@ def test_execute_query_with_multi_element_path_with_path_elements(kg_client): ], name="dataset", expect_single=True, - filter=Filter("CONTAINS", value=DATASET_ID) + filter=Filter("CONTAINS", value=DATASET_ID), ), QueryProperty("https://openminds.om-i.org/props/name", name="name"), - ] + ], ) expected = { "@context": { @@ -697,10 +697,7 @@ def test_execute_query_with_multi_element_path_with_path_elements(kg_client): "@id", ], }, - { - "propertyName": "name", - "path": "https://openminds.om-i.org/props/name" - }, + {"propertyName": "name", "path": "https://openminds.om-i.org/props/name"}, ], } assert query.serialize() == expected @@ -710,8 +707,7 @@ def test_execute_query_with_multi_element_path_with_path_elements(kg_client): pagination=Pagination(start=0, size=5), ) assert len(response.data) == 5 - assert all(item["dataset"] == f"https://kg.ebrains.eu/api/instances/{DATASET_ID}" - for item in response.data) + assert all(item["dataset"] == f"https://kg.ebrains.eu/api/instances/{DATASET_ID}" for item in response.data) def test_generate_query_with_regex_filter(mock_client): @@ -824,7 +820,9 @@ def test_equals_filters_a_link_by_id_with_equals(mock_client): def test_equals_rejects_a_non_id_string_for_a_link(mock_client): # as for a plain string or a Regex with pytest.raises(TypeError): - omcore.DatasetVersion.generate_query(client=mock_client, space=None, filters={"is_new_version_of": Equals("FOO")}) + omcore.DatasetVersion.generate_query( + client=mock_client, space=None, filters={"is_new_version_of": Equals("FOO")} + ) def test_existence_query_filters_strings_with_equals(mock_client): @@ -883,9 +881,7 @@ def test_existence_query_with_list_of_embedded_nodes(mock_client): props = _existence_filter_properties(omcore.File, file, mock_client, "hashes") assert [prop["propertyName"] for prop in props] == ["Qhashes1", "Qhashes2"] # the filters for each hash are kept together, so that they must match the same hash in the KG - assert [ - {sub_prop["propertyName"]: sub_prop["filter"] for sub_prop in prop["structure"]} for prop in props - ] == [ + assert [{sub_prop["propertyName"]: sub_prop["filter"] for sub_prop in prop["structure"]} for prop in props] == [ {"Qalgorithm": {"op": "EQUALS", "value": algorithm}, "Qdigest": {"op": "EQUALS", "value": digest}} for algorithm, digest in (("MD5", "abc"), ("SHA1", "def")) ] diff --git a/test/test_utility.py b/test/test_utility.py index 1a5d5740..bbf440d9 100644 --- a/test/test_utility.py +++ b/test/test_utility.py @@ -96,7 +96,7 @@ def test_normalize_data(): }, "familyName": "Oakenshield", "givenName": "Thorin", - "alternateName": None + "alternateName": None, } context = {"@vocab": "https://openminds.ebrains.eu/vocab/"} expected = { @@ -111,7 +111,7 @@ def test_normalize_data(): }, "https://openminds.ebrains.eu/vocab/familyName": "Oakenshield", "https://openminds.ebrains.eu/vocab/givenName": "Thorin", - "https://openminds.ebrains.eu/vocab/alternateName": None + "https://openminds.ebrains.eu/vocab/alternateName": None, } assert normalize_data(data, context) == expected @@ -135,11 +135,7 @@ def test_initialise_instances_resolves_cross_references(): from fairgraph.kgproxy import KGProxy # The library instances were recast to typed fairgraph objects. - pe_by_id = { - obj.id: obj - for obj in vars(ParcellationEntity).values() - if isinstance(obj, ParcellationEntity) - } + pe_by_id = {obj.id: obj for obj in vars(ParcellationEntity).values() if isinstance(obj, ParcellationEntity)} assert pe_by_id, "no ParcellationEntity library instances were recast" assert all(isinstance(pe, fairgraph.KGObject) for pe in pe_by_id.values()) From a51853297060f293f88991121527f3b28e279448 Mon Sep 17 00:00:00 2001 From: Andrew Davison Date: Sat, 17 Oct 2026 23:42:50 +0200 Subject: [PATCH 2/2] Remove deprecated aliases from the renaming of fields to properties Remove the fairgraph.fields module and the class attributes fields, field_names, required_field_names and existence_query_fields. The fairgraph.fields module has not worked since 0.13.0, as it imports fairgraph.properties, which no longer exists. The deprecation warnings said that these names would be removed in a future release. --- doc/release_notes.rst | 9 +++++++++ fairgraph/fields.py | 25 ------------------------- fairgraph/registry.py | 37 ------------------------------------- 3 files changed, 9 insertions(+), 62 deletions(-) delete mode 100644 fairgraph/fields.py diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 087950a0..8bf82261 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -55,6 +55,15 @@ Changes in behaviour is now sorted by ``family_name``. The ordering of results is now described in :doc:`queries` (`#129 `_). +- The remaining deprecated names from the renaming of "fields" to "properties" in version 0.12.0 have been removed: + + - the class attributes ``fields``, ``field_names``, ``required_field_names`` and ``existence_query_fields``; + use ``properties`` (with ``reverse_properties``, or ``all_properties`` for both), ``property_names``, + ``required_property_names`` and ``existence_query_properties`` instead. + Note that ``required_field_names`` returned the names of all properties, not only the required ones. + - the ``fairgraph.fields`` module, which has not worked since version 0.13.0, as importing it raised + :exc:`ModuleNotFoundError`. Use ``openminds.properties.Property`` in place of ``Field``. + Bug fixes --------- diff --git a/fairgraph/fields.py b/fairgraph/fields.py deleted file mode 100644 index 6239a66a..00000000 --- a/fairgraph/fields.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2018-2026 CNRS and fairgraph authors and/or their employers - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from warnings import warn - -from .properties import Property as Field - -warn( - "The 'Field' class has been renamed to 'Property' " - "for consistency with openMINDS. " - "Use of 'Field' will still work until the next release, " - "when this alias will be removed.", - DeprecationWarning, -) diff --git a/fairgraph/registry.py b/fairgraph/registry.py index 656c4876..7923e3a1 100644 --- a/fairgraph/registry.py +++ b/fairgraph/registry.py @@ -21,7 +21,6 @@ from __future__ import annotations from itertools import chain from typing import TYPE_CHECKING, Union, List, Dict -from warnings import warn from openminds.properties import Property from openminds.registry import Registry @@ -109,42 +108,6 @@ def all_property_names(cls): def reverse_property_names(cls): return [p.name for p in cls.reverse_properties] - @property - def fields(cls): - warn( - "Use of the 'fields' attribute is deprecated, it will be removed in a future release. " - "Use 'properties' instead", - DeprecationWarning, - ) - return cls.properties + cls.reverse_properties - - @property - def field_names(cls): - warn( - "Use of the 'field_names' attribute is deprecated, it will be removed in a future release. " - "Use 'property_names' instead", - DeprecationWarning, - ) - return cls.property_names - - @property - def required_field_names(cls): - warn( - "Use of the 'required_field_names' attribute is deprecated, it will be removed in a future release. " - "Use 'required_property_names' instead", - DeprecationWarning, - ) - return cls.property_names - - @property - def existence_query_fields(cls): - warn( - "Use of the 'existence_query_fields' attribute is deprecated, it will be removed in a future release. " - "Use 'existence_query_properties' instead", - DeprecationWarning, - ) - return cls.existence_query_properties - # Deprecated alias Node = NodeMeta