fairgraph 0.11.0__tar.gz → 0.12.2__tar.gz

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 (366) hide show
  1. {fairgraph-0.11.0 → fairgraph-0.12.2}/PKG-INFO +22 -7
  2. {fairgraph-0.11.0 → fairgraph-0.12.2}/README.md +5 -4
  3. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/__init__.py +2 -2
  4. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/base.py +210 -105
  5. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/caching.py +5 -2
  6. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/client.py +113 -12
  7. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/embedded.py +14 -12
  8. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/errors.py +7 -1
  9. fairgraph-0.12.2/fairgraph/fields.py +11 -0
  10. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/kgobject.py +165 -124
  11. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/kgproxy.py +1 -1
  12. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/kgquery.py +11 -9
  13. fairgraph-0.12.2/fairgraph/openminds/__init__.py +1 -0
  14. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/chemicals/__init__.py +3 -3
  15. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/chemicals/amount_of_chemical.py +7 -7
  16. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/chemicals/chemical_mixture.py +28 -27
  17. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/chemicals/chemical_substance.py +22 -21
  18. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/chemicals/product_source.py +16 -15
  19. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/computation/__init__.py +13 -13
  20. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/computation/data_analysis.py +65 -56
  21. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/computation/data_copy.py +69 -58
  22. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/computation/environment.py +20 -17
  23. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/computation/generic_computation.py +65 -56
  24. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/computation/hardware_system.py +18 -17
  25. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/computation/launch_configuration.py +19 -18
  26. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/computation/local_file.py +31 -30
  27. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/computation/model_validation.py +67 -57
  28. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/computation/optimization.py +65 -56
  29. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/computation/simulation.py +65 -56
  30. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/computation/software_agent.py +30 -25
  31. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/computation/validation_test.py +83 -65
  32. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/computation/validation_test_version.py +153 -139
  33. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/computation/visualization.py +65 -56
  34. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/computation/workflow_execution.py +11 -9
  35. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/computation/workflow_recipe.py +46 -29
  36. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/computation/workflow_recipe_version.py +153 -137
  37. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/__init__.py +66 -62
  38. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/action_status_type.py +147 -0
  39. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/age_category.py +139 -0
  40. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/analysis_technique.py +37 -31
  41. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/anatomical_axes_orientation.py +139 -0
  42. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/anatomical_identification_type.py +139 -0
  43. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/anatomical_plane.py +139 -0
  44. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/annotation_criteria_type.py +139 -0
  45. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/annotation_type.py +139 -0
  46. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/atlas_type.py +138 -0
  47. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/auditory_stimulus_type.py +42 -52
  48. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/biological_order.py +167 -0
  49. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/biological_process.py +129 -0
  50. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/biological_sex.py +182 -0
  51. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/breeding_type.py +177 -0
  52. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/cell_culture_type.py +40 -54
  53. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/cell_type.py +197 -0
  54. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/chemical_mixture_type.py +139 -0
  55. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/colormap.py +129 -0
  56. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/contribution_type.py +26 -64
  57. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/cranial_window_construction_type.py +139 -0
  58. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/cranial_window_reinforcement_type.py +139 -0
  59. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/criteria_quality_type.py +36 -40
  60. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/data_type.py +139 -0
  61. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/device_type.py +144 -0
  62. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/difference_measure.py +139 -0
  63. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/disease.py +192 -0
  64. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/disease_model.py +192 -0
  65. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/educational_level.py +28 -46
  66. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/electrical_stimulus_type.py +46 -56
  67. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/ethics_assessment.py +129 -0
  68. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/experimental_approach.py +129 -0
  69. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/file_bundle_grouping.py +40 -76
  70. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/file_repository_type.py +139 -0
  71. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/file_usage_role.py +139 -0
  72. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/genetic_strain_type.py +45 -79
  73. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/gustatory_stimulus_type.py +42 -64
  74. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/handedness.py +177 -0
  75. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/language.py +36 -69
  76. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/laterality.py +36 -45
  77. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/learning_resource_type.py +138 -0
  78. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/measured_quantity.py +139 -0
  79. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/measured_signal_type.py +129 -0
  80. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/meta_data_model_type.py +138 -0
  81. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/model_abstraction_level.py +139 -0
  82. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/model_scope.py +139 -0
  83. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/molecular_entity.py +192 -0
  84. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/mri_pulse_sequence.py +148 -0
  85. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/mri_weighting.py +148 -0
  86. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/olfactory_stimulus_type.py +42 -52
  87. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/operating_device.py +129 -0
  88. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/operating_system.py +138 -0
  89. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/optical_stimulus_type.py +177 -0
  90. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/organ.py +207 -0
  91. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/organism_substance.py +197 -0
  92. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/organism_system.py +167 -0
  93. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/patch_clamp_variation.py +139 -0
  94. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/preparation_type.py +148 -0
  95. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/product_accessibility.py +129 -0
  96. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/programming_language.py +138 -0
  97. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/qualitative_overlap.py +129 -0
  98. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/semantic_data_type.py +28 -50
  99. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/service.py +149 -0
  100. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/setup_type.py +32 -50
  101. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/software_application_category.py +129 -0
  102. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/software_feature.py +129 -0
  103. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/species.py +193 -0
  104. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/stimulation_approach.py +148 -0
  105. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/stimulation_technique.py +148 -0
  106. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/subcellular_entity.py +193 -0
  107. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/subject_attribute.py +139 -0
  108. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/tactile_stimulus_type.py +42 -60
  109. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/technique.py +158 -0
  110. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/term_suggestion.py +45 -39
  111. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/terminology.py +139 -0
  112. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/tissue_sample_attribute.py +139 -0
  113. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/tissue_sample_type.py +177 -0
  114. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/type_of_uncertainty.py +34 -48
  115. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/uberon_parcellation.py +203 -0
  116. fairgraph-0.12.2/fairgraph/openminds/controlled_terms/unit_of_measurement.py +153 -0
  117. {fairgraph-0.11.0/fairgraph/openminds/controlledterms → fairgraph-0.12.2/fairgraph/openminds/controlled_terms}/visual_stimulus_type.py +42 -80
  118. fairgraph-0.12.2/fairgraph/openminds/controlledterms.py +6 -0
  119. fairgraph-0.12.2/fairgraph/openminds/core/__init__.py +107 -0
  120. fairgraph-0.12.2/fairgraph/openminds/core/actors/__init__.py +7 -0
  121. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/actors/account_information.py +14 -11
  122. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/actors/affiliation.py +10 -7
  123. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/actors/consortium.py +67 -35
  124. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/actors/contact_information.py +10 -9
  125. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/actors/contribution.py +7 -7
  126. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/actors/organization.py +80 -48
  127. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/actors/person.py +75 -61
  128. fairgraph-0.12.2/fairgraph/openminds/core/data/__init__.py +13 -0
  129. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/data/content_type.py +39 -35
  130. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/data/content_type_pattern.py +17 -14
  131. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/data/copyright.py +6 -6
  132. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/data/file.py +122 -75
  133. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/data/file_archive.py +32 -24
  134. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/data/file_bundle.py +88 -73
  135. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/data/file_path_pattern.py +11 -9
  136. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/data/file_repository.py +46 -42
  137. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/data/file_repository_structure.py +15 -12
  138. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/data/hash.py +9 -6
  139. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/data/license.py +28 -15
  140. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/data/measurement.py +14 -11
  141. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/data/service_link.py +18 -13
  142. fairgraph-0.12.2/fairgraph/openminds/core/digital_identifier/__init__.py +11 -0
  143. {fairgraph-0.11.0/fairgraph/openminds/core/digitalIdentifier → fairgraph-0.12.2/fairgraph/openminds/core/digital_identifier}/doi.py +22 -41
  144. {fairgraph-0.11.0/fairgraph/openminds/core/digitalIdentifier → fairgraph-0.12.2/fairgraph/openminds/core/digital_identifier}/gridid.py +11 -8
  145. {fairgraph-0.11.0/fairgraph/openminds/core/digitalIdentifier → fairgraph-0.12.2/fairgraph/openminds/core/digital_identifier}/handle.py +11 -8
  146. fairgraph-0.12.2/fairgraph/openminds/core/digital_identifier/identifiers_dot_org_id.py +49 -0
  147. {fairgraph-0.11.0/fairgraph/openminds/core/digitalIdentifier → fairgraph-0.12.2/fairgraph/openminds/core/digital_identifier}/isbn.py +17 -17
  148. {fairgraph-0.11.0/fairgraph/openminds/core/digitalIdentifier → fairgraph-0.12.2/fairgraph/openminds/core/digital_identifier}/issn.py +12 -11
  149. {fairgraph-0.11.0/fairgraph/openminds/core/digitalIdentifier → fairgraph-0.12.2/fairgraph/openminds/core/digital_identifier}/orcid.py +9 -8
  150. {fairgraph-0.11.0/fairgraph/openminds/core/digitalIdentifier → fairgraph-0.12.2/fairgraph/openminds/core/digital_identifier}/rorid.py +9 -8
  151. {fairgraph-0.11.0/fairgraph/openminds/core/digitalIdentifier → fairgraph-0.12.2/fairgraph/openminds/core/digital_identifier}/rrid.py +11 -10
  152. {fairgraph-0.11.0/fairgraph/openminds/core/digitalIdentifier → fairgraph-0.12.2/fairgraph/openminds/core/digital_identifier}/stock_number.py +12 -8
  153. {fairgraph-0.11.0/fairgraph/openminds/core/digitalIdentifier → fairgraph-0.12.2/fairgraph/openminds/core/digital_identifier}/swhid.py +14 -11
  154. fairgraph-0.12.2/fairgraph/openminds/core/miscellaneous/__init__.py +7 -0
  155. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/miscellaneous/comment.py +14 -9
  156. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/miscellaneous/funding.py +14 -13
  157. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/miscellaneous/quantitative_value.py +13 -11
  158. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/miscellaneous/quantitative_value_array.py +16 -14
  159. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/miscellaneous/quantitative_value_range.py +12 -10
  160. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/miscellaneous/research_product_group.py +11 -9
  161. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/miscellaneous/web_resource.py +60 -27
  162. fairgraph-0.12.2/fairgraph/openminds/core/products/__init__.py +12 -0
  163. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/products/dataset.py +41 -26
  164. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/products/dataset_version.py +210 -185
  165. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/products/meta_data_model.py +50 -31
  166. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/products/meta_data_model_version.py +155 -137
  167. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/products/model.py +74 -56
  168. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/products/model_version.py +169 -147
  169. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/products/project.py +25 -13
  170. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/products/setup.py +30 -27
  171. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/products/software.py +42 -25
  172. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/products/software_version.py +181 -157
  173. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/products/web_service.py +59 -34
  174. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/products/web_service_version.py +152 -145
  175. fairgraph-0.12.2/fairgraph/openminds/core/research/__init__.py +17 -0
  176. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/research/behavioral_protocol.py +33 -31
  177. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/research/configuration.py +20 -9
  178. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/research/custom_property_set.py +14 -12
  179. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/research/numerical_property.py +6 -6
  180. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/research/property_value_list.py +24 -13
  181. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/research/protocol.py +35 -32
  182. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/research/protocol_execution.py +58 -43
  183. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/research/strain.py +41 -38
  184. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/research/string_property.py +10 -8
  185. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/research/subject.py +24 -23
  186. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/research/subject_group.py +36 -33
  187. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/research/subject_group_state.py +44 -41
  188. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/research/subject_state.py +48 -45
  189. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/research/tissue_sample.py +38 -37
  190. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/research/tissue_sample_collection.py +50 -47
  191. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/research/tissue_sample_collection_state.py +41 -38
  192. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/core/research/tissue_sample_state.py +41 -40
  193. {fairgraph-0.11.0/fairgraph/openminds/specimenprep → fairgraph-0.12.2/fairgraph/openminds/ephys}/__init__.py +4 -6
  194. fairgraph-0.12.2/fairgraph/openminds/ephys/activity/__init__.py +3 -0
  195. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/ephys/activity/cell_patching.py +59 -53
  196. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/ephys/activity/electrode_placement.py +55 -49
  197. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/ephys/activity/recording_activity.py +52 -46
  198. fairgraph-0.12.2/fairgraph/openminds/ephys/device/__init__.py +6 -0
  199. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/ephys/device/electrode.py +45 -32
  200. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/ephys/device/electrode_array.py +44 -39
  201. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/ephys/device/electrode_array_usage.py +69 -46
  202. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/ephys/device/electrode_usage.py +53 -30
  203. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/ephys/device/pipette.py +44 -31
  204. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/ephys/device/pipette_usage.py +67 -42
  205. fairgraph-0.12.2/fairgraph/openminds/ephys/entity/__init__.py +2 -0
  206. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/ephys/entity/channel.py +11 -9
  207. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/ephys/entity/recording.py +30 -27
  208. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/publications/__init__.py +7 -7
  209. fairgraph-0.12.2/fairgraph/openminds/publications/book.py +276 -0
  210. fairgraph-0.12.2/fairgraph/openminds/publications/chapter.py +279 -0
  211. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/publications/learning_resource.py +133 -123
  212. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/publications/live_paper.py +46 -31
  213. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/publications/live_paper_resource_item.py +34 -28
  214. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/publications/live_paper_section.py +25 -22
  215. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/publications/live_paper_version.py +154 -139
  216. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/publications/periodical.py +20 -17
  217. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/publications/publication_issue.py +16 -13
  218. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/publications/publication_volume.py +16 -13
  219. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/publications/scholarly_article.py +130 -123
  220. {fairgraph-0.11.0/fairgraph/openminds/ephys → fairgraph-0.12.2/fairgraph/openminds/sands}/__init__.py +22 -12
  221. fairgraph-0.12.2/fairgraph/openminds/sands/atlas/__init__.py +9 -0
  222. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/sands/atlas/atlas_annotation.py +22 -20
  223. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/sands/atlas/brain_atlas.py +53 -40
  224. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/sands/atlas/brain_atlas_version.py +158 -144
  225. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/sands/atlas/common_coordinate_space.py +62 -49
  226. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/sands/atlas/common_coordinate_space_version.py +179 -160
  227. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/sands/atlas/parcellation_entity.py +60 -44
  228. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/sands/atlas/parcellation_entity_version.py +79 -51
  229. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/sands/atlas/parcellation_terminology.py +24 -12
  230. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/sands/atlas/parcellation_terminology_version.py +24 -12
  231. fairgraph-0.12.2/fairgraph/openminds/sands/mathematical_shapes/__init__.py +3 -0
  232. {fairgraph-0.11.0/fairgraph/openminds/sands/mathematicalShapes → fairgraph-0.12.2/fairgraph/openminds/sands/mathematical_shapes}/circle.py +9 -7
  233. {fairgraph-0.11.0/fairgraph/openminds/sands/mathematicalShapes → fairgraph-0.12.2/fairgraph/openminds/sands/mathematical_shapes}/ellipse.py +10 -8
  234. {fairgraph-0.11.0/fairgraph/openminds/sands/mathematicalShapes → fairgraph-0.12.2/fairgraph/openminds/sands/mathematical_shapes}/rectangle.py +10 -8
  235. fairgraph-0.12.2/fairgraph/openminds/sands/miscellaneous/__init__.py +6 -0
  236. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/sands/miscellaneous/anatomical_target_position.py +18 -16
  237. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/sands/miscellaneous/coordinate_point.py +6 -6
  238. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/sands/miscellaneous/qualitative_relation_assessment.py +12 -10
  239. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/sands/miscellaneous/quantitative_relation_assessment.py +11 -9
  240. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/sands/miscellaneous/single_color.py +10 -8
  241. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/sands/miscellaneous/viewer_specification.py +13 -11
  242. fairgraph-0.12.2/fairgraph/openminds/sands/non_atlas/__init__.py +3 -0
  243. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/sands/non_atlas/custom_anatomical_entity.py +45 -32
  244. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/sands/non_atlas/custom_annotation.py +23 -21
  245. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/sands/non_atlas/custom_coordinate_space.py +37 -24
  246. fairgraph-0.12.2/fairgraph/openminds/specimen_prep/__init__.py +38 -0
  247. fairgraph-0.12.2/fairgraph/openminds/specimen_prep/activity/__init__.py +3 -0
  248. {fairgraph-0.11.0/fairgraph/openminds/specimenprep → fairgraph-0.12.2/fairgraph/openminds/specimen_prep}/activity/cranial_window_preparation.py +55 -49
  249. {fairgraph-0.11.0/fairgraph/openminds/specimenprep → fairgraph-0.12.2/fairgraph/openminds/specimen_prep}/activity/tissue_culture_preparation.py +55 -49
  250. {fairgraph-0.11.0/fairgraph/openminds/specimenprep → fairgraph-0.12.2/fairgraph/openminds/specimen_prep}/activity/tissue_sample_slicing.py +54 -48
  251. fairgraph-0.12.2/fairgraph/openminds/specimen_prep/device/__init__.py +2 -0
  252. {fairgraph-0.11.0/fairgraph/openminds/specimenprep → fairgraph-0.12.2/fairgraph/openminds/specimen_prep}/device/slicing_device.py +39 -26
  253. {fairgraph-0.11.0/fairgraph/openminds/specimenprep → fairgraph-0.12.2/fairgraph/openminds/specimen_prep}/device/slicing_device_usage.py +65 -32
  254. fairgraph-0.12.2/fairgraph/openminds/specimenprep.py +4 -0
  255. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/stimulation/__init__.py +3 -3
  256. fairgraph-0.12.2/fairgraph/openminds/stimulation/activity/__init__.py +1 -0
  257. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/openminds/stimulation/activity/stimulation_activity.py +57 -49
  258. fairgraph-0.12.2/fairgraph/openminds/stimulation/stimulus/__init__.py +1 -0
  259. fairgraph-0.12.2/fairgraph/openminds/stimulation/stimulus/ephys_stimulus.py +124 -0
  260. fairgraph-0.11.0/fairgraph/fields.py → fairgraph-0.12.2/fairgraph/properties.py +46 -45
  261. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/queries.py +22 -10
  262. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/registry.py +61 -16
  263. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph/utility.py +9 -0
  264. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph.egg-info/PKG-INFO +22 -7
  265. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph.egg-info/SOURCES.txt +109 -102
  266. {fairgraph-0.11.0 → fairgraph-0.12.2}/pyproject.toml +2 -2
  267. {fairgraph-0.11.0 → fairgraph-0.12.2}/test/test_base.py +96 -64
  268. {fairgraph-0.11.0 → fairgraph-0.12.2}/test/test_client.py +1 -1
  269. {fairgraph-0.11.0 → fairgraph-0.12.2}/test/test_openminds_controlled_terms.py +1 -1
  270. {fairgraph-0.11.0 → fairgraph-0.12.2}/test/test_openminds_core.py +25 -12
  271. fairgraph-0.12.2/test/test_properties.py +190 -0
  272. {fairgraph-0.11.0 → fairgraph-0.12.2}/test/test_queries.py +3 -3
  273. {fairgraph-0.11.0 → fairgraph-0.12.2}/test/test_registry.py +2 -2
  274. fairgraph-0.11.0/fairgraph/openminds/__init__.py +0 -1
  275. fairgraph-0.11.0/fairgraph/openminds/controlledterms/action_status_type.py +0 -181
  276. fairgraph-0.11.0/fairgraph/openminds/controlledterms/age_category.py +0 -185
  277. fairgraph-0.11.0/fairgraph/openminds/controlledterms/anatomical_axes_orientation.py +0 -229
  278. fairgraph-0.11.0/fairgraph/openminds/controlledterms/anatomical_identification_type.py +0 -143
  279. fairgraph-0.11.0/fairgraph/openminds/controlledterms/anatomical_plane.py +0 -169
  280. fairgraph-0.11.0/fairgraph/openminds/controlledterms/annotation_criteria_type.py +0 -143
  281. fairgraph-0.11.0/fairgraph/openminds/controlledterms/annotation_type.py +0 -159
  282. fairgraph-0.11.0/fairgraph/openminds/controlledterms/atlas_type.py +0 -147
  283. fairgraph-0.11.0/fairgraph/openminds/controlledterms/biological_order.py +0 -197
  284. fairgraph-0.11.0/fairgraph/openminds/controlledterms/biological_sex.py +0 -204
  285. fairgraph-0.11.0/fairgraph/openminds/controlledterms/breeding_type.py +0 -207
  286. fairgraph-0.11.0/fairgraph/openminds/controlledterms/cell_type.py +0 -277
  287. fairgraph-0.11.0/fairgraph/openminds/controlledterms/chemical_mixture_type.py +0 -157
  288. fairgraph-0.11.0/fairgraph/openminds/controlledterms/colormap.py +0 -219
  289. fairgraph-0.11.0/fairgraph/openminds/controlledterms/cranial_window_construction_type.py +0 -157
  290. fairgraph-0.11.0/fairgraph/openminds/controlledterms/cranial_window_reinforcement_type.py +0 -165
  291. fairgraph-0.11.0/fairgraph/openminds/controlledterms/data_type.py +0 -229
  292. fairgraph-0.11.0/fairgraph/openminds/controlledterms/device_type.py +0 -178
  293. fairgraph-0.11.0/fairgraph/openminds/controlledterms/difference_measure.py +0 -169
  294. fairgraph-0.11.0/fairgraph/openminds/controlledterms/disease.py +0 -274
  295. fairgraph-0.11.0/fairgraph/openminds/controlledterms/disease_model.py +0 -230
  296. fairgraph-0.11.0/fairgraph/openminds/controlledterms/ethics_assessment.py +0 -155
  297. fairgraph-0.11.0/fairgraph/openminds/controlledterms/experimental_approach.py +0 -219
  298. fairgraph-0.11.0/fairgraph/openminds/controlledterms/file_repository_type.py +0 -181
  299. fairgraph-0.11.0/fairgraph/openminds/controlledterms/file_usage_role.py +0 -161
  300. fairgraph-0.11.0/fairgraph/openminds/controlledterms/handedness.py +0 -203
  301. fairgraph-0.11.0/fairgraph/openminds/controlledterms/learning_resource_type.py +0 -159
  302. fairgraph-0.11.0/fairgraph/openminds/controlledterms/measured_quantity.py +0 -171
  303. fairgraph-0.11.0/fairgraph/openminds/controlledterms/meta_data_model_type.py +0 -151
  304. fairgraph-0.11.0/fairgraph/openminds/controlledterms/model_abstraction_level.py +0 -205
  305. fairgraph-0.11.0/fairgraph/openminds/controlledterms/model_scope.py +0 -185
  306. fairgraph-0.11.0/fairgraph/openminds/controlledterms/molecular_entity.py +0 -282
  307. fairgraph-0.11.0/fairgraph/openminds/controlledterms/operating_device.py +0 -163
  308. fairgraph-0.11.0/fairgraph/openminds/controlledterms/operating_system.py +0 -171
  309. fairgraph-0.11.0/fairgraph/openminds/controlledterms/optical_stimulus_type.py +0 -187
  310. fairgraph-0.11.0/fairgraph/openminds/controlledterms/organ.py +0 -227
  311. fairgraph-0.11.0/fairgraph/openminds/controlledterms/organism_substance.py +0 -205
  312. fairgraph-0.11.0/fairgraph/openminds/controlledterms/organism_system.py +0 -213
  313. fairgraph-0.11.0/fairgraph/openminds/controlledterms/patch_clamp_variation.py +0 -169
  314. fairgraph-0.11.0/fairgraph/openminds/controlledterms/preparation_type.py +0 -178
  315. fairgraph-0.11.0/fairgraph/openminds/controlledterms/product_accessibility.py +0 -151
  316. fairgraph-0.11.0/fairgraph/openminds/controlledterms/programming_language.py +0 -215
  317. fairgraph-0.11.0/fairgraph/openminds/controlledterms/qualitative_overlap.py +0 -155
  318. fairgraph-0.11.0/fairgraph/openminds/controlledterms/service.py +0 -193
  319. fairgraph-0.11.0/fairgraph/openminds/controlledterms/software_application_category.py +0 -159
  320. fairgraph-0.11.0/fairgraph/openminds/controlledterms/software_feature.py +0 -219
  321. fairgraph-0.11.0/fairgraph/openminds/controlledterms/species.py +0 -271
  322. fairgraph-0.11.0/fairgraph/openminds/controlledterms/stimulation_approach.py +0 -179
  323. fairgraph-0.11.0/fairgraph/openminds/controlledterms/stimulation_technique.py +0 -223
  324. fairgraph-0.11.0/fairgraph/openminds/controlledterms/subcellular_entity.py +0 -245
  325. fairgraph-0.11.0/fairgraph/openminds/controlledterms/subject_attribute.py +0 -225
  326. fairgraph-0.11.0/fairgraph/openminds/controlledterms/technique.py +0 -249
  327. fairgraph-0.11.0/fairgraph/openminds/controlledterms/terminology.py +0 -229
  328. fairgraph-0.11.0/fairgraph/openminds/controlledterms/tissue_sample_attribute.py +0 -173
  329. fairgraph-0.11.0/fairgraph/openminds/controlledterms/tissue_sample_type.py +0 -197
  330. fairgraph-0.11.0/fairgraph/openminds/controlledterms/uberon_parcellation.py +0 -283
  331. fairgraph-0.11.0/fairgraph/openminds/controlledterms/unit_of_measurement.py +0 -239
  332. fairgraph-0.11.0/fairgraph/openminds/core/__init__.py +0 -103
  333. fairgraph-0.11.0/fairgraph/openminds/core/data/__init__.py +0 -0
  334. fairgraph-0.11.0/fairgraph/openminds/core/digitalIdentifier/__init__.py +0 -0
  335. fairgraph-0.11.0/fairgraph/openminds/core/digitalIdentifier/identifiers_dot_org_id.py +0 -36
  336. fairgraph-0.11.0/fairgraph/openminds/core/miscellaneous/__init__.py +0 -0
  337. fairgraph-0.11.0/fairgraph/openminds/core/products/__init__.py +0 -0
  338. fairgraph-0.11.0/fairgraph/openminds/core/research/__init__.py +0 -0
  339. fairgraph-0.11.0/fairgraph/openminds/ephys/activity/__init__.py +0 -0
  340. fairgraph-0.11.0/fairgraph/openminds/ephys/device/__init__.py +0 -0
  341. fairgraph-0.11.0/fairgraph/openminds/ephys/entity/__init__.py +0 -0
  342. fairgraph-0.11.0/fairgraph/openminds/publications/book.py +0 -265
  343. fairgraph-0.11.0/fairgraph/openminds/publications/chapter.py +0 -268
  344. fairgraph-0.11.0/fairgraph/openminds/sands/__init__.py +0 -57
  345. fairgraph-0.11.0/fairgraph/openminds/sands/atlas/__init__.py +0 -0
  346. fairgraph-0.11.0/fairgraph/openminds/sands/mathematicalShapes/__init__.py +0 -0
  347. fairgraph-0.11.0/fairgraph/openminds/sands/miscellaneous/__init__.py +0 -0
  348. fairgraph-0.11.0/fairgraph/openminds/sands/non_atlas/__init__.py +0 -0
  349. fairgraph-0.11.0/fairgraph/openminds/specimenprep/activity/__init__.py +0 -0
  350. fairgraph-0.11.0/fairgraph/openminds/specimenprep/device/__init__.py +0 -0
  351. fairgraph-0.11.0/fairgraph/openminds/stimulation/activity/__init__.py +0 -0
  352. fairgraph-0.11.0/fairgraph/openminds/stimulation/stimulus/__init__.py +0 -0
  353. fairgraph-0.11.0/fairgraph/openminds/stimulation/stimulus/ephys_stimulus.py +0 -45
  354. fairgraph-0.11.0/test/__init__.py +0 -0
  355. fairgraph-0.11.0/test/test_fields.py +0 -165
  356. {fairgraph-0.11.0 → fairgraph-0.12.2}/LICENSE.txt +0 -0
  357. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph.egg-info/dependency_links.txt +0 -0
  358. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph.egg-info/requires.txt +0 -0
  359. {fairgraph-0.11.0 → fairgraph-0.12.2}/fairgraph.egg-info/top_level.txt +0 -0
  360. {fairgraph-0.11.0 → fairgraph-0.12.2}/requirements.txt +0 -0
  361. {fairgraph-0.11.0 → fairgraph-0.12.2}/setup.cfg +0 -0
  362. {fairgraph-0.11.0 → fairgraph-0.12.2}/setup.py +0 -0
  363. {fairgraph-0.11.0/fairgraph/openminds/core/actors → fairgraph-0.12.2/test}/__init__.py +0 -0
  364. {fairgraph-0.11.0 → fairgraph-0.12.2}/test/test_openminds_computation.py +7 -7
  365. {fairgraph-0.11.0 → fairgraph-0.12.2}/test/test_openminds_publication.py +0 -0
  366. {fairgraph-0.11.0 → fairgraph-0.12.2}/test/test_utility.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fairgraph
