oaklib 0.2.6__tar.gz → 0.2.8__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 (246) hide show
  1. {oaklib-0.2.6 → oaklib-0.2.8}/PKG-INFO +1 -1
  2. {oaklib-0.2.6 → oaklib-0.2.8}/pyproject.toml +1 -1
  3. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/__init__.py +1 -1
  4. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/cli.py +27 -8
  5. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/converters/data_model_converter.py +3 -0
  6. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/__init__.py +26 -0
  7. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/pronto/pronto_implementation.py +5 -1
  8. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/simpleobo/simple_obo_implementation.py +14 -0
  9. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/simpleobo/simple_obo_parser.py +175 -16
  10. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/differ_interface.py +5 -2
  11. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/dumper_interface.py +8 -3
  12. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/semsim_interface.py +36 -0
  13. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/selector.py +60 -74
  14. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/obograph_utils.py +15 -3
  15. {oaklib-0.2.6 → oaklib-0.2.8}/LICENSE +0 -0
  16. {oaklib-0.2.6 → oaklib-0.2.8}/README.md +0 -0
  17. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/conf/__init__.py +0 -0
  18. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/conf/lexmatch-rules-oboinowl-default.yaml +0 -0
  19. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/conf/obograph-style.json +0 -0
  20. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/conf/omo-to-skos.sssom.tsv +0 -0
  21. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/conf/value-set-expander.conf.yaml +0 -0
  22. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/constants.py +0 -0
  23. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/converters/__init__.py +0 -0
  24. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/converters/logical_definition_flattener.py +0 -0
  25. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/converters/obo_graph_to_cx_converter.py +0 -0
  26. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/converters/obo_graph_to_fhir_converter.py +0 -0
  27. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/converters/obo_graph_to_obo_format_converter.py +0 -0
  28. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/converters/obo_graph_to_rdf_owl_converter.py +0 -0
  29. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/__init__.py +0 -0
  30. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/association.owl.ttl +0 -0
  31. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/association.py +0 -0
  32. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/association.yaml +0 -0
  33. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/class_enrichment.owl.ttl +0 -0
  34. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/class_enrichment.py +0 -0
  35. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/class_enrichment.yaml +0 -0
  36. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/cross_ontology_diff.owl.ttl +0 -0
  37. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/cross_ontology_diff.py +0 -0
  38. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/cross_ontology_diff.yaml +0 -0
  39. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/fhir.owl.ttl +0 -0
  40. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/fhir.py +0 -0
  41. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/fhir.yaml +0 -0
  42. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/lexical_index.owl.ttl +0 -0
  43. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/lexical_index.py +0 -0
  44. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/lexical_index.schema.json +0 -0
  45. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/lexical_index.yaml +0 -0
  46. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/mapping_cluster_datamodel.py +0 -0
  47. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/mapping_cluster_datamodel.yaml +0 -0
  48. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/mapping_rules_datamodel.owl.ttl +0 -0
  49. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/mapping_rules_datamodel.py +0 -0
  50. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/mapping_rules_datamodel.schema.json +0 -0
  51. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/mapping_rules_datamodel.yaml +0 -0
  52. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/obograph.owl.ttl +0 -0
  53. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/obograph.py +0 -0
  54. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/obograph.schema.json +0 -0
  55. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/obograph.yaml +0 -0
  56. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/ontology_metadata.owl.ttl +0 -0
  57. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/ontology_metadata.py +0 -0
  58. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/ontology_metadata.schema.json +0 -0
  59. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/ontology_metadata.yaml +0 -0
  60. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/oxo.owl.ttl +0 -0
  61. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/oxo.py +0 -0
  62. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/oxo.yaml +0 -0
  63. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/search.py +0 -0
  64. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/search_datamodel.owl.ttl +0 -0
  65. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/search_datamodel.py +0 -0
  66. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/search_datamodel.yaml +0 -0
  67. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/similarity.owl.ttl +0 -0
  68. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/similarity.py +0 -0
  69. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/similarity.yaml +0 -0
  70. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/summary_statistics_datamodel.owl.ttl +0 -0
  71. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/summary_statistics_datamodel.py +0 -0
  72. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/summary_statistics_datamodel.schema.json +0 -0
  73. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/summary_statistics_datamodel.yaml +0 -0
  74. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/taxon_constraints.owl.ttl +0 -0
  75. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/taxon_constraints.py +0 -0
  76. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/taxon_constraints.yaml +0 -0
  77. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/text_annotator.owl.ttl +0 -0
  78. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/text_annotator.py +0 -0
  79. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/text_annotator.schema.json +0 -0
  80. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/text_annotator.yaml +0 -0
  81. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/validation_datamodel.owl.ttl +0 -0
  82. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/validation_datamodel.py +0 -0
  83. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/validation_datamodel.schema.json +0 -0
  84. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/validation_datamodel.yaml +0 -0
  85. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/value_set_configuration.owl.ttl +0 -0
  86. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/value_set_configuration.py +0 -0
  87. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/value_set_configuration.yaml +0 -0
  88. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/datamodels/vocabulary.py +0 -0
  89. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/aggregator/__init__.py +0 -0
  90. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/aggregator/aggregator_implementation.py +0 -0
  91. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/amigo/__init__.py +0 -0
  92. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/cx/__init__.py +0 -0
  93. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/cx/cx_implementation.py +0 -0
  94. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/fhir/__init__.py +0 -0
  95. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/funowl/__init__.py +0 -0
  96. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/funowl/funowl_implementation.py +0 -0
  97. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/gilda.py +0 -0
  98. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/kgx/__init__.py +0 -0
  99. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/kgx/kgx_implementation.py +0 -0
  100. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/neo4j/__init__.py +0 -0
  101. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/obograph/__init__.py +0 -0
  102. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/obograph/obograph_implementation.py +0 -0
  103. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/ols/__init__.py +0 -0
  104. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/ols/constants.py +0 -0
  105. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/ols/ols_implementation.py +0 -0
  106. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/ols/oxo_utils.py +0 -0
  107. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/ontobee/__init__.py +0 -0
  108. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/ontobee/ontobee_implementation.py +0 -0
  109. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/ontoportal/__init__.py +0 -0
  110. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/ontoportal/agroportal_implementation.py +0 -0
  111. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/ontoportal/bioportal_implementation.py +0 -0
  112. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/ontoportal/ecoportal_implementation.py +0 -0
  113. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/ontoportal/matportal_implementation.py +0 -0
  114. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/ontoportal/ontoportal_implementation_base.py +0 -0
  115. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/owlery/__init__.py +0 -0
  116. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/owlery/owlery_implementation.py +0 -0
  117. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/pronto/__init__.py +0 -0
  118. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/robot/__init__.py +0 -0
  119. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/scigraph/__init__.py +0 -0
  120. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/simpleobo/__init__.py +0 -0
  121. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/skos/__init__.py +0 -0
  122. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/solor/__init__.py +0 -0
  123. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/solr/__init__.py +0 -0
  124. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/sparql/__init__.py +0 -0
  125. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/sparql/abstract_sparql_implementation.py +0 -0
  126. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/sparql/lov_implementation.py +0 -0
  127. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/sparql/oak_metamodel_implementation.py +0 -0
  128. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/sparql/sparql_implementation.py +0 -0
  129. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/sparql/sparql_query.py +0 -0
  130. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/sqldb/__init__.py +0 -0
  131. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/sqldb/sql_implementation.py +0 -0
  132. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/sqldb/sqlite_utils.py +0 -0
  133. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/tccm/__init__.py +0 -0
  134. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/translator/__init__.py +0 -0
  135. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/translator/translator_implementation.py +0 -0
  136. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/ubergraph/__init__.py +0 -0
  137. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/ubergraph/ubergraph_implementation.py +0 -0
  138. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/umls/__init__.py +0 -0
  139. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/uniprot/__init__.py +0 -0
  140. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/uniprot/uniprot_implementation.py +0 -0
  141. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/wikidata/__init__.py +0 -0
  142. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/implementations/wikidata/wikidata_implementation.py +0 -0
  143. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/__init__.py +0 -0
  144. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/association_provider_interface.py +0 -0
  145. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/basic_ontology_interface.py +0 -0
  146. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/class_enrichment_calculation_interface.py +0 -0
  147. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/mapping_provider_interface.py +0 -0
  148. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/merge_interface.py +0 -0
  149. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/metadata_interface.py +0 -0
  150. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/obograph_interface.py +0 -0
  151. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/obolegacy_interface.py +0 -0
  152. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/ontology_interface.py +0 -0
  153. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/owl_interface.py +0 -0
  154. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/patcher_interface.py +0 -0
  155. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/rdf_interface.py +0 -0
  156. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/relation_graph_interface.py +0 -0
  157. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/search_interface.py +0 -0
  158. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/skos_interface.py +0 -0
  159. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/subsetter_interface.py +0 -0
  160. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/summary_statistics_interface.py +0 -0
  161. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/taxon_constraint_interface.py +0 -0
  162. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/text_annotator_interface.py +0 -0
  163. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/interfaces/validator_interface.py +0 -0
  164. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/__init__.py +0 -0
  165. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/heatmap_writer.py +0 -0
  166. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/html_writer.py +0 -0
  167. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/obograph_writer.py +0 -0
  168. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/rollup_report_writer.py +0 -0
  169. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/streaming_axiom_writer.py +0 -0
  170. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/streaming_csv_writer.py +0 -0
  171. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/streaming_fhir_writer.py +0 -0
  172. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/streaming_info_writer.py +0 -0
  173. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/streaming_json_lines_writer.py +0 -0
  174. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/streaming_json_writer.py +0 -0
  175. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/streaming_kgcl_writer.py +0 -0
  176. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/streaming_markdown_writer.py +0 -0
  177. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/streaming_nl_writer.py +0 -0
  178. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/streaming_obo_json_writer.py +0 -0
  179. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/streaming_obo_writer.py +0 -0
  180. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/streaming_owl_functional_writer.py +0 -0
  181. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/streaming_rdf_writer.py +0 -0
  182. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/streaming_writer.py +0 -0
  183. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/io/streaming_yaml_writer.py +0 -0
  184. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/mappers/__init__.py +0 -0
  185. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/mappers/base_mapper.py +0 -0
  186. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/mappers/ontology_metadata_mapper.py +0 -0
  187. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/parsers/__init__.py +0 -0
  188. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/parsers/association_parser.py +0 -0
  189. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/parsers/association_parser_factory.py +0 -0
  190. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/parsers/boomer_parser.py +0 -0
  191. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/parsers/gaf_association_parser.py +0 -0
  192. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/parsers/hpoa_association_parser.py +0 -0
  193. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/parsers/hpoa_g2p_association_parser.py +0 -0
  194. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/parsers/kgx_association_parser.py +0 -0
  195. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/parsers/pairwise_association_parser.py +0 -0
  196. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/parsers/parser_base.py +0 -0
  197. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/parsers/phaf_association_parser.py +0 -0
  198. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/parsers/xaf_association_parser.py +0 -0
  199. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/resource.py +0 -0
  200. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/types.py +0 -0
  201. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/__init__.py +0 -0
  202. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/apikey_manager.py +0 -0
  203. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/associations/__init__.py +0 -0
  204. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/associations/association_differ.py +0 -0
  205. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/associations/association_index.py +0 -0
  206. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/basic_utils.py +0 -0
  207. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/graph/__init__.py +0 -0
  208. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/graph/networkx_bridge.py +0 -0
  209. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/graph/relationship_walker.py +0 -0
  210. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/identifier_utils.py +0 -0
  211. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/iterator_utils.py +0 -0
  212. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/kgcl_utilities.py +0 -0
  213. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/label_utilities.py +0 -0
  214. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/lexical/__init__.py +0 -0
  215. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/lexical/lexical_indexer.py +0 -0
  216. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/mapping/__init__.py +0 -0
  217. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/mapping/boomer_utils.py +0 -0
  218. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/mapping/cross_ontology_diffs.py +0 -0
  219. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/mapping/mapping_propagator.py +0 -0
  220. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/mapping/mapping_validation.py +0 -0
  221. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/mapping/sssom_utils.py +0 -0
  222. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/ner_utilities.py +0 -0
  223. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/nlp/__init__.py +0 -0
  224. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/nlp/natual_language_generation.py +0 -0
  225. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/oboformat_utils.py +0 -0
  226. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/ontology_builder.py +0 -0
  227. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/rate_limiter.py +0 -0
  228. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/reasoning/__init__.py +0 -0
  229. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/reasoning/relation_graph.py +0 -0
  230. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/semsim/__init__.py +0 -0
  231. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/semsim/similarity_utils.py +0 -0
  232. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/stats/__init__.py +0 -0
  233. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/stats/hypergeometric.py +0 -0
  234. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/subsets/__init__.py +0 -0
  235. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/subsets/slimmer_utils.py +0 -0
  236. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/subsets/subset_analysis.py +0 -0
  237. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/subsets/value_set_expander.py +0 -0
  238. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/table_filler.py +0 -0
  239. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/taxon/__init__.py +0 -0
  240. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/taxon/taxon_constraint_utils.py +0 -0
  241. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/validation/__init__.py +0 -0
  242. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/validation/definition_ontology_rule.py +0 -0
  243. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/validation/disjointness_rule.py +0 -0
  244. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/validation/lint_utils.py +0 -0
  245. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/validation/ontology_rule.py +0 -0
  246. {oaklib-0.2.6 → oaklib-0.2.8}/src/oaklib/utilities/validation/rule_runner.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: oaklib
