fairgraph 0.13.0__py3-none-any.whl

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.
Files changed (267) hide show
  1. fairgraph/__init__.py +61 -0
  2. fairgraph/base.py +104 -0
  3. fairgraph/caching.py +52 -0
  4. fairgraph/client.py +867 -0
  5. fairgraph/collection.py +104 -0
  6. fairgraph/embedded.py +122 -0
  7. fairgraph/errors.py +47 -0
  8. fairgraph/fields.py +11 -0
  9. fairgraph/kgobject.py +1087 -0
  10. fairgraph/kgproxy.py +178 -0
  11. fairgraph/kgquery.py +151 -0
  12. fairgraph/node.py +488 -0
  13. fairgraph/openminds/__init__.py +1 -0
  14. fairgraph/openminds/chemicals/__init__.py +40 -0
  15. fairgraph/openminds/chemicals/amount_of_chemical.py +23 -0
  16. fairgraph/openminds/chemicals/chemical_mixture.py +72 -0
  17. fairgraph/openminds/chemicals/chemical_substance.py +67 -0
  18. fairgraph/openminds/chemicals/product_source.py +57 -0
  19. fairgraph/openminds/computation/__init__.py +53 -0
  20. fairgraph/openminds/computation/data_analysis.py +104 -0
  21. fairgraph/openminds/computation/data_copy.py +104 -0
  22. fairgraph/openminds/computation/environment.py +66 -0
  23. fairgraph/openminds/computation/generic_computation.py +104 -0
  24. fairgraph/openminds/computation/hardware_system.py +53 -0
  25. fairgraph/openminds/computation/launch_configuration.py +68 -0
  26. fairgraph/openminds/computation/local_file.py +83 -0
  27. fairgraph/openminds/computation/model_validation.py +107 -0
  28. fairgraph/openminds/computation/optimization.py +104 -0
  29. fairgraph/openminds/computation/simulation.py +104 -0
  30. fairgraph/openminds/computation/software_agent.py +81 -0
  31. fairgraph/openminds/computation/validation_test.py +105 -0
  32. fairgraph/openminds/computation/validation_test_version.py +180 -0
  33. fairgraph/openminds/computation/visualization.py +104 -0
  34. fairgraph/openminds/computation/workflow_execution.py +44 -0
  35. fairgraph/openminds/computation/workflow_recipe.py +95 -0
  36. fairgraph/openminds/computation/workflow_recipe_version.py +185 -0
  37. fairgraph/openminds/controlled_terms/__init__.py +116 -0
  38. fairgraph/openminds/controlled_terms/action_status_type.py +97 -0
  39. fairgraph/openminds/controlled_terms/age_category.py +89 -0
  40. fairgraph/openminds/controlled_terms/analysis_technique.py +108 -0
  41. fairgraph/openminds/controlled_terms/anatomical_axes_orientation.py +89 -0
  42. fairgraph/openminds/controlled_terms/anatomical_identification_type.py +89 -0
  43. fairgraph/openminds/controlled_terms/anatomical_plane.py +89 -0
  44. fairgraph/openminds/controlled_terms/annotation_criteria_type.py +89 -0
  45. fairgraph/openminds/controlled_terms/annotation_type.py +89 -0
  46. fairgraph/openminds/controlled_terms/atlas_type.py +88 -0
  47. fairgraph/openminds/controlled_terms/auditory_stimulus_type.py +127 -0
  48. fairgraph/openminds/controlled_terms/biological_order.py +117 -0
  49. fairgraph/openminds/controlled_terms/biological_process.py +79 -0
  50. fairgraph/openminds/controlled_terms/biological_sex.py +132 -0
  51. fairgraph/openminds/controlled_terms/breeding_type.py +127 -0
  52. fairgraph/openminds/controlled_terms/cell_culture_type.py +117 -0
  53. fairgraph/openminds/controlled_terms/cell_type.py +151 -0
  54. fairgraph/openminds/controlled_terms/chemical_mixture_type.py +89 -0
  55. fairgraph/openminds/controlled_terms/colormap.py +79 -0
  56. fairgraph/openminds/controlled_terms/contribution_type.py +79 -0
  57. fairgraph/openminds/controlled_terms/cranial_window_construction_type.py +89 -0
  58. fairgraph/openminds/controlled_terms/cranial_window_reinforcement_type.py +89 -0
  59. fairgraph/openminds/controlled_terms/criteria_quality_type.py +89 -0
  60. fairgraph/openminds/controlled_terms/data_type.py +89 -0
  61. fairgraph/openminds/controlled_terms/device_type.py +94 -0
  62. fairgraph/openminds/controlled_terms/difference_measure.py +89 -0
  63. fairgraph/openminds/controlled_terms/disease.py +142 -0
  64. fairgraph/openminds/controlled_terms/disease_model.py +142 -0
  65. fairgraph/openminds/controlled_terms/educational_level.py +79 -0
  66. fairgraph/openminds/controlled_terms/electrical_stimulus_type.py +137 -0
  67. fairgraph/openminds/controlled_terms/ethics_assessment.py +79 -0
  68. fairgraph/openminds/controlled_terms/experimental_approach.py +79 -0
  69. fairgraph/openminds/controlled_terms/file_bundle_grouping.py +99 -0
  70. fairgraph/openminds/controlled_terms/file_repository_type.py +89 -0
  71. fairgraph/openminds/controlled_terms/file_usage_role.py +89 -0
  72. fairgraph/openminds/controlled_terms/genetic_strain_type.py +127 -0
  73. fairgraph/openminds/controlled_terms/gustatory_stimulus_type.py +127 -0
  74. fairgraph/openminds/controlled_terms/handedness.py +127 -0
  75. fairgraph/openminds/controlled_terms/language.py +88 -0
  76. fairgraph/openminds/controlled_terms/laterality.py +94 -0
  77. fairgraph/openminds/controlled_terms/learning_resource_type.py +88 -0
  78. fairgraph/openminds/controlled_terms/measured_quantity.py +89 -0
  79. fairgraph/openminds/controlled_terms/measured_signal_type.py +79 -0
  80. fairgraph/openminds/controlled_terms/meta_data_model_type.py +88 -0
  81. fairgraph/openminds/controlled_terms/model_abstraction_level.py +89 -0
  82. fairgraph/openminds/controlled_terms/model_scope.py +89 -0
  83. fairgraph/openminds/controlled_terms/molecular_entity.py +142 -0
  84. fairgraph/openminds/controlled_terms/mri_pulse_sequence.py +98 -0
  85. fairgraph/openminds/controlled_terms/mri_weighting.py +98 -0
  86. fairgraph/openminds/controlled_terms/olfactory_stimulus_type.py +127 -0
  87. fairgraph/openminds/controlled_terms/operating_device.py +79 -0
  88. fairgraph/openminds/controlled_terms/operating_system.py +88 -0
  89. fairgraph/openminds/controlled_terms/optical_stimulus_type.py +127 -0
  90. fairgraph/openminds/controlled_terms/organ.py +161 -0
  91. fairgraph/openminds/controlled_terms/organism_substance.py +151 -0
  92. fairgraph/openminds/controlled_terms/organism_system.py +117 -0
  93. fairgraph/openminds/controlled_terms/patch_clamp_variation.py +89 -0
  94. fairgraph/openminds/controlled_terms/preparation_type.py +98 -0
  95. fairgraph/openminds/controlled_terms/product_accessibility.py +79 -0
  96. fairgraph/openminds/controlled_terms/programming_language.py +88 -0
  97. fairgraph/openminds/controlled_terms/qualitative_overlap.py +79 -0
  98. fairgraph/openminds/controlled_terms/semantic_data_type.py +79 -0
  99. fairgraph/openminds/controlled_terms/service.py +89 -0
  100. fairgraph/openminds/controlled_terms/setup_type.py +89 -0
  101. fairgraph/openminds/controlled_terms/software_application_category.py +79 -0
  102. fairgraph/openminds/controlled_terms/software_feature.py +79 -0
  103. fairgraph/openminds/controlled_terms/species.py +143 -0
  104. fairgraph/openminds/controlled_terms/stimulation_approach.py +98 -0
  105. fairgraph/openminds/controlled_terms/stimulation_technique.py +98 -0
  106. fairgraph/openminds/controlled_terms/subcellular_entity.py +143 -0
  107. fairgraph/openminds/controlled_terms/subject_attribute.py +89 -0
  108. fairgraph/openminds/controlled_terms/tactile_stimulus_type.py +127 -0
  109. fairgraph/openminds/controlled_terms/technique.py +108 -0
  110. fairgraph/openminds/controlled_terms/term_suggestion.py +121 -0
  111. fairgraph/openminds/controlled_terms/terminology.py +89 -0
  112. fairgraph/openminds/controlled_terms/tissue_sample_attribute.py +89 -0
  113. fairgraph/openminds/controlled_terms/tissue_sample_type.py +127 -0
  114. fairgraph/openminds/controlled_terms/type_of_uncertainty.py +89 -0
  115. fairgraph/openminds/controlled_terms/uberon_parcellation.py +153 -0
  116. fairgraph/openminds/controlled_terms/unit_of_measurement.py +108 -0
  117. fairgraph/openminds/controlled_terms/visual_stimulus_type.py +127 -0
  118. fairgraph/openminds/controlledterms.py +6 -0
  119. fairgraph/openminds/core/__init__.py +107 -0
  120. fairgraph/openminds/core/actors/__init__.py +7 -0
  121. fairgraph/openminds/core/actors/account_information.py +44 -0
  122. fairgraph/openminds/core/actors/affiliation.py +30 -0
  123. fairgraph/openminds/core/actors/consortium.py +175 -0
  124. fairgraph/openminds/core/actors/contact_information.py +43 -0
  125. fairgraph/openminds/core/actors/contribution.py +23 -0
  126. fairgraph/openminds/core/actors/organization.py +199 -0
  127. fairgraph/openminds/core/actors/person.py +236 -0
  128. fairgraph/openminds/core/data/__init__.py +13 -0
  129. fairgraph/openminds/core/data/content_type.py +107 -0
  130. fairgraph/openminds/core/data/content_type_pattern.py +53 -0
  131. fairgraph/openminds/core/data/copyright.py +23 -0
  132. fairgraph/openminds/core/data/file.py +275 -0
  133. fairgraph/openminds/core/data/file_archive.py +71 -0
  134. fairgraph/openminds/core/data/file_bundle.py +150 -0
  135. fairgraph/openminds/core/data/file_path_pattern.py +23 -0
  136. fairgraph/openminds/core/data/file_repository.py +99 -0
  137. fairgraph/openminds/core/data/file_repository_structure.py +51 -0
  138. fairgraph/openminds/core/data/hash.py +23 -0
  139. fairgraph/openminds/core/data/license.py +77 -0
  140. fairgraph/openminds/core/data/measurement.py +45 -0
  141. fairgraph/openminds/core/data/service_link.py +49 -0
  142. fairgraph/openminds/core/digital_identifier/__init__.py +11 -0
  143. fairgraph/openminds/core/digital_identifier/doi.py +98 -0
  144. fairgraph/openminds/core/digital_identifier/gridid.py +41 -0
  145. fairgraph/openminds/core/digital_identifier/handle.py +52 -0
  146. fairgraph/openminds/core/digital_identifier/identifiers_dot_org_id.py +41 -0
  147. fairgraph/openminds/core/digital_identifier/isbn.py +88 -0
  148. fairgraph/openminds/core/digital_identifier/issn.py +63 -0
  149. fairgraph/openminds/core/digital_identifier/orcid.py +41 -0
  150. fairgraph/openminds/core/digital_identifier/rorid.py +41 -0
  151. fairgraph/openminds/core/digital_identifier/rrid.py +55 -0
  152. fairgraph/openminds/core/digital_identifier/stock_number.py +23 -0
  153. fairgraph/openminds/core/digital_identifier/swhid.py +48 -0
  154. fairgraph/openminds/core/miscellaneous/__init__.py +7 -0
  155. fairgraph/openminds/core/miscellaneous/comment.py +47 -0
  156. fairgraph/openminds/core/miscellaneous/funding.py +70 -0
  157. fairgraph/openminds/core/miscellaneous/quantitative_value.py +43 -0
  158. fairgraph/openminds/core/miscellaneous/quantitative_value_array.py +49 -0
  159. fairgraph/openminds/core/miscellaneous/quantitative_value_range.py +43 -0
  160. fairgraph/openminds/core/miscellaneous/research_product_group.py +26 -0
  161. fairgraph/openminds/core/miscellaneous/web_resource.py +104 -0
  162. fairgraph/openminds/core/products/__init__.py +12 -0
  163. fairgraph/openminds/core/products/dataset.py +95 -0
  164. fairgraph/openminds/core/products/dataset_version.py +240 -0
  165. fairgraph/openminds/core/products/meta_data_model.py +95 -0
  166. fairgraph/openminds/core/products/meta_data_model_version.py +168 -0
  167. fairgraph/openminds/core/products/model.py +103 -0
  168. fairgraph/openminds/core/products/model_version.py +235 -0
  169. fairgraph/openminds/core/products/project.py +56 -0
  170. fairgraph/openminds/core/products/setup.py +69 -0
  171. fairgraph/openminds/core/products/software.py +95 -0
  172. fairgraph/openminds/core/products/software_version.py +226 -0
  173. fairgraph/openminds/core/products/web_service.py +103 -0
  174. fairgraph/openminds/core/products/web_service_version.py +182 -0
  175. fairgraph/openminds/core/research/__init__.py +17 -0
  176. fairgraph/openminds/core/research/behavioral_protocol.py +69 -0
  177. fairgraph/openminds/core/research/configuration.py +67 -0
  178. fairgraph/openminds/core/research/custom_property_set.py +27 -0
  179. fairgraph/openminds/core/research/numerical_property.py +23 -0
  180. fairgraph/openminds/core/research/property_value_list.py +71 -0
  181. fairgraph/openminds/core/research/protocol.py +67 -0
  182. fairgraph/openminds/core/research/protocol_execution.py +76 -0
  183. fairgraph/openminds/core/research/strain.py +90 -0
  184. fairgraph/openminds/core/research/string_property.py +23 -0
  185. fairgraph/openminds/core/research/subject.py +79 -0
  186. fairgraph/openminds/core/research/subject_group.py +91 -0
  187. fairgraph/openminds/core/research/subject_group_state.py +113 -0
  188. fairgraph/openminds/core/research/subject_state.py +138 -0
  189. fairgraph/openminds/core/research/tissue_sample.py +87 -0
  190. fairgraph/openminds/core/research/tissue_sample_collection.py +99 -0
  191. fairgraph/openminds/core/research/tissue_sample_collection_state.py +109 -0
  192. fairgraph/openminds/core/research/tissue_sample_state.py +127 -0
  193. fairgraph/openminds/ephys/__init__.py +39 -0
  194. fairgraph/openminds/ephys/activity/__init__.py +3 -0
  195. fairgraph/openminds/ephys/activity/cell_patching.py +73 -0
  196. fairgraph/openminds/ephys/activity/electrode_placement.py +67 -0
  197. fairgraph/openminds/ephys/activity/recording_activity.py +67 -0
  198. fairgraph/openminds/ephys/device/__init__.py +6 -0
  199. fairgraph/openminds/ephys/device/electrode.py +81 -0
  200. fairgraph/openminds/ephys/device/electrode_array.py +85 -0
  201. fairgraph/openminds/ephys/device/electrode_array_usage.py +105 -0
  202. fairgraph/openminds/ephys/device/electrode_usage.py +101 -0
  203. fairgraph/openminds/ephys/device/pipette.py +81 -0
  204. fairgraph/openminds/ephys/device/pipette_usage.py +123 -0
  205. fairgraph/openminds/ephys/entity/__init__.py +2 -0
  206. fairgraph/openminds/ephys/entity/channel.py +23 -0
  207. fairgraph/openminds/ephys/entity/recording.py +63 -0
  208. fairgraph/openminds/publications/__init__.py +47 -0
  209. fairgraph/openminds/publications/book.py +106 -0
  210. fairgraph/openminds/publications/chapter.py +100 -0
  211. fairgraph/openminds/publications/learning_resource.py +90 -0
  212. fairgraph/openminds/publications/live_paper.py +95 -0
  213. fairgraph/openminds/publications/live_paper_resource_item.py +58 -0
  214. fairgraph/openminds/publications/live_paper_section.py +57 -0
  215. fairgraph/openminds/publications/live_paper_version.py +177 -0
  216. fairgraph/openminds/publications/periodical.py +53 -0
  217. fairgraph/openminds/publications/publication_issue.py +44 -0
  218. fairgraph/openminds/publications/publication_volume.py +44 -0
  219. fairgraph/openminds/publications/scholarly_article.py +146 -0
  220. fairgraph/openminds/sands/__init__.py +57 -0
  221. fairgraph/openminds/sands/atlas/__init__.py +9 -0
  222. fairgraph/openminds/sands/atlas/atlas_annotation.py +52 -0
  223. fairgraph/openminds/sands/atlas/brain_atlas.py +113 -0
  224. fairgraph/openminds/sands/atlas/brain_atlas_version.py +213 -0
  225. fairgraph/openminds/sands/atlas/common_coordinate_space.py +121 -0
  226. fairgraph/openminds/sands/atlas/common_coordinate_space_version.py +243 -0
  227. fairgraph/openminds/sands/atlas/parcellation_entity.py +133 -0
  228. fairgraph/openminds/sands/atlas/parcellation_entity_version.py +162 -0
  229. fairgraph/openminds/sands/atlas/parcellation_terminology.py +38 -0
  230. fairgraph/openminds/sands/atlas/parcellation_terminology_version.py +38 -0
  231. fairgraph/openminds/sands/mathematical_shapes/__init__.py +3 -0
  232. fairgraph/openminds/sands/mathematical_shapes/circle.py +23 -0
  233. fairgraph/openminds/sands/mathematical_shapes/ellipse.py +27 -0
  234. fairgraph/openminds/sands/mathematical_shapes/rectangle.py +23 -0
  235. fairgraph/openminds/sands/miscellaneous/__init__.py +6 -0
  236. fairgraph/openminds/sands/miscellaneous/anatomical_target_position.py +40 -0
  237. fairgraph/openminds/sands/miscellaneous/coordinate_point.py +23 -0
  238. fairgraph/openminds/sands/miscellaneous/qualitative_relation_assessment.py +34 -0
  239. fairgraph/openminds/sands/miscellaneous/quantitative_relation_assessment.py +38 -0
  240. fairgraph/openminds/sands/miscellaneous/single_color.py +24 -0
  241. fairgraph/openminds/sands/miscellaneous/viewer_specification.py +40 -0
  242. fairgraph/openminds/sands/non_atlas/__init__.py +3 -0
  243. fairgraph/openminds/sands/non_atlas/custom_anatomical_entity.py +110 -0
  244. fairgraph/openminds/sands/non_atlas/custom_annotation.py +54 -0
  245. fairgraph/openminds/sands/non_atlas/custom_coordinate_space.py +67 -0
  246. fairgraph/openminds/specimen_prep/__init__.py +38 -0
  247. fairgraph/openminds/specimen_prep/activity/__init__.py +3 -0
  248. fairgraph/openminds/specimen_prep/activity/cranial_window_preparation.py +69 -0
  249. fairgraph/openminds/specimen_prep/activity/tissue_culture_preparation.py +67 -0
  250. fairgraph/openminds/specimen_prep/activity/tissue_sample_slicing.py +69 -0
  251. fairgraph/openminds/specimen_prep/device/__init__.py +2 -0
  252. fairgraph/openminds/specimen_prep/device/slicing_device.py +73 -0
  253. fairgraph/openminds/specimen_prep/device/slicing_device_usage.py +117 -0
  254. fairgraph/openminds/specimenprep.py +4 -0
  255. fairgraph/openminds/stimulation/__init__.py +38 -0
  256. fairgraph/openminds/stimulation/activity/__init__.py +1 -0
  257. fairgraph/openminds/stimulation/activity/stimulation_activity.py +67 -0
  258. fairgraph/openminds/stimulation/stimulus/__init__.py +1 -0
  259. fairgraph/openminds/stimulation/stimulus/ephys_stimulus.py +63 -0
  260. fairgraph/queries.py +499 -0
  261. fairgraph/registry.py +123 -0
  262. fairgraph/utility.py +607 -0
  263. fairgraph-0.13.0.dist-info/METADATA +222 -0
  264. fairgraph-0.13.0.dist-info/RECORD +267 -0
  265. fairgraph-0.13.0.dist-info/WHEEL +5 -0
  266. fairgraph-0.13.0.dist-info/licenses/LICENSE.txt +177 -0
  267. fairgraph-0.13.0.dist-info/top_level.txt +1 -0