3
- Version: 0.11.0
3
+ Version: 0.12.2
4
4
  Summary: Python API for the EBRAINS Knowledge Graph
5
5
  Author-email: "Andrew P. Davison" <andrew.davison@cnrs.fr>
6
6
  License: Apache Software License
@@ -11,16 +11,30 @@ Classifier: Intended Audience :: Science/Research
11
11
  Classifier: Topic :: Scientific/Engineering
12
12
  Classifier: License :: OSI Approved :: Apache Software License
13
13
  Classifier: Programming Language :: Python :: 3
14
- Requires-Python: >=3.7
14
+ Requires-Python: >=3.8
15
15
  Description-Content-Type: text/markdown
16
- Provides-Extra: dev
17
16
  License-File: LICENSE.txt
17
+ Requires-Dist: ebrains-kg-core
18
+ Requires-Dist: python-dateutil
19
+ Requires-Dist: tabulate
20
+ Requires-Dist: requests
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest; extra == "dev"
23
+ Requires-Dist: pytest-cov; extra == "dev"
24
+ Requires-Dist: pytest-mock; extra == "dev"
25
+ Requires-Dist: coverage; extra == "dev"
26
+ Requires-Dist: build; extra == "dev"
27
+ Requires-Dist: setuptools; extra == "dev"
28
+ Requires-Dist: wheel; extra == "dev"
29
+ Requires-Dist: sphinx; extra == "dev"
30
+ Requires-Dist: black; extra == "dev"
31
+ Requires-Dist: twine; extra == "dev"
18
32
 
