Skip to content

Commit 052b33f

Browse files
committed
Release 0.13.5
1 parent 6c5adb9 commit 052b33f

7 files changed

Lines changed: 73 additions & 9 deletions

File tree

codemeta.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
"license": "https://spdx.org/licenses/Apache-2.0.html",
55
"codeRepository": "https://github.com/HumanBrainProject/fairgraph",
66
"contIntegration": "https://github.com/HumanBrainProject/fairgraph/actions",
7-
"dateModified": "2026-05-14",
8-
"downloadUrl": "https://files.pythonhosted.org/packages/d7/f6/460a038f133fd922eac20d544a14fe5c7b1a214ce9f02c9f53d2392e9291/fairgraph-0.13.4.tar.gz",
7+
"dateModified": "2026-05-26",
8+
"downloadUrl": null,
99
"issueTracker": "https://github.com/HumanBrainProject/fairgraph/issues",
1010
"name": "fairgraph",
11-
"version": "0.13.4",
12-
"identifier": "https://pypi.org/project/fairgraph/0.13.4/",
11+
"version": "0.13.5",
12+
"identifier": "https://pypi.org/project/fairgraph/0.13.5/",
1313
"description": "Python API for the EBRAINS Knowledge Graph",
1414
"applicationCategory": "neuroscience",
15-
"releaseNotes": "https://fairgraph.readthedocs.io/en/latest/release_notes.html#version-0-13-4",
15+
"releaseNotes": "https://fairgraph.readthedocs.io/en/latest/release_notes.html#version-0-13-5",
1616
"funding": "https://cordis.europa.eu/project/id/945539",
1717
"developmentStatus": "active",
1818
"referencePublication": null,

doc/release_notes.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,19 @@ Release notes
33
=============
44

55

6+
Version 0.13.5
7+
==============
8+
9+
Bug fixes in this release:
10+
11+
- Fixed a bug where :meth:`~fairgraph.kgobject.KGObject.save` could silently
12+
no-op after re-fetching an object via :meth:`~fairgraph.kgobject.KGObject.from_id`,
13+
because :attr:`KGClient.cache` was not invalidated by writes
14+
(`#110 <https://github.com/HumanBrainProject/fairgraph/issues/110>`_).
15+
- Fixed the repository IRI used by the dataset version ``download()`` method
16+
(`#109 <https://github.com/HumanBrainProject/fairgraph/pull/109>`_).
17+
18+
619
Version 0.13.4
720
==============
821

fairgraph/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from .collection import Collection
2929
from . import client, errors, openminds, utility
3030

31-
__version__ = "0.13.4"
31+
__version__ = "0.13.5"
3232

3333
utility.initialise_instances(
3434
[

fairgraph/kgobject.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,10 @@ def save(
763763
raise
764764
else:
765765
self.remote_data = local_data
766+
# Mark the raw server-side document as stale, to match
767+
# the cache invalidation done in client.replace_instance.
768+
# It will be re-fetched on demand by exists() if needed.
769+
self._raw_remote_data = None
766770
else:
767771
modified_data = self.modified_data()
768772
if modified_data:
@@ -792,6 +796,11 @@ def save(
792796
raise
793797
else:
794798
self.remote_data = local_data
799+
# Mark the raw server-side document as stale, to
800+
# match the cache invalidation done in
801+
# client.update_instance. It will be re-fetched
802+
# on demand by exists() if needed.
803+
self._raw_remote_data = None
795804
if activity_log:
796805
activity_log.update(
797806
item=self,

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "fairgraph"
3-
version = "0.13.4"
3+
version = "0.13.5"
44
description = "Python API for the EBRAINS Knowledge Graph"
55
readme = "README.md"
66
authors = [

test/test_client.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,3 +346,45 @@ def contribute_to_partial_replacement(instance_id, payload, extended_response_co
346346
assert studied_specimen_path not in server_state, (
347347
"second save should have sent a PATCH that cleared studiedSpecimen"
348348
)
349+
350+
def test_save_marks_raw_remote_data_stale(self, offline_kg_client, mocker):
351+
"""After a successful update/replace, `_raw_remote_data` must be set
352+
to None so it can't be silently out of sync with the cache and with
353+
the actual server state. exists() repopulates it on demand."""
354+
from fairgraph.openminds.core import DatasetVersion
355+
356+
server_state = {
357+
"@id": self.uri,
358+
"@type": ["https://openminds.om-i.org/types/DatasetVersion"],
359+
"http://schema.org/identifier": [self.uri],
360+
"https://core.kg.ebrains.eu/vocab/meta/space": "myspace",
361+
"https://openminds.om-i.org/props/shortName": "original",
362+
}
363+
364+
def get_by_id(stage, instance_id, extended_response_configuration):
365+
return MockKGResponse(dict(server_state))
366+
367+
def contribute_to_partial_replacement(instance_id, payload, extended_response_configuration):
368+
for key, value in payload.items():
369+
if value is None:
370+
server_state.pop(key, None)
371+
else:
372+
server_state[key] = value
373+
return MockKGResponse(dict(server_state))
374+
375+
mocker.patch.object(offline_kg_client._kg_client.instances, "get_by_id", get_by_id)
376+
mocker.patch.object(
377+
offline_kg_client._kg_client.instances,
378+
"contribute_to_partial_replacement",
379+
contribute_to_partial_replacement,
380+
)
381+
382+
dsv = DatasetVersion.from_id(self.uuid, offline_kg_client, scope="any")
383+
assert dsv._raw_remote_data is not None # populated by from_id
384+
385+
dsv.short_name = "updated"
386+
dsv.save(offline_kg_client, space="myspace", recursive=False)
387+
388+
assert dsv._raw_remote_data is None, (
389+
"_raw_remote_data must be invalidated after a successful update"
390+
)

test/test_openminds_core.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -884,12 +884,12 @@ def test_dataset_version_download(mocker):
884884
lambda url, local_filename: (local_filename, None),
885885
)
886886
fake_dsv = omcore.DatasetVersion(
887-
repository=omcore.FileRepository(iri=IRI("https://data-proxy.ebrains.eu/api/v1/public/foo/bar"))
887+
repository=omcore.FileRepository(iri=IRI("https://data-proxy.ebrains.eu/api/v1/buckets/foo/bar"))
888888
)
889889
local_dir = tempfile.mkdtemp()
890890
local_filename, repository_url = fake_dsv.download(local_dir, client=None, accept_terms_of_use=True)
891891
os.rmdir(local_dir)
892-
assert repository_url == "https://data-proxy.ebrains.eu/api/v1/public/foo/bar"
892+
assert repository_url == "https://data-proxy.ebrains.eu/api/v1/buckets/foo/bar"
893893
assert str(local_filename) == os.path.join(local_dir, "bar.zip")
894894

895895

0 commit comments

Comments
 (0)