fairgraph/kgproxy.py ADDED
@@ -0,0 +1,178 @@
1
+ """
2
+ This module provides the KGProxy class, which represents a
3
+ KGObject whose type and identifier are known but whose other metadata
4
+ have not been retrieved from the KG.
5
+ """
6
+
7
+ # Copyright 2018-2024 CNRS
8
+
9
+ # Licensed under the Apache License, Version 2.0 (the "License");
10
+ # you may not use this file except in compliance with the License.
11
+ # You may obtain a copy of the License at
12
+
13
+ # http://www.apache.org/licenses/LICENSE-2.0
14
+
15
+ # Unless required by applicable law or agreed to in writing, software
16
+ # distributed under the License is distributed on an "AS IS" BASIS,
17
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ # See the License for the specific language governing permissions and
19
+ # limitations under the License.
20
+
21
+ from __future__ import annotations
22
+ import logging
23
+ from typing import List, Optional, Tuple, Union, Dict, Any, TYPE_CHECKING
24
+
25
+ from openminds.base import Link
26
+ from openminds.registry import lookup
27
+
28
+ from .errors import ResolutionFailure
29
+ from .caching import object_cache
30
+ from .base import RepresentsSingleObject
31
+
32
+ if TYPE_CHECKING:
33
+ from .client import KGClient
34
+ from .kgobject import KGObject
35
+
36
+
37
+ logger = logging.getLogger("fairgraph")
38
+
39
+
40
+ class KGProxy(RepresentsSingleObject, Link):
41
+ """
42
+ Representation of an KGObject whose identifier, and possibly type, are known but whose
43
+ other metadata have not been retrieved from the KG.
44
+
45
+ Args:
46
+ cls (str, KGObject, List[KGObject]): the possible types of the associated KG object, defined by a KGObject subclass
47
+ or by the name of the subclass.
48
+ uri (URI): The global identifier of the KG object.
49
+ preferred_release_status (str, optional): The preferred scope used to resolve the proxy.
50
+ Valid values are "released", "in progress", or "any".
51
+
52
+ Example:
53
+ >>> import fairgraph.openminds
54
+ >>> proxy = KGProxy("openminds.core.Person", "https://kg.ebrains.eu/api/instances/bd554312-9829-4148-8803-cb873d0b32f9")
55
+ >>> person = proxy.resolve(kg_client)
56
+ >>> type(person)
57
+ <class 'fairgraph.openminds.core.actors.person.Person'>
58
+ >>> person.given_name
59
+ Andrew P.
60
+ """
61
+
62
+ # todo: rename uri to id, for consistency?
63
+
64
+ def __init__(
65
+ self,
66
+ classes: Union[str, KGObject, List[KGObject], Tuple[KGObject]],
67
+ uri: str,
68
+ preferred_release_status: str = "released",
69
+ ):
70
+ self.classes: List[KGObject] # todo: make this a set?
71
+ if isinstance(classes, str):
72
+ resolved_cls = lookup(classes)
73
+ if TYPE_CHECKING:
74
+ assert isinstance(resolved_cls, KGObject)
75
+ self.classes = [resolved_cls]
76
+ elif isinstance(classes, (list, tuple)):
77
+ self.classes = list(classes)
78
+ else:
79
+ self.classes = [classes]
80
+ if TYPE_CHECKING:
81
+ assert all(isinstance(cls, KGObject) for cls in self.classes)
82
+ self.id = uri
83
+ self.preferred_release_status = preferred_release_status
84
+ self.remote_data = None
85
+ Link.__init__(self, self.id, allowed_types=self.classes)
86
+
87
+ @property
88
+ def type(self) -> List[str]:
89
+ """
90
+ Provide the global identifiers of the object type (as a list of URIs).
91
+ """
92
+ try:
93
+ return [cls.type_ for cls in self.classes]
94
+ except AttributeError as err:
95
+ raise AttributeError(f"{err} self.classes={self.classes}")
96
+
97
+ @property
98
+ def cls(self):
99
+ """
100
+ For backwards compatibility
101
+ """
102
+ if len(self.classes) == 1:
103
+ return self.classes[0]
104
+ else:
105
+ raise AttributeError("This KGProxy has multiple possible types, use the 'classes' attribute instead")
106
+
107
+ def to_jsonld(self, **kwargs):
108
+ return {"@id": self.id}
109
+
110
+ def resolve(
111
+ self,
112
+ client: KGClient,
113
+ release_status: Optional[str] = None,
114
+ use_cache: bool = True,
115
+ follow_links: Optional[Dict[str, Any]] = None,
116
+ ):
117
+ """
118
+ Retrieve the full metadata for the KGObject represented by this proxy.
119
+
120
+ Args:
121
+ client: a KGClient
122
+ release_status (str, optional): The scope of the lookup. Valid values are "released", "in progress", or "any".
123
+ If not provided, the "preferred_release_status" provided when creating the proxy object will be used.
124
+ use_cache (bool): Whether to use cached data if they exist. Defaults to True.
125
+ follow_links (dict): The links in the graph to follow. Defaults to None.
126
+
127
+ Returns:
128
+ a KGObject instance, of the appropriate subclass.
129
+ """
130
+ if use_cache and self.id in object_cache:
131
+ obj = object_cache[self.id]
132
+ else:
133
+ release_status = release_status or self.preferred_release_status
134
+ obj = None
135
+ for cls in self.classes:
136
+ # this is inefficient, we should just get the data from the id, then get the correct type from the data
137
+ try:
138
+ obj = cls.from_uri(self.id, client, release_status=release_status)
139
+ except TypeError:
140
+ pass
141
+ else:
142
+ break
143
+ if obj is None:
144
+ raise ResolutionFailure(f"Cannot resolve proxy object of type {self.classes} with id {self.uuid}")
145
+ object_cache[self.id] = obj
146
+ if follow_links:
147
+ return obj.resolve(client, release_status=release_status, use_cache=use_cache, follow_links=follow_links)
148
+ else:
149
+ return obj
150
+
151
+ def __repr__(self):
152
+ return f"""{self.__class__.__name__}([{", ".join(cls.__name__ for cls in self.classes)}], id="{self.id.split('/')[-1]}")"""
153
+
154
+ def __eq__(self, other):
155
+ return (
156
+ isinstance(other, self.__class__) and set(self.classes).intersection(other.classes) and self.id == other.id
157
+ )
158
+
159
+ def __ne__(self, other):
160
+ return (
161
+ not isinstance(other, self.__class__) or set(self.classes).isdisjoint(other.classes) or self.id != other.id
162
+ )
163
+
164
+ @property
165
+ def uuid(self) -> str:
166
+ return self.id.split("/")[-1]
167
+
168
+ def delete(self, client: KGClient, ignore_not_found: bool = True):
169
+ """Delete the instance which this proxy represents"""
170
+ try:
171
+ obj = self.resolve(client, release_status="in progress")
172
+ except ResolutionFailure as err:
173
+ logger.warning(str(err))
174
+ obj = None
175
+ if obj:
176
+ obj.delete(client, ignore_not_found=ignore_not_found)
177
+ elif not ignore_not_found:
178
+ raise ResolutionFailure("Couldn't resolve object to delete")
fairgraph/kgquery.py ADDED
@@ -0,0 +1,151 @@
1
+ """
2
+ This module provides the KGQuery class, which represents one or more
3
+ KGObjects identified by a range of possible types and by some of their
4
+ metadata, but whose specific identifier(s) is/are not known.
5
+ """
6
+
7
+ # Copyright 2018-2024 CNRS
8
+
9
+ # Licensed under the Apache License, Version 2.0 (the "License");
10
+ # you may not use this file except in compliance with the License.
11
+ # You may obtain a copy of the License at
12
+
13
+ # http://www.apache.org/licenses/LICENSE-2.0
14
+
15
+ # Unless required by applicable law or agreed to in writing, software
16
+ # distributed under the License is distributed on an "AS IS" BASIS,
17
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ # See the License for the specific language governing permissions and
19
+ # limitations under the License.
20
+
21
+ from __future__ import annotations
22
+ import logging
23
+ from typing import Dict, List, Optional, Union, Any, TYPE_CHECKING
24
+
25
+ from openminds.registry import lookup
26
+
27
+ from .utility import as_list, expand_filter
28
+ from .caching import object_cache
29
+ from .base import Resolvable, SupportsQuerying
30
+
31
+ if TYPE_CHECKING:
32
+ from .client import KGClient
33
+ from .kgobject import KGObject
34
+
35
+ logger = logging.getLogger("fairgraph")
36
+
37
+
38
+ class KGQuery(Resolvable, SupportsQuerying):
39
+ """
40
+ Representation of one or more KGObjects identified by a range of possible types
41
+ and by some of their metadata, but whose specific identifier(s) is/are not known.
42
+
43
+ It is possible that no KGObjects match the types/metadata.
44
+
45
+ Args:
46
+ classes (list of KGObject subclasses): a list of types to query.
47
+ filter (dict): key:value pairs that should be matched. All pairs must match.
48
+ preferred_release_status (str): The preferred scope used to resolve the query.
49
+ Valid values are "released", "in progress", or "any".
50
+
51
+ Example:
52
+ >>> import fairgraph.openminds.core as omcore
53
+ >>> from fairgraph.utility import as_list
54
+ >>> query = KGQuery([omcore.Person], {"family_name": "Amunts"})
55
+ >>> people = as_list(query.resolve(kg_client))
56
+ >>> len(people)
57
+ 1
58
+ >>> people[0].family_name
59
+ Amunts
60
+ """
61
+
62
+ def __init__(
63
+ self,
64
+ classes: Union[str, KGObject, List[Union[str, KGObject]]],
65
+ filter: Dict[str, str],
66
+ preferred_release_status: str = "released",
67
+ ):
68
+ self.classes: List[KGObject] = []
69
+ for cls in as_list(classes):
70
+ if isinstance(cls, str):
71
+ resolved_cls = lookup(cls)
72
+ assert isinstance(resolved_cls, KGObject)
73
+ self.classes.append(resolved_cls)
74
+ else:
75
+ self.classes.append(cls)
76
+ self.filter = filter
77
+ self.preferred_release_status = preferred_release_status
78
+
79
+ def __repr__(self):
80
+ return f"""{self.__class__.__name__}([{", ".join(cls.__name__ for cls in self.classes)}], filter="{self.filter!r}")""".replace(
81
+ "https://kg.ebrains.eu/api/instances/", ""
82
+ )
83
+
84
+ def resolve(
85
+ self,
86
+ client: KGClient,
87
+ size: int = 10000,
88
+ from_index: int = 0,
89
+ space: Optional[str] = None,
90
+ release_status: Optional[str] = None,
91
+ use_cache: bool = True,
92
+ follow_links: Optional[Dict[str, Any]] = None,
93
+ with_reverse_properties: Optional[bool] = False,
94
+ ):
95
+ """
96
+ Retrieve the full metadata for the KGObject(s) represented by this query object.
97
+
98
+ Args:
99
+ client: a KGClient
100
+ from_index: The index of the first result to include in the response.
101
+ size: The maximum number of results to include in the response.
102
+ space: If specified, queries only in the given space.
103
+ release_status (str, optional): The scope of the query. Valid values are "released", "in progress", or "any".
104
+ If not provided, the "preferred_release_status" provided when creating the proxy object will be used.
105
+ use_cache (bool): Whether to use cached data if they exist. Defaults to True.
106
+ follow_links (dict): The links in the graph to follow. Defaults to None.
107
+ with_reverse_properties (dict): Whether to include reverse properties. Defaults to False.
108
+
109
+ Returns:
110
+ a KGObject instance, of the appropriate subclass.
111
+ """
112
+ release_status = release_status or self.preferred_release_status
113
+ objects: List[KGObject] = []
114
+ for cls in self.classes:
115
+ if hasattr(cls, "generate_query"):
116
+ # if cls is EmbeddedMetadata we cannot query it
117
+ query = cls.generate_query(
118
+ client=client,
119
+ filters=self.filter,
120
+ space=space,
121
+ follow_links=follow_links,
122
+ with_reverse_properties=with_reverse_properties,
123
+ )
124
+ instances = client.query(
125
+ query=query,
126
+ size=size,
127
+ from_index=from_index,
128
+ release_status=release_status,
129
+ ).data
130
+ objects.extend(cls.from_jsonld(instance_data, client) for instance_data in instances)
131
+ for obj in objects:
132
+ object_cache[obj.id] = obj
133
+
134
+ if follow_links:
135
+ for obj in objects:
136
+ obj.resolve(client, release_status=release_status, use_cache=use_cache, follow_links=follow_links)
137
+
138
+ if len(objects) == 1:
139
+ return objects[0]
140
+ else:
141
+ return objects
142
+
143
+ def count(self, client: KGClient, space: Optional[str] = None, release_status: Optional[str] = None):
144
+ """
145
+ Return the number of objects that would be returned by resolving this query.
146
+ """
147
+ release_status = release_status or self.preferred_release_status
148
+ n = 0
149
+ for cls in self.classes:
150
+ n += cls.count(client, api="query", release_status=release_status, space=space, **self.filter)
151
+ return n