19
33
  # fairgraph: a Python API for the EBRAINS Knowledge Graph.
20
34
 
21
35
  Authors: Andrew P. Davison, Onur Ates, Nico Feld, Yann Zerlaut, Glynis Mattheisen, Peyman Najafi
22
36
 
23
- Copyright CNRS 2019-2023
37
+ Copyright CNRS 2019-2024
24
38
 
25
39
  **fairgraph** is a Python library for working with metadata
26
40
  in the EBRAINS Knowledge Graph, with a particular focus on data reuse,
@@ -84,10 +98,10 @@ following the openMINDS structure. For example:
84
98
 
85
99
  ```
86
100
  >>> from fairgraph.openminds.core import DatasetVersion
87
- >>> from fairgraph.openminds.controlledterms import Technique
101
+ >>> from fairgraph.openminds.controlled_terms import Technique
88
102
  ```
89
103
 
90
- The following openMINDS modules are currently available: `core`, `controlledterms`, `sands`, `computation`, `ephys`, `publications`.
104
+ The following openMINDS modules are currently available: `core`, `controlled_terms`, `sands`, `computation`, `chemicals`, `specimen_prep`, `ephys`, `publications`, `stimulation`.
91
105
  Using these classes, it is possible to list all metadata matching a particular criterion, e.g.