3
- Version: 0.2.6
3
+ Version: 0.2.8
4
4
  Summary: Ontology Access Kit: Python library for common ontology operations over a variety of backends
5
5
  Author: cmungall
6
6
  Author-email: cjm@berkeleybop.org
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "oaklib"
3
- version = "v0.2.6"
3
+ version = "v0.2.8"
4
4
  description = "Ontology Access Kit: Python library for common ontology operations over a variety of backends"
5
5
  authors = ["cmungall <cjm@berkeleybop.org>"]
6
6
 
@@ -6,6 +6,6 @@ __version__ = "0.1.0"
6
6
 
7
7
  from oaklib.interfaces import BasicOntologyInterface # noqa:F401
8
8
  from oaklib.resource import OntologyResource # noqa:F401
9
- from oaklib.selector import get_implementation_from_shorthand # noqa:F401
9
+ from oaklib.selector import get_adapter, get_implementation_from_shorthand # noqa:F401
10
10
 
11
11
  schemes = {}
@@ -11,7 +11,6 @@ import logging
11
11
  import os
12
12
  import re
13
13
  import secrets
14
- import subprocess
15
14
  import sys
16
15
  from collections import defaultdict
17
16
  from dataclasses import dataclass
@@ -744,6 +743,18 @@ def query_terms_iterator(query_terms: NESTED_LIST, impl: BasicOntologyInterface)
744
743
  chain_results(impl.ancestors(rest, predicates=this_predicates))