92
106
 
93
107
  ```
@@ -174,4 +188,5 @@ please open a ticket in the [issue tracker](https://github.com/HumanBrainProject
174
188
 
175
189
  <div><img src="https://www.braincouncil.eu/wp-content/uploads/2018/11/wsi-imageoptim-EU-Logo.jpg" alt="EU Logo" height="23%" width="15%" align="right" style="margin-left: 10px"></div>
176
190
 
177
- This open source software code was developed in part or in whole in the Human Brain Project, funded from the European Union's Horizon 2020 Framework Programme for Research and Innovation under Specific Grant Agreements No. 720270, No. 785907 and No. 945539 (Human Brain Project SGA1, SGA2 and SGA3).
191
+ This open source software code was developed in part or in whole in the Human Brain Project, funded from the European Union's Horizon 2020 Framework Programme for Research and Innovation under Specific Grant Agreements No. 720270, No. 785907 and No. 945539 (Human Brain Project SGA1, SGA2 and SGA3) and in the EBRAINS research infrastructure,
192
+ funded from the European Union's Horizon Europe funding programme under grant agreement No. 101147319 (EBRAINS-2.0).
@@ -2,7 +2,7 @@
2
2
 
3
3
  Authors: Andrew P. Davison, Onur Ates, Nico Feld, Yann Zerlaut, Glynis Mattheisen, Peyman Najafi
4
4
 
5
- Copyright CNRS 2019-2023
5
+ Copyright CNRS 2019-2024
6
6
 
7
7
  **fairgraph** is a Python library for working with metadata
8
8
  in the EBRAINS Knowledge Graph, with a particular focus on data reuse,
@@ -66,10 +66,10 @@ following the openMINDS structure. For example:
66
66
 
67
67
  ```
68
68
  >>> from fairgraph.openminds.core import DatasetVersion
69
- >>> from fairgraph.openminds.controlledterms import Technique
69
+ >>> from fairgraph.openminds.controlled_terms import Technique
70
70
  ```
71
71
 
72
- The following openMINDS modules are currently available: `core`, `controlledterms`, `sands`, `computation`, `ephys`, `publications`.
72
+ The following openMINDS modules are currently available: `core`, `controlled_terms`, `sands`, `computation`, `chemicals`, `specimen_prep`, `ephys`, `publications`, `stimulation`.
73
73
  Using these classes, it is possible to list all metadata matching a particular criterion, e.g.
74
74
 
75
75
  ```
@@ -156,4 +156,5 @@ please open a ticket in the [issue tracker](https://github.com/HumanBrainProject
156
156
 
157
157
  <div><img src="https://www.braincouncil.eu/wp-content/uploads/2018/11/wsi-imageoptim-EU-Logo.jpg" alt="EU Logo" height="23%" width="15%" align="right" style="margin-left: 10px"></div>
158
158
 
159
- This open source software code was developed in part or in whole in the Human Brain Project, funded from the European Union's Horizon 2020 Framework Programme for Research and Innovation under Specific Grant Agreements No. 720270, No. 785907 and No. 945539 (Human Brain Project SGA1, SGA2 and SGA3).
159
+ This open source software code was developed in part or in whole in the Human Brain Project, funded from the European Union's Horizon 2020 Framework Programme for Research and Innovation under Specific Grant Agreements No. 720270, No. 785907 and No. 945539 (Human Brain Project SGA1, SGA2 and SGA3) and in the EBRAINS research infrastructure,
160
+ funded from the European Union's Horizon Europe funding programme under grant agreement No. 101147319 (EBRAINS-2.0).
@@ -4,7 +4,7 @@ Python client for the EBRAINS Knowledge Graph
4
4
  Authors: Andrew Davison et al., CNRS (see authors.rst)
5
5
 
6
6
 
7
- Copyright 2018-2023 CNRS
7
+ Copyright 2018-2024 CNRS
8
8
 
9
9
  Licensed under the Apache License, Version 2.0 (the "License");
10
10
  you may not use this file except in compliance with the License.
@@ -26,7 +26,7 @@ from .kgproxy import KGProxy
26
26
  from .kgquery import KGQuery
27
27
  from .base import IRI
28
28
 
29
- __version__ = "0.11.0"
29
+ __version__ = "0.12.2"
30
30
 
31
31
  # from . import (
32
32
  # base, client, errors, utility, openminds)
@@ -3,7 +3,7 @@ This module contains base classes that define interfaces
3
3
  and contain code common to sub-classes, to avoid code duplication.
4
4
  """
5
5
 
6
- # Copyright 2018-2023 CNRS
6
+ # Copyright 2018-2024 CNRS
7
7
 
8
8
  # Licensed under the Apache License, Version 2.0 (the "License");
9
9
  # you may not use this file except in compliance with the License.
@@ -19,7 +19,6 @@ and contain code common to sub-classes, to avoid code duplication.
19
19
 
20
20
 
21
21
  from __future__ import annotations
22
-
23
22
  from typing import TYPE_CHECKING, Optional, Dict, List, Union, Any
24
23
  from typing_extensions import TypeAlias
25
24
  from copy import copy
@@ -29,16 +28,17 @@ from warnings import warn
29
28
 
30
29
  from .registry import Registry
31
30
  from .queries import QueryProperty
32
- from .errors import ResolutionFailure, AuthorizationError
31
+ from .errors import ResolutionFailure, AuthorizationError, CannotBuildExistenceQuery
33
32
  from .utility import (
34
33
  as_list, # temporary for backwards compatibility (a lot of code imports it from here)
35
34
  expand_uri,
36
35
  normalize_data,
36
+ invert_dict
37
37
  )
38
38
 
39
39
  if TYPE_CHECKING:
40
40
  from .client import KGClient
41
- from .fields import Field
41
+ from .properties import Property
42
42
  from .utility import ActivityLog
43
43
 
44
44
  logger = logging.getLogger("fairgraph")
@@ -74,40 +74,49 @@ class Resolvable: # all
74
74
 
75
75
 
76
76
  class ContainsMetadata(Resolvable, metaclass=Registry): # KGObject and EmbeddedMetadata
77
- fields: List[Field]
77
+ properties: List[Property]
78
+ reverse_properties: List[Property]
78
79
  context: Dict[str, str]
79
- type_: List[str]
80
+ type_: str
80
81
  scope: Optional[str]
81
82
  space: Union[str, None]
82
83
  default_space: Union[str, None]
83
84
  remote_data: Optional[JSONdict]
85
+ aliases: Dict[str, str] = {}
84
86
 
85
87
  def __init__(self, data: Optional[Dict] = None, **properties):
86
88
  properties_copy = copy(properties)
87
- for field in self.fields:
89
+ for prop in self.__class__.all_properties:
88
90
  try:
89
- value = properties[field.name]
91
+ val = properties[prop.name]
90
92
  except KeyError:
91
- if field.required:
92
- msg = "Field '{}' is required.".format(field.name)
93
- ErrorHandling.handle_violation(field.error_handling, msg)
94
- value = None
93
+ if prop.required:
94
+ msg = "Property '{}' is required.".format(prop.name)
95
+ ErrorHandling.handle_violation(prop.error_handling, msg)
96
+ val = None
95
97
  else:
96
- properties_copy.pop(field.name)
97
- if value is None:
98
- value = field.default
99
- if callable(value):
100
- value = value()
101
- elif isinstance(value, (list, tuple)) and len(value) == 0: # empty list
102
- value = None
103
- field.check_value(value)
104
- setattr(self, field.name, value)
98
+ properties_copy.pop(prop.name)
99
+ if val is None:
100
+ val = prop.default
101
+ if callable(val):
102
+ val = val()
103
+ elif isinstance(val, (list, tuple)) and len(val) == 0: # empty list
104
+ val = None
105
+ setattr(self, prop.name, val)
106
+ for name_, alias_ in self.aliases.items():
107
+ # the trailing underscores are because 'name' and 'alias' can be keys in 'properties'
108
+ if name_ in properties_copy:
109
+ val = properties_copy.pop(name_)
110
+ if val is not None:
111
+ if properties.get(alias_, None):
112
+ raise ValueError(f"'{name_}' is an alias for '{alias_}', you cannot specify both")
113
+ setattr(self, alias_, val)
105
114
  if len(properties_copy) > 0:
106
115
  if len(properties_copy) == 1:
107
- raise NameError(f'{self.__class__.__name__} does not have a field named "{list(properties_copy)[0]}".')
116
+ raise NameError(f'{self.__class__.__name__} does not have a property named "{list(properties_copy)[0]}".')
108
117
  else:
109
118
  raise NameError(
110
- f"""{self.__class__.__name__} does not have fields named "{'", "'.join(properties_copy)}"."""
119
+ f"""{self.__class__.__name__} does not have properties named "{'", "'.join(properties_copy)}"."""
111
120
  )
112
121
 
113
122
  # we store the original remote data in `_raw_remote_data`
@@ -115,14 +124,35 @@ class ContainsMetadata(Resolvable, metaclass=Registry): # KGObject and Embedded
115
124
  self._raw_remote_data = data # for debugging
116
125
  self.remote_data = {}
117
126
  if data:
118
- self.remote_data = self.to_jsonld(include_empty_fields=True, follow_links=False)
127
+ self.remote_data = self.to_jsonld(include_empty_properties=True, follow_links=False)
128
+
129
+ def __getattribute__(self, name):
130
+ try:
131
+ return object.__getattribute__(self, name)
132
+ except AttributeError:
133
+ if name in self.aliases:
134
+ return object.__getattribute__(self, self.aliases[name])
135
+ else:
136
+ raise
137
+
138
+ def __setattr__(self, name, value):
139
+ try:
140
+ prop = self._property_lookup[name]
141
+ except KeyError:
142
+ if name in self.aliases:
143
+ setattr(self, self.aliases[name], value)
144
+ else:
145
+ super().__setattr__(name, value)
146
+ else:
147
+ prop.check_value(value)
148
+ super().__setattr__(name, value)
119
149
 
120
150
  def to_jsonld(
121
151
  self,
122
152
  normalized: bool = True,
123
153
  follow_links: bool = False,
124
- include_empty_fields: bool = False,
125
- include_reverse_fields: bool = False,
154
+ include_empty_properties: bool = False,
155
+ include_reverse_properties: bool = False,
126
156
  ):
127
157
  """
128
158
  Return a JSON-LD representation of this metadata object
@@ -131,20 +161,20 @@ class ContainsMetadata(Resolvable, metaclass=Registry): # KGObject and Embedded
131
161
  normalized (bool): Whether to expand all URIs. Defaults to True.
132
162
  follow_links (bool, optional): Whether to represent linked objects just by their "@id"
133
163
  or to include their full metadata. Defaults to False.
134
- include_empty_fields (bool, optional): Whether to include empty fields (with value "null").
164
+ include_empty_properties (bool, optional): Whether to include empty properties (with value "null").
135
165
  Defaults to False.
136
166
 
137
167
  """
138
- if self.fields:
139
- data: JSONdict = {"@type": self.type_}
168
+ if self.properties:
169
+ data: JSONdict = {"@type": [self.type_]}
140
170
  if hasattr(self, "id") and self.id:
141
171
  data["@id"] = self.id
142
- for field in self.fields:
143
- if field.intrinsic or include_reverse_fields:
144
- expanded_path = field.expanded_path
145
- value = getattr(self, field.name)
146
- if include_empty_fields or field.required or value is not None:
147
- serialized = field.serialize(value, follow_links=follow_links)
172
+ for prop in self.__class__.all_properties:
173
+ if prop.intrinsic or include_reverse_properties:
174
+ expanded_path = prop.expanded_path
175
+ value = getattr(self, prop.name)
176
+ if include_empty_properties or prop.required or value is not None:
177
+ serialized = prop.serialize(value, follow_links=follow_links)
148
178
  if expanded_path in data:
149
179
  if isinstance(data[expanded_path], list):
150
180
  data[expanded_path].append(serialized)
@@ -181,41 +211,40 @@ class ContainsMetadata(Resolvable, metaclass=Registry): # KGObject and Embedded
181
211
  activity_log: Optional[ActivityLog] = None,
182
212
  replace: bool = False,
183
213
  ignore_auth_errors: bool = False,
214
+ ignore_duplicates: bool = False
184
215
  ):
185
216
  pass
186
217
 
187
218
  @classmethod
188
219
  def set_error_handling(
189
- cls, value: Union[ErrorHandling, None], field_names: Optional[Union[str, List[str]]] = None
220
+ cls, value: Union[ErrorHandling, None], property_names: Optional[Union[str, List[str]]] = None
190
221
  ):
191
222
  """
192
223
  Control validation for this class.
193
224
 
194
225
  Args:
195
226
  value (str): action to follow when there is a validation failure.
196
- (e.g. if a required field is not provided).
227
+ (e.g. if a required property is not provided).
197
228
  Possible values: "error", "warning", "log", None
198
- field_names (str or list of str, optional): If not provided, the error handling
199
- mode will be applied to all fields. If a field name or list of names is given,
200
- the mode will be applied only to those fields.
229
+ property_names (str or list of str, optional): If not provided, the error handling
230
+ mode will be applied to all properties. If a property name or list of names is given,
231
+ the mode will be applied only to those properties.
201
232
  """
202
233
  if value is None:
203
234
  value = ErrorHandling.none
204
235
  else:
205
236
  value = ErrorHandling(value)
206
- if field_names:
207
- for field_name in as_list(field_names):
208
- found = False
209
- for field in cls.fields:
210
- if field.name == field_name:
211
- field.error_handling = value
212
- found = True
213
- break
214
- if not found:
215
- raise ValueError("No such field: {}".format(field_name))
237
+ if property_names:
238
+ for property_name in as_list(property_names):
239
+ try:
240
+ prop = cls._property_lookup[property_name]
241
+ except KeyError:
242
+ raise ValueError("No such property: {}".format(property_name))
243
+ else:
244
+ prop.error_handling = value
216
245
  else:
217
- for field in cls.fields:
218
- field.error_handling = value
246
+ for prop in cls.all_properties:
247
+ prop.error_handling = value
219
248
 
220
249
  @classmethod
221
250
  def normalize_filter(cls, filter_dict: Dict[str, Any]) -> Dict[str, Any]:
@@ -232,15 +261,22 @@ class ContainsMetadata(Resolvable, metaclass=Registry): # KGObject and Embedded
232
261
  'custodians': 'https://kg.ebrains.eu/api/instances/045f846f-f010-4db8-97b9-b95b20970bf2'}
233
262
  """
234
263
  normalized = {}
235
- for field in cls.fields:
236
- if field.name in filter_dict:
237
- value = filter_dict[field.name]
264
+ filter_dict_copy = filter_dict.copy()
265
+
266
+ # handle aliases
267
+ for name_, alias_ in cls.aliases.items():
268
+ if name_ in filter_dict_copy:
269
+ filter_dict_copy[alias_] = filter_dict_copy.pop(name_)
270
+
271
+ for prop in cls.all_properties:
272
+ if prop.name in filter_dict_copy:
273
+ value = filter_dict_copy[prop.name]
238
274
  if isinstance(value, dict):
239
- normalized[field.name] = {}
240
- for child_cls in field.types:
241
- normalized[field.name].update(child_cls.normalize_filter(value))
275
+ normalized[prop.name] = {}
276
+ for child_cls in prop.types:
277
+ normalized[prop.name].update(child_cls.normalize_filter(value))
242
278
  else:
243
- normalized[field.name] = field.get_filter_value(value)
279
+ normalized[prop.name] = prop.get_filter_value(value)
244
280
  return normalized
245
281
 
246
282
  @classmethod
@@ -253,11 +289,17 @@ class ContainsMetadata(Resolvable, metaclass=Registry): # KGObject and Embedded
253
289
  follow_links (dict): The links in the graph to follow when constructing the query. Defaults to None.
254
290
  """
255
291
  properties = [QueryProperty("@type")]
256
- for field in cls.fields:
257
- if field.is_link and follow_links and field.name in follow_links:
258
- properties.extend(field.get_query_properties(follow_links[field.name]))
292
+ reverse_aliases = invert_dict(cls.aliases)
293
+ for prop in cls.all_properties:
294
+ if prop.is_link and follow_links:
295
+ if prop.name in follow_links:
296
+ properties.extend(prop.get_query_properties(follow_links[prop.name]))
297
+ elif reverse_aliases.get(prop.name, None) in follow_links:
298
+ properties.extend(prop.get_query_properties(follow_links[reverse_aliases[prop.name]]))
299
+ else:
300
+ properties.extend(prop.get_query_properties())
259
301
  else:
260
- properties.extend(field.get_query_properties())
302
+ properties.extend(prop.get_query_properties())
261
303
  return properties
262
304
 
263
305
  @classmethod
@@ -273,9 +315,9 @@ class ContainsMetadata(Resolvable, metaclass=Registry): # KGObject and Embedded
273
315
  if filters is None:
274
316
  filters = {}
275
317
  properties = []
276
- for field in cls.fields:
277
- if field.name in filters:
278
- properties.append(field.get_query_filter_property(filters[field.name]))
318
+ for prop in cls.all_properties:
319
+ if prop.name in filters:
320
+ properties.append(prop.get_query_filter_property(filters[prop.name]))
279
321
  return properties
280
322
 
281
323
  @classmethod
@@ -293,22 +335,41 @@ class ContainsMetadata(Resolvable, metaclass=Registry): # KGObject and Embedded
293
335
  D[normalised_key].extend(value)
294
336
  else:
295
337
  D[normalised_key] = value
296
- elif key.startswith("Q"): # for 'Q' fields in data from queries
338
+ elif key.startswith("Q"): # for 'Q' properties in data from queries
297
339
  D[key] = value
298
340
  elif key[0] != "@":
299
341
  normalised_key = expand_uri(key, cls.context)
300
342
  D[normalised_key] = value
301
- for otype in expand_uri(as_list(cls.type_), cls.context):
302
- if otype not in D["@type"]:
303
- raise TypeError("type mismatch {} - {}".format(otype, D["@type"]))
343
+ if cls.type_ not in D["@type"]:
344
+ raise TypeError("type mismatch {} - {}".format(cls.type_, D["@type"]))
345
+
346
+ def _get_type_from_data(data_item):
347
+ type_ = data_item.get("@type", None)
348
+ if type_:
349
+ return type_[0]
350
+ else:
351
+ return None
352
+
304
353
  deserialized_data = {}
305
- for field in cls.fields:
306
- expanded_path = expand_uri(field.path, cls.context)
354
+ for prop in cls.all_properties:
355
+ expanded_path = expand_uri(prop.path, cls.context)
307
356
  data_item = D.get(expanded_path)
357
+ if data_item is not None and prop.reverse:
358
+ # for reverse properties, more than one property can have the same path
359
+ # so we extract only those sub-items whose types match
360
+ try:
361
+ data_item = [
362
+ part for part in as_list(data_item)
363
+ if _get_type_from_data(part) in [t.type_ for t in prop.types]
364
+ ]
365
+ except AttributeError:
366
+ # problem when a forward and reverse path both given the same expanded path
367
+ # e.g. for Configuration
368
+ data_item = None
308
369
  # sometimes queries put single items in a list, this removes the enclosing list
309
- if (not field.multiple) and isinstance(data_item, (list, tuple)) and len(data_item) == 1:
370
+ if (not prop.multiple) and isinstance(data_item, (list, tuple)) and len(data_item) == 1:
310
371
  data_item = data_item[0]
311
- deserialized_data[field.name] = field.deserialize(data_item, client, belongs_to=data.get("@id", None))
372
+ deserialized_data[prop.name] = prop.deserialize(data_item, client, belongs_to=data.get("@id", None))
312
373
  return deserialized_data
313
374
 
314
375
  def resolve(
@@ -319,7 +380,7 @@ class ContainsMetadata(Resolvable, metaclass=Registry): # KGObject and Embedded
319
380
  follow_links: Optional[Dict[str, Any]] = None,
320
381
  ):
321
382
  """
322
- Resolve fields that are represented by KGProxy objects.
383
+ Resolve properties that are represented by KGProxy objects.
323
384
 
324
385
  Args:
325
386
  client: KGClient object that handles the communication with the KG.
@@ -332,39 +393,83 @@ class ContainsMetadata(Resolvable, metaclass=Registry): # KGObject and Embedded
332
393
  """
333
394
  use_scope = scope or self.scope or "released"
334
395
  if follow_links:
335
- for field in self.fields:
336
- if field.is_link and field.name in follow_links:
337
- if issubclass(field.types[0], ContainsMetadata):
338
- values = getattr(self, field.name)
339
- resolved_values: List[Any] = []
340
- for value in as_list(values):
341
- if isinstance(value, Resolvable):
342
- if isinstance(value, ContainsMetadata) and isinstance(value, RepresentsSingleObject):
343
- # i.e. isinstance(value, KGObject) - already resolved
344
- resolved_values.append(value)
345
- else:
346
- try:
347
- resolved_value = value.resolve(
348
- client,
349
- scope=use_scope,
350
- use_cache=use_cache,
351
- follow_links=follow_links[field.name],
352
- )
353
- except ResolutionFailure as err:
354
- warn(str(err))
396
+ reverse_aliases = invert_dict(self.__class__.aliases)
397
+ for prop in self.__class__.all_properties:
398
+ if prop.is_link:
399
+ follow_name = None
400
+ if prop.name in follow_links:
401
+ follow_name = prop.name
402
+ elif reverse_aliases.get(prop.name, None) in follow_links:
403
+ follow_name = reverse_aliases[prop.name]
404
+
405
+ if follow_name:
406
+ if issubclass(prop.types[0], ContainsMetadata):
407
+ values = getattr(self, prop.name)
408
+ resolved_values: List[Any] = []
409
+ for value in as_list(values):
410
+ if isinstance(value, Resolvable):
411
+ if isinstance(value, ContainsMetadata) and isinstance(value, RepresentsSingleObject):
412
+ # i.e. isinstance(value, KGObject) - already resolved
355
413
  resolved_values.append(value)
356
414
  else:
357
- resolved_values.append(resolved_value)
358
- if isinstance(values, RepresentsSingleObject):
359
- assert len(resolved_values) == 1
360
- setattr(self, field.name, resolved_values[0])
361
- elif values is None:
362
- assert len(resolved_values) == 0
363
- setattr(self, field.name, None)
364
- else:
365
- setattr(self, field.name, resolved_values)
415
+ try:
416
+ resolved_value = value.resolve(
417
+ client,
418
+ scope=use_scope,
419
+ use_cache=use_cache,
420
+ follow_links=follow_links[follow_name],
421
+ )
422
+ except ResolutionFailure as err:
423
+ warn(str(err))
424
+ resolved_values.append(value)
425
+ else:
426
+ resolved_values.append(resolved_value)
427
+ if isinstance(values, RepresentsSingleObject):
428
+ assert len(resolved_values) == 1
429
+ setattr(self, prop.name, resolved_values[0])
430
+ elif values is None:
431
+ assert len(resolved_values) == 0
432
+ setattr(self, prop.name, None)
433
+ else:
434
+ setattr(self, prop.name, resolved_values)
366
435
  return self
367
436
 
437
+ def _build_existence_query(self) -> Union[None, Dict[str, Any]]:
438
+ """
439
+ Generate a KG query definition (as a JSON-LD document) that can be used to
440
+ check whether a locally-defined object (with no ID) already exists in the KG.
441
+ """
442
+ if self.existence_query_properties is None:
443
+ return None
444
+
445
+ query_properties = []
446
+ for property_name in self.existence_query_properties:
447
+ for property in self.__class__.all_properties:
448
+ if property.name == property_name:
449
+ query_properties.append(property)
450
+ break
451
+ if len(query_properties) < 1:
452
+ raise CannotBuildExistenceQuery("Empty existence query for class {}".format(self.__class__.__name__))
453
+ query = {}
454
+ for property in query_properties:
455
+ query_property_name = property.name
456
+ value = getattr(self, property.name)
457
+ if isinstance(value, ContainsMetadata):
458
+ if hasattr(value, "id") and value.id:
459
+ query[query_property_name] = value.id
460
+ else:
461
+ sub_query = value._build_existence_query()
462
+ query.update({f"{query_property_name}__{key}": val for key, val in sub_query.items()})
463
+ elif isinstance(value, (list, tuple)):
464
+ raise CannotBuildExistenceQuery("not implemented yet")
465
+ elif value is None:
466
+ raise CannotBuildExistenceQuery(f"Required value for '{query_property_name}' is missing")
467
+ else:
468
+ query_val = property.serialize(value, follow_links=False)
469
+ if query_val is None:
470
+ raise CannotBuildExistenceQuery(f"Required value for '{query_property_name}' is missing")
471
+ query[query_property_name] = query_val
472
+ return query
368
473
 
369
474
  class RepresentsSingleObject(Resolvable): # KGObject, KGProxy
370
475
  id: Optional[str]
@@ -414,7 +519,7 @@ class IRI:
414
519
  else:
415
520
  iri = value
416
521
  if not iri.startswith("http"):
417
- raise ValueError("Invalid IRI")
522
+ raise ValueError(f"Invalid IRI: '{iri}'")
418
523
  self.value: str = iri
419
524
 
420
525
  def __eq__(self, other):
@@ -3,7 +3,7 @@ This module contains global caches for Knowledge Graph data and queries,
3
3
  to avoid making unnecessary API calls.
4
4
  """
5
5
 
6
- # Copyright 2018-2023 CNRS
6
+ # Copyright 2018-2024 CNRS
7
7
 
8
8
  # Licensed under the Apache License, Version 2.0 (the "License");
9
9
  # you may not use this file except in compliance with the License.
@@ -31,7 +31,10 @@ def generate_cache_key(qd: Dict[str, str]) -> Tuple:
31
31
  if isinstance(value, (list, tuple)):
32
32
  sub_key = []
33
33
  for sub_value in value:
34
- sub_key.append(generate_cache_key(sub_value))
34
+ if isinstance(sub_value, dict):
35
+ sub_key.append(generate_cache_key(sub_value))
36
+ else:
37
+ sub_key.append(str(value))
35
38
  cache_key.append(tuple(sub_key))
36
39
  elif isinstance(value, dict):
37
40
  cache_key.append((key, str(value)))