745
744
  else:
746
745
  raise NotImplementedError
746
+ elif term.startswith(".mrca"):
747
+ # graph query: most recent common ancestors
748
+ params = _parse_params(term)
749
+ this_predicates = params.get("predicates", predicates)
750
+ rest = list(query_terms_iterator([query_terms[0]], impl))
751
+ query_terms = query_terms[1:]
752
+ if isinstance(impl, SemanticSimilarityInterface):
753
+ chain_results(
754
+ impl.setwise_most_recent_common_ancestors(rest, predicates=this_predicates)
755
+ )
756
+ else:
757
+ raise NotImplementedError
747
758
  else:
748
759
  # term is not query syntax: feed directly to search
749
760
  if not isinstance(impl, SearchInterface):
@@ -1698,11 +1709,9 @@ def viz(
1698
1709
  if output_type:
1699
1710
  write_graph(graph, format=output_type, output=output)
1700
1711
  else:
1701
- imgfile = graph_to_image(
1702
- graph, seeds=curies, stylemap=stylemap, configure=configure, imgfile=output
1712
+ graph_to_image(
1713
+ graph, seeds=curies, stylemap=stylemap, configure=configure, imgfile=output, view=view
1703
1714
  )
1704
- if view:
1705
- subprocess.run(["open", imgfile])
1706
1715
 
1707
1716
 
1708
1717
  @main.command()
@@ -2169,10 +2178,14 @@ def paths(
2169
2178
  else:
2170
2179
  if stylemap is None:
2171
2180
  stylemap = default_stylemap_path()
2172
- imgfile = graph_to_image(
2173
- path_graph, seeds=all_curies, imgfile=output, stylemap=stylemap, configure=configure
2181
+ graph_to_image(
2182
+ path_graph,
2183
+ seeds=all_curies,
2184
+ imgfile=output,
2185
+ stylemap=stylemap,
2186
+ configure=configure,
2187
+ view=viz,
2174
2188
  )
2175
- subprocess.run(["open", imgfile])
2176
2189
 
2177
2190
 
2178
2191
  @main.command()
@@ -2266,6 +2279,12 @@ def descendants(
2266
2279
  show_default=True,
2267
2280
  help="For formats that export only IS_A by default, this will include all possible predicates",
2268
2281
  )
2282
+ @click.option(
2283
+ "--enforce-canonical-ordering/--no-enforce-canonical-ordering",
2284
+ default=False,
2285
+ show_default=True,
2286
+ help="Forces the serialization to be in canonical order, which is useful for diffing",
2287
+ )
2269
2288
  @output_type_option
2270
2289
  def dump(terms, output, output_type: str, **kwargs):
2271
2290
  """
@@ -21,6 +21,9 @@ class DataModelConverter(ABC):
21
21
  labeler: Callable[[CURIE], Optional[str]] = None
22
22
  """A function that returns a label for a given CURIE"""
23
23
 
24
+ enforce_canonical_ordering: Optional[bool] = None
25
+ """If True, will enforce canonical ordering of keys in the output"""
26
+
24
27
  def __hash__(self):
25
28
  return hash(str(self))
26
29
 
@@ -1,3 +1,6 @@
1
+ """
2
+ This package serves as the master index for all implementations.
3
+ """
1
4
  from functools import cache
2
5
 
3
6
  from class_resolver import ClassResolver
@@ -70,6 +73,26 @@ __all__ = [
70
73
 
71
74
  @cache
72
75
  def get_implementation_resolver() -> ClassResolver[OntologyInterface]:
76
+ """
77
+ Get a class resolver for all implementations (adapters).
78
+
79
+ See `<https://class-resolver.readthedocs.io/>`_
80
+
81
+ Note that typical OAK users should never need to call this directly;
82
+ this is used by OAK to dynamically select the right implementation given
83
+ a selector descriptions
84
+
85
+ As far as possible we try and use generic mechanisms to resolve.
86
+
87
+ Any class specified in __all__ above will be checked to see if it inherits from
88
+ OntologyInterface.
89
+
90
+ If the class name ends with "Implementation" (which is the convention in OAK
91
+ for all implementations), then it should be available here, wiith a descriptor
92
+ name that is downcases class name, with "Implementation" removed.
93
+
94
+ :return: A ClassResolver capable of resolving an OntologyInterface implementation
95
+ """
73
96
  implementation_resolver: ClassResolver[OntologyInterface] = ClassResolver.from_subclasses(
74
97
  OntologyInterface,
75
98
  suffix="Implementation",
@@ -78,6 +101,9 @@ def get_implementation_resolver() -> ClassResolver[OntologyInterface]:
78
101
  BaseOlsImplementation,
79
102
  },
80
103
  )
104
+ # if an implementation uses a shorthand name that is
105
+ # different from the class name (minus Implementation), then
106
+ # it should be added here
81
107
  implementation_resolver.synonyms.update(
82
108
  {
83
109
  "obolibrary": ProntoImplementation,
@@ -582,10 +582,14 @@ class ProntoImplementation(
582
582
  shutil.copyfile(self.resource.slug, resource.slug)
583
583
  return type(self)(resource)
584
584
 
585
- def dump(self, path: str = None, syntax: str = "obo", **kwargs):
585
+ def dump(
586
+ self, path: str = None, syntax: str = "obo", enforce_canonical_ordering=False, **kwargs
587
+ ):
586
588
  if syntax is None:
587
589
  syntax = "obo"
588
590
  if syntax in ["obo", "json"]:
591
+ if enforce_canonical_ordering:
592
+ raise NotImplementedError("enforce_canonical_ordering not implemented for pronto")
589
593
  # TODO: simplify the logic here; not clear why pronto wants a binary file
590
594
  if isinstance(path, str):
591
595
  with open(path, "wb") as file:
@@ -774,21 +774,26 @@ class SimpleOboImplementation(
774
774
  od = self.obo_document
775
775
  tidy_change_object(patch)
776
776
  logging.debug(f"Applying {patch}")
777
+ modified_entities = []
777
778
  if isinstance(patch, kgcl.NodeRename):
778
779
  # self.set_label(patch.about_node, _clean(patch.new_value))
779
780
  self.set_label(patch.about_node, patch.new_value)
781
+ modified_entities.append(patch.about_node)
780
782
  elif isinstance(patch, kgcl.NodeObsoletion):
781
783
  t = self._stanza(patch.about_node, strict=True)
782
784
  t.set_singular_tag(TAG_IS_OBSOLETE, "true")
783
785
  if isinstance(patch, kgcl.NodeObsoletionWithDirectReplacement):
784
786
  t.set_singular_tag(TAG_REPLACED_BY, patch.has_direct_replacement)
787
+ modified_entities.append(patch.about_node)
785
788
  elif isinstance(patch, kgcl.NodeDeletion):
786
789
  t = self._stanza(patch.about_node, strict=True)
787
790
  od.stanzas = [s for s in od.stanzas if s.id != patch.about_node]
788
791
  elif isinstance(patch, kgcl.NodeCreation):
789
792
  self.create_entity(patch.about_node, patch.name)
793
+ modified_entities.append(patch.about_node)
790
794
  elif isinstance(patch, kgcl.ClassCreation):
791
795
  self.create_entity(patch.about_node, patch.name)
796
+ modified_entities.append(patch.about_node)
792
797
  elif isinstance(patch, kgcl.SynonymReplacement):
793
798
  t = self._stanza(patch.about_node, strict=True)
794
799
  n = 0
@@ -800,6 +805,7 @@ class SimpleOboImplementation(
800
805
  n += 1
801
806
  if not n:
802
807
  raise ValueError(f"Failed to find synonym {patch.old_value} for {t.id}")
808
+ modified_entities.append(patch.about_node)
803
809
  elif isinstance(patch, kgcl.NodeTextDefinitionChange):
804
810
  t = self._stanza(patch.about_node, strict=True)
805
811
  for tv in t.tag_values:
@@ -808,6 +814,7 @@ class SimpleOboImplementation(
808
814
  elif isinstance(patch, kgcl.NewTextDefinition):
809
815
  t = self._stanza(patch.about_node, strict=True)
810
816
  t.add_tag_value(TAG_DEFINITION, patch.new_value)
817
+ modified_entities.append(patch.about_node)
811
818
  elif isinstance(patch, kgcl.NewSynonym):
812
819
  t = self._stanza(patch.about_node, strict=True)
813
820
  # Get scope from patch.qualifier
@@ -818,6 +825,7 @@ class SimpleOboImplementation(
818
825
  scope = str(patch.qualifier.value).upper() if patch.qualifier else "RELATED"
819
826
  v = patch.new_value.replace('"', '\\"')
820
827
  t.add_tag_value(TAG_SYNONYM, f'"{v}" {scope} []')
828
+ modified_entities.append(patch.about_node)
821
829
  elif isinstance(patch, kgcl.RemoveSynonym):
822
830
  t = self._stanza(patch.about_node, strict=True)
823
831
  # scope = str(patch.qualifier.value).upper() if patch.qualifier else "RELATED"
@@ -825,6 +833,7 @@ class SimpleOboImplementation(
825
833
  t.remove_simple_tag_value(TAG_SYNONYM, f'"{v}"')
826
834
  elif isinstance(patch, kgcl.EdgeCreation):
827
835
  self.add_relationship(patch.subject, patch.predicate, patch.object)
836
+ modified_entities.append(patch.subject)
828
837
  elif isinstance(patch, kgcl.EdgeDeletion):
829
838
  self.remove_relationship(patch.subject, patch.predicate, patch.object)
830
839
  elif isinstance(patch, kgcl.NodeMove):
@@ -844,8 +853,13 @@ class SimpleOboImplementation(
844
853
  else:
845
854
  t.add_tag_value(TAG_RELATIONSHIP, f"{patch.new_value} {object}")
846
855
  self._clear_relationship_index()
856
+ modified_entities.append(subject)
847
857
  else:
848
858
  raise NotImplementedError(f"cannot handle KGCL type {type(patch)}")
849
859
  if patch.contributor:
850
860
  self.add_contributors(patch.about_node, [patch.contributor])
861
+ modified_entities.append(patch.about_node)
862
+ for e in modified_entities:
863
+ stanza = self._stanza(e, strict=True)
864
+ stanza.normalize_order()
851
865
  return patch
@@ -80,18 +80,18 @@ TERM_TAGS = [
80
80
  TAG_SYNONYM,
81
81
  TAG_XREF,
82
82
  # TAG_BUILTIN,
83
- TAG_PROPERTY_VALUE,
84
83
  TAG_IS_A,
85
84
  TAG_INTERSECTION_OF,
86
85
  TAG_UNION_OF,
87
86
  TAG_EQUIVALENT_TO,
88
87
  TAG_DISJOINT_FROM,
89
88
  TAG_RELATIONSHIP,
90
- TAG_CREATED_BY,
91
- TAG_CREATION_DATE,
89
+ TAG_PROPERTY_VALUE,
92
90
  TAG_IS_OBSOLETE,
93
91
  TAG_REPLACED_BY,
94
92
  TAG_CONSIDER,
93
+ TAG_CREATED_BY,
94
+ TAG_CREATION_DATE,
95
95
  ]
96
96
 
97
97
 
@@ -101,6 +101,47 @@ def _parse_list(as_str: str) -> List[str]:
101
101
  return as_str.split(", ")
102
102
 
103
103
 
104
+ @dataclass
105
+ class ValueComponent:
106
+ pass
107
+
108
+ def order(self) -> Tuple:
109
+ pass
110
+
111
+
112
+ @dataclass
113
+ class QuotedText(ValueComponent):
114
+ value: str
115
+
116
+ def order(self) -> Tuple[str, str]:
117
+ return self.value.lower(), self.value
118
+
119
+
120
+ @dataclass
121
+ class SimpleValue(ValueComponent):
122
+ value: str
123
+
124
+ def order(self) -> Tuple[str, str]:
125
+ return (self.value,)
126
+ # return self.value.lower(), self.value
127
+
128
+
129
+ @dataclass
130
+ class XrefList(ValueComponent):
131
+ values: List[str]
132
+
133
+ def order(self) -> Tuple:
134
+ return tuple(self.values)
135
+
136
+
137
+ @dataclass
138
+ class Comment(ValueComponent):
139
+ value: str
140
+
141
+ def order(self) -> Tuple:
142
+ return (0,)
143
+
144
+
104
145
  @dataclass
105
146
  class TagValue:
106
147
  """Simple unparsed tag-value pair"""
@@ -171,11 +212,101 @@ class TagValue:
171
212
  toks = [curie_map.get(x, x) for x in toks]
172
213
  self.value = " ".join(toks)
173
214
 
174
- def order(self) -> Tuple[int, int]:
215
+ def values_as_tuple(self) -> Tuple:
216
+ """
217
+ Return a tuple of values for sorting
218
+
219
+ :return:
220
+ """
221
+ toks = [x for x in self.value.split(" ") if x]
222
+ tpl = []
223
+ for t in toks:
224
+ if t.startswith("!"):
225
+ break
226
+ tpl.append(t)
227
+ return tuple(tpl)
228
+
229
+ def tokenize(self) -> List[ValueComponent]:
230
+ """
231
+ Tokenize the value
232
+
233
+ :return:
234
+ """
235
+ if self.tag == TAG_NAME:
236
+ return [SimpleValue(self.value)]
237
+ toks = [x for x in self.value.split(" ") if x]
238
+ cmt = ""
239
+ components = []
240
+ while toks:
241
+ t = toks.pop(0)
242
+ if t.startswith("!"):
243
+ cmt = " ".join(toks)
244
+ break
245
+ if t.startswith('"'):
246
+ toks.insert(0, t)
247
+ s = ""
248
+ while True:
249
+ if not toks:
250
+ raise ValueError(f"Badly quoted value: {self.value}")
251
+ if s:
252
+ s += " "
253
+ s += toks.pop(0)
254
+ closed = False
255
+ if '"' in s:
256
+ for i, char in enumerate(s):
257
+ # Check if the current character is a quote and not escaped
258
+ if char == '"' and i > 0 and s[i - 1] != "\\":
259
+ s = s[0:i]
260
+ rest = s[i + 1 :]
261
+ if len(rest) > 0:
262
+ toks.insert(0, rest)
263
+ closed = True
264
+ break
265
+ if closed:
266
+ break
267
+ components.append(QuotedText(s))
268
+ elif t.startswith("["):
269
+ toks.insert(0, t[1:])
270
+ xrefs = []
271
+ while True:
272
+ if not toks:
273
+ raise ValueError(f"Xref list does not terminate: {self.value}")
274
+ next_tok = toks.pop(0)
275
+ if next_tok.endswith("]"):
276
+ xrefs.append(next_tok[:-1])
277
+ break
278
+ xrefs.append(next_tok)
279
+ # TODO
280
+ components.append(XrefList(xrefs))
281
+ else:
282
+ components.append(SimpleValue(t))
283
+ if cmt:
284
+ components.append(Comment(cmt))
285
+ return components
286
+
287
+ def order(self) -> Tuple:
288
+ """
289
+ Order for sorting tag-value pairs.
290
+
291
+ Note: we aim for consistency with OWLAPI, which differs partially from
292
+ https://owlcollab.github.io/oboformat/doc/GO.format.obo-1_4.html
293
+ :return:
294
+ """
175
295
  t = self.tag
176
296
  v1 = TERM_TAGS.index(t) if t in TERM_TAGS else 99
177
- v2 = str(self.value)
178
- return v1, v2
297
+ toks = self.tokenize()
298
+ if self.tag == TAG_SYNONYM:
299
+ # normalize a synonym by placing a blank type if not present
300
+ if isinstance(toks[2], XrefList):
301
+ # necessary to preserve owlapi order
302
+ toks.insert(2, SimpleValue("zzzzz"))
303
+ order_values = []
304
+ for x in toks:
305
+ order_values.append(x.order())
306
+ if self.tag == TAG_INTERSECTION_OF:
307
+ tpl = self.values_as_tuple()
308
+ order_values = [chr(96 + len(list(tpl)))] + order_values
309
+ return tuple([v1] + order_values)
179
310
 
180
311
 
181
312
  @dataclass
@@ -420,28 +551,56 @@ class OboDocument:
420
551
  stanzas: Mapping[CURIE, Stanza] = field(default_factory=lambda: {})
421
552
 
422
553
  def add_stanza(self, stanza: Stanza) -> None:
554
+ """
555
+ Adds a stanza to the document.
556
+
557
+ Ensures stanza added in order.
558
+ :param stanza:
559
+ :return:
560
+ """
423
561
  self.stanzas[stanza.id] = stanza
562
+ self.order_stanzas()
424
563
 
425
564
  def reindex(self) -> None:
426
565
  self.stanzas = {s.id: s for s in self.stanzas.values()}
427
566
 
428
- def dump(self, file: TextIO, sort_tags=True) -> None:
567
+ def order_stanzas(self) -> None:
568
+ """
569
+ Orders stanzas by ID
570
+
571
+ Does not change tag-value ordering within stanzas
572
+ """
573
+ stanzas = self.stanzas.values()
574
+ stanzas = sorted(stanzas, key=lambda x: x.id)
575
+ self.stanzas = {s.id: s for s in stanzas}
576
+
577
+ def normalize_line_order(self) -> None:
578
+ """
579
+ Normalizes line order within stanzas
580
+ """
581
+ for s in self.stanzas.values():
582
+ s.normalize_order()
583
+
584
+ def dump(self, file: TextIO, ensure_sorted=False, normalize_line_order=False) -> None:
429
585
  """Export to a file
430
586
 
431
587
  :param file:
588
+ :param ensure_sorted: Sort stanzas
589
+ :param normalize_line_order: Sort tags within stanzas
432
590
  """
433
- if sort_tags:
434
- stanzas = self.stanzas.values()
435
- stanzas = sorted(stanzas, key=lambda x: x.id)
436
- self.stanzas = {s.id: s for s in stanzas}
437
- for s in stanzas:
438
- s.normalize_order()
591
+ if ensure_sorted:
592
+ self.order_stanzas()
593
+ if normalize_line_order:
594
+ self.normalize_line_order()
439
595
 
440
596
  self._dump_tag_values(self.header.tag_values, file)
441
597
  for s in self.stanzas.values():
442
- file.write(f"[{s.type}]\n")
443
- file.write(f"id: {s.id}\n")
444
- self._dump_tag_values(s.tag_values, file)
598
+ self._dump_stanza(s, file)
599
+
600
+ def _dump_stanza(self, stanza: Stanza, file: TextIO):
601
+ file.write(f"[{stanza.type}]\n")
602
+ file.write(f"id: {stanza.id}\n")
603
+ self._dump_tag_values(stanza.tag_values, file)
445
604
 
446
605
  def _dump_tag_values(self, tag_values: List[TagValue], file: TextIO):
447
606
  for tv in tag_values:
@@ -137,7 +137,7 @@ class DifferInterface(BasicOntologyInterface, ABC):
137
137
  id=_gen_id(), about_edge=edge, old_value=pred, new_value=switches[0]
138
138
  )
139
139
  else:
140
- yield kgcl.NodeMove(id=_gen_id(), about_edge=edge, old_value=pred)
140
+ yield kgcl.EdgeDeletion(id=_gen_id(), subject=e1, predicate=pred, object=filler)
141
141
  for rel in e2_rels.difference(e1_rels):
142
142
  pred, filler = rel
143
143
  edge = kgcl.Edge(subject=e1, predicate=pred, object=filler)
@@ -191,7 +191,10 @@ class DifferInterface(BasicOntologyInterface, ABC):
191
191
  if isinstance(change, kgcl.NodeChange):
192
192
  about = change.about_node
193
193
  elif isinstance(change, kgcl.EdgeChange):
194
- about = change.about_edge.subject
194
+ if isinstance(change, kgcl.EdgeDeletion):
195
+ about = change.subject
196
+ else:
197
+ about = change.about_edge.subject
195
198
  else:
196
199
  about = None
197
200
  partition = RESIDUAL_KEY
@@ -32,12 +32,16 @@ class DumperInterface(BasicOntologyInterface, ABC):
32
32
  An OntologyInterface that is capable of exporting entire contents.
33
33
  """
34
34
 
35
- def dump(self, path: str = None, syntax: str = None, **kwargs):
35
+ def dump(
36
+ self, path: str = None, syntax: str = None, enforce_canonical_ordering=False, **kwargs
37
+ ):
36
38
  """
37
39
  Exports current contents.
38
40
 
39
- :param path:
40
- :param syntax:
41
+ :param path: Path to file to write to. If None, then write to stdout.
42
+ :param syntax: Syntax to use. If None, then use the default syntax.
43
+ :param enforce_canonical_ordering:
44
+ :param kwargs: Additional arguments to pass to the dumper
41
45
  :return:
42
46
  """
43
47
  logging.info(f"Dumping graph to {path} in {syntax}")
@@ -58,6 +62,7 @@ class DumperInterface(BasicOntologyInterface, ABC):
58
62
  print(json_str)
59
63
  else:
60
64
  converter = OBOGRAPH_CONVERTERS[syntax]()
65
+ converter.enforce_canonical_ordering = enforce_canonical_ordering
61
66
  logging.info(f"Using {converter}")
62
67
  converter.curie_converter = self.converter
63
68
  kwargs = {k: v for k, v in kwargs.items() if v is not None}
@@ -65,6 +65,42 @@ class SemanticSimilarityInterface(BasicOntologyInterface, ABC):
65
65
  else:
66
66
  raise NotImplementedError
67
67
 
68
+ def setwise_most_recent_common_ancestors(
69
+ self,
70
+ subjects: List[CURIE],
71
+ predicates: List[PRED_CURIE] = None,
72
+ include_owl_thing: bool = True,
73
+ ) -> Iterable[CURIE]:
74
+ """
75
+ Most recent common ancestors (MRCAs) for a set of entities
76
+
77
+ The MRCAs are the set of Common Ancestors (CAs) that are not themselves proper
78
+ ancestors of another CA
79
+
80
+ :param subjects:
81
+ :param predicates:
82
+ :param include_owl_thing:
83
+ :return:
84
+ """
85
+ if not isinstance(self, OboGraphInterface):
86
+ raise NotImplementedError
87
+ ancs = []
88
+ for s in subjects:
89
+ ancs.append(set(self.ancestors([s], predicates)))
90
+ common = set.intersection(*ancs)
91
+ ancs_of_common = []
92
+ for ca in common:
93
+ for caa in self.ancestors(ca, predicates):
94
+ if caa != ca:
95
+ ancs_of_common.append(caa)
96
+ n = 0
97
+ for a in common:
98
+ if a not in ancs_of_common:
99
+ yield a
100
+ n += 1
101
+ if n == 0 and include_owl_thing:
102
+ yield OWL_THING
103
+
68
104
  def multiset_most_recent_common_ancestors(
69
105
  self, subjects: List[CURIE], predicates: List[PRED_CURIE] = None, asymmetric=True
70
106
  ) -> Iterable[Tuple[CURIE, CURIE, CURIE]]: