rustdl 0.2.2__tar.gz → 0.3.1__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 (152) hide show
  1. {rustdl-0.2.2 → rustdl-0.3.1}/Cargo.lock +9 -9
  2. {rustdl-0.2.2 → rustdl-0.3.1}/Cargo.toml +6 -6
  3. {rustdl-0.2.2 → rustdl-0.3.1}/PKG-INFO +62 -15
  4. {rustdl-0.2.2/crates/owl-dl-py → rustdl-0.3.1}/README.md +61 -14
  5. {rustdl-0.2.2 → rustdl-0.3.1/crates/owl-dl-py}/README.md +61 -14
  6. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-py/src/classify.rs +25 -3
  7. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-py/tests/python/test_classify.py +30 -0
  8. rustdl-0.3.1/crates/owl-dl-py/tests/python/test_examples.py +34 -0
  9. {rustdl-0.2.2 → rustdl-0.3.1}/pyproject.toml +1 -0
  10. rustdl-0.3.1/python/rustdl/__init__.py +132 -0
  11. rustdl-0.3.1/python/rustdl/data/pizza.owl.gz +0 -0
  12. rustdl-0.3.1/python/rustdl/data/sio.owl.gz +0 -0
  13. rustdl-0.3.1/python/rustdl/data/sulo.owl.gz +0 -0
  14. rustdl-0.3.1/python/rustdl/examples.py +115 -0
  15. rustdl-0.2.2/python/rustdl/__init__.py +0 -69
  16. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/Cargo.toml +0 -0
  17. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/README.md +0 -0
  18. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/src/absorb.rs +0 -0
  19. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/src/clause.rs +0 -0
  20. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/src/convert.rs +0 -0
  21. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/src/convert_back.rs +0 -0
  22. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/src/data_axioms.rs +0 -0
  23. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/src/definitions.rs +0 -0
  24. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/src/ir.rs +0 -0
  25. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/src/lib.rs +0 -0
  26. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/src/locality.rs +0 -0
  27. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/src/normalize.rs +0 -0
  28. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/src/ontology.rs +0 -0
  29. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/src/residual_trigger.rs +0 -0
  30. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/src/role_hierarchy.rs +0 -0
  31. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/src/told.rs +0 -0
  32. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/src/transform.rs +0 -0
  33. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/src/vocab.rs +0 -0
  34. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/tests/concept_pool_proptest.proptest-regressions +0 -0
  35. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/tests/concept_pool_proptest.rs +0 -0
  36. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/tests/convert_round_trip_proptest.rs +0 -0
  37. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-core/tests/role_hierarchy_proptest.rs +0 -0
  38. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-datatypes/Cargo.toml +0 -0
  39. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-datatypes/README.md +0 -0
  40. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-datatypes/src/lib.rs +0 -0
  41. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-py/.gitignore +0 -0
  42. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-py/Cargo.toml +0 -0
  43. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-py/src/errors.rs +0 -0
  44. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-py/src/lib.rs +0 -0
  45. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-py/src/load.rs +0 -0
  46. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-py/src/materialize.rs +0 -0
  47. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-py/src/queries.rs +0 -0
  48. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-py/tests/python/conftest.py +0 -0
  49. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-py/tests/python/test_materialize.py +0 -0
  50. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-py/tests/python/test_queries.py +0 -0
  51. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-py/tests/python/test_smoke.py +0 -0
  52. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-py/tests/python/test_soundness.py +0 -0
  53. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/Cargo.toml +0 -0
  54. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/README.md +0 -0
  55. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/src/abox_check.rs +0 -0
  56. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/src/classify.rs +0 -0
  57. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/src/lib.rs +0 -0
  58. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/src/model_cache.rs +0 -0
  59. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/src/realize.rs +0 -0
  60. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/src/union_find.rs +0 -0
  61. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/abox_consistency.rs +0 -0
  62. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/anon349_diagnostic.rs +0 -0
  63. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/datatype_completeness.rs +0 -0
  64. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/abox/p1_direct_bot.ofn +0 -0
  65. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/abox/p1_no_bot.ofn +0 -0
  66. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/abox/p2_disjoint_different_individuals.ofn +0 -0
  67. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/abox/p2_disjoint_types.ofn +0 -0
  68. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/abox/p3_neg_opa.ofn +0 -0
  69. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/abox/p3_neg_opa_no_clash.ofn +0 -0
  70. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/abox/p3_role_hierarchy_neg_consistent.ofn +0 -0
  71. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/abox/p3_role_hierarchy_neg_inconsistent.ofn +0 -0
  72. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/abox/p4_same_different.ofn +0 -0
  73. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/abox/p4_same_without_different.ofn +0 -0
  74. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/abox/p5_functional_diff.ofn +0 -0
  75. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/abox/p5_functional_same_target.ofn +0 -0
  76. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/abox/p6_asymmetric.ofn +0 -0
  77. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/abox/p6_asymmetric_one_way.ofn +0 -0
  78. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/abox/p6_irreflexive.ofn +0 -0
  79. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/abox/p6_irreflexive_distinct.ofn +0 -0
  80. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/abox/p7_range_compatible.ofn +0 -0
  81. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/abox/p7_range_disjoint.ofn +0 -0
  82. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/datatype/data_cardinality_disjoint.ofn +0 -0
  83. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/datatype/data_property_domain-classified.owx +0 -0
  84. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/datatype/data_property_domain.ofn +0 -0
  85. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/datatype/datatype_definition-classified.owx +0 -0
  86. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/datatype/datatype_definition.ofn +0 -0
  87. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/datatype/datatype_facet.ofn +0 -0
  88. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/datatype/functional_data_property.ofn +0 -0
  89. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/datatype/sub_data_property-classified.owx +0 -0
  90. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/datatype/sub_data_property.ofn +0 -0
  91. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/functional-equiv-some-bug.ofn +0 -0
  92. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/named-pizza-country-bug.ofn +0 -0
  93. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-01.txt +0 -0
  94. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-02.txt +0 -0
  95. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-03.txt +0 -0
  96. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-04.txt +0 -0
  97. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-05.txt +0 -0
  98. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-06.txt +0 -0
  99. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-07.txt +0 -0
  100. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/p2b0-terms-08.txt +0 -0
  101. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_01.hermit.owx +0 -0
  102. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_01.ofn +0 -0
  103. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_01.owx +0 -0
  104. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_02.hermit.owx +0 -0
  105. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_02.ofn +0 -0
  106. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_02.owx +0 -0
  107. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_03.hermit.owx +0 -0
  108. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_03.ofn +0 -0
  109. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_03.owx +0 -0
  110. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_04.hermit.owx +0 -0
  111. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_04.ofn +0 -0
  112. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_04.owx +0 -0
  113. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_05.hermit.owx +0 -0
  114. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_05.ofn +0 -0
  115. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_05.owx +0 -0
  116. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_06.hermit.owx +0 -0
  117. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_06.ofn +0 -0
  118. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_06.owx +0 -0
  119. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_07.hermit.owx +0 -0
  120. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_07.ofn +0 -0
  121. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_07.owx +0 -0
  122. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_08.hermit.owx +0 -0
  123. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_08.ofn +0 -0
  124. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/pair_08.owx +0 -0
  125. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/fixtures/phase2b/phase2b-verdicts.log +0 -0
  126. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/konclude_closure_diff.rs +0 -0
  127. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/label_heuristic_canary.rs +0 -0
  128. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/phase2c_pair_06_canary.rs +0 -0
  129. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/real_ontology_corpus.rs +0 -0
  130. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-reasoner/tests/snapshot_phase0_canary.rs +0 -0
  131. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-saturation/Cargo.toml +0 -0
  132. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-saturation/README.md +0 -0
  133. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-saturation/src/lib.rs +0 -0
  134. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-saturation/tests/fixtures/phase2a_functional_role_canary.ofn +0 -0
  135. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-saturation/tests/fixtures/phase2b_compound_existential_canary.ofn +0 -0
  136. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-tableau/Cargo.toml +0 -0
  137. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-tableau/README.md +0 -0
  138. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-tableau/src/counters.rs +0 -0
  139. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-tableau/src/deps.rs +0 -0
  140. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-tableau/src/graph.rs +0 -0
  141. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-tableau/src/hyper.rs +0 -0
  142. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-tableau/src/lib.rs +0 -0
  143. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-tableau/src/replay.rs +0 -0
  144. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-tableau/src/rules.rs +0 -0
  145. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-tableau/src/saturate.rs +0 -0
  146. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-tableau/src/search.rs +0 -0
  147. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-tableau/src/snapshot.rs +0 -0
  148. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-tableau/src/trail.rs +0 -0
  149. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-tableau/tests/backprop_risk.rs +0 -0
  150. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-tableau/tests/replay_driver.rs +0 -0
  151. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-tableau/tests/replay_roundtrip.rs +0 -0
  152. {rustdl-0.2.2 → rustdl-0.3.1}/crates/owl-dl-tableau/tests/snapshot_capture.rs +0 -0
@@ -1037,7 +1037,7 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
1037
1037
 
1038
1038
  [[package]]
1039
1039
  name = "owl-dl-bench"
1040
- version = "0.2.2"
1040
+ version = "0.3.1"
1041
1041
  dependencies = [
1042
1042
  "anyhow",
1043
1043
  "clap",
@@ -1054,7 +1054,7 @@ dependencies = [
1054
1054
 
1055
1055
  [[package]]
1056
1056
  name = "owl-dl-cli"
1057
- version = "0.2.2"
1057
+ version = "0.3.1"
1058
1058
  dependencies = [
1059
1059
  "anyhow",
1060
1060
  "clap",
@@ -1066,7 +1066,7 @@ dependencies = [
1066
1066
 
1067
1067
  [[package]]
1068
1068
  name = "owl-dl-core"
1069
- version = "0.2.2"
1069
+ version = "0.3.1"
1070
1070
  dependencies = [
1071
1071
  "bitvec",
1072
1072
  "bumpalo",
@@ -1080,7 +1080,7 @@ dependencies = [
1080
1080
 
1081
1081
  [[package]]
1082
1082
  name = "owl-dl-datatypes"
1083
- version = "0.2.2"
1083
+ version = "0.3.1"
1084
1084
  dependencies = [
1085
1085
  "owl-dl-core",
1086
1086
  "proptest",
@@ -1090,7 +1090,7 @@ dependencies = [
1090
1090
 
1091
1091
  [[package]]
1092
1092
  name = "owl-dl-py"
1093
- version = "0.2.2"
1093
+ version = "0.3.1"
1094
1094
  dependencies = [
1095
1095
  "horned-owl",
1096
1096
  "owl-dl-core",
@@ -1101,7 +1101,7 @@ dependencies = [
1101
1101
 
1102
1102
  [[package]]
1103
1103
  name = "owl-dl-reasoner"
1104
- version = "0.2.2"
1104
+ version = "0.3.1"
1105
1105
  dependencies = [
1106
1106
  "dashmap",
1107
1107
  "horned-owl",
@@ -1117,7 +1117,7 @@ dependencies = [
1117
1117
 
1118
1118
  [[package]]
1119
1119
  name = "owl-dl-saturation"
1120
- version = "0.2.2"
1120
+ version = "0.3.1"
1121
1121
  dependencies = [
1122
1122
  "dashmap",
1123
1123
  "fixedbitset",
@@ -1133,7 +1133,7 @@ dependencies = [
1133
1133
 
1134
1134
  [[package]]
1135
1135
  name = "owl-dl-tableau"
1136
- version = "0.2.2"
1136
+ version = "0.3.1"
1137
1137
  dependencies = [
1138
1138
  "bitvec",
1139
1139
  "bumpalo",
@@ -2569,7 +2569,7 @@ dependencies = [
2569
2569
 
2570
2570
  [[package]]
2571
2571
  name = "xtask"
2572
- version = "0.2.2"
2572
+ version = "0.3.1"
2573
2573
  dependencies = [
2574
2574
  "anyhow",
2575
2575
  "clap",
@@ -3,7 +3,7 @@ resolver = "2"
3
3
  members = ["crates/owl-dl-core", "crates/owl-dl-saturation", "crates/owl-dl-tableau", "crates/owl-dl-datatypes", "crates/owl-dl-reasoner", "crates/owl-dl-py"]
4
4
 
5
5
  [workspace.package]
6
- version = "0.2.2"
6
+ version = "0.3.1"
7
7
  edition = "2024"
8
8
  rust-version = "1.88"
9
9
  license = "Apache-2.0 OR MIT"
@@ -15,11 +15,11 @@ keywords = ["owl", "ontology", "reasoner", "description-logic", "semantic-web"]
15
15
  categories = ["science", "data-structures"]
16
16
 
17
17
  [workspace.dependencies]
18
- owl-dl-core = { path = "crates/owl-dl-core", version = "0.2.2" }
19
- owl-dl-saturation = { path = "crates/owl-dl-saturation", version = "0.2.2" }
20
- owl-dl-tableau = { path = "crates/owl-dl-tableau", version = "0.2.2" }
21
- owl-dl-datatypes = { path = "crates/owl-dl-datatypes", version = "0.2.2" }
22
- owl-dl-reasoner = { path = "crates/owl-dl-reasoner", version = "0.2.2" }
18
+ owl-dl-core = { path = "crates/owl-dl-core", version = "0.3.1" }
19
+ owl-dl-saturation = { path = "crates/owl-dl-saturation", version = "0.3.1" }
20
+ owl-dl-tableau = { path = "crates/owl-dl-tableau", version = "0.3.1" }
21
+ owl-dl-datatypes = { path = "crates/owl-dl-datatypes", version = "0.3.1" }
22
+ owl-dl-reasoner = { path = "crates/owl-dl-reasoner", version = "0.3.1" }
23
23
 
24
24
  horned-owl = { version = "1.4", default-features = false }
25
25
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rustdl
3
- Version: 0.2.2
3
+ Version: 0.3.1
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Science/Research
6
6
  Classifier: License :: OSI Approved :: Apache Software License
@@ -48,18 +48,58 @@ Wheels are published for CPython 3.10+ on Linux (x86_64, aarch64), macOS
48
48
  ```python
49
49
  import rustdl
50
50
 
51
- # Classify an ontology. Format auto-detected from the extension:
51
+ # A small OWL 2 DL ontology ships inside the wheel (gzip-compressed) no
52
+ # download needed. `examples.pizza()` returns its file path (decompressed
53
+ # into a per-user cache dir on first use); `examples.PIZZA_NS` is its
54
+ # namespace, so class IRIs are PIZZA_NS + local name (e.g. + "Pizza").
55
+ from rustdl.examples import pizza, PIZZA_NS, SULO_NS
56
+
57
+ # Classify. Format is auto-detected from the extension:
52
58
  # .ofn (OWL Functional), .owx (OWL/XML), .rdf / .owl (RDF/XML).
53
- result = rustdl.classify("pizza.ofn")
59
+ result = rustdl.classify(pizza())
54
60
 
55
- print(f"{len(result.classes)} classes, {len(result.unsatisfiable)} unsatisfiable")
61
+ print(f"{len(result.classes)} classes, {len(result.unsatisfiable)} unsatisfiable, "
62
+ f"complete={result.complete}")
63
+ # -> 88 classes, 0 unsatisfiable, complete=True
56
64
 
57
65
  # Query the computed hierarchy
58
- result.is_subclass("http://ex.org/Margherita", "http://ex.org/Pizza") # -> bool
59
- result.subclasses_of("http://ex.org/Pizza") # -> list[str]
60
- result.superclasses_of("http://ex.org/Margherita") # -> list[str]
61
- result.equivalent_classes("http://ex.org/Pizza") # -> list[str]
62
- result.direct_subsumers("http://ex.org/Margherita") # -> list[str] (Hasse-direct parents)
66
+ print(result.is_subclass(PIZZA_NS + "BoxedPizza", PIZZA_NS + "Pizza"))
67
+ # -> True
68
+ print(len(result.subclasses_of(PIZZA_NS + "FoodMaterial")))
69
+ # -> 25
70
+
71
+ # The pizza ontology is aligned to the SULO upper ontology, so reasoning
72
+ # spans both — e.g. a pizza-making timestamp is inferred to be a SULO StartTime:
73
+ print(result.is_subclass(PIZZA_NS + "BakingStartTime", SULO_NS + "StartTime"))
74
+ # -> True
75
+
76
+ # Other hierarchy queries (all take full class IRIs):
77
+ result.superclasses_of(PIZZA_NS + "Cheese") # -> list[str]
78
+ result.equivalent_classes(PIZZA_NS + "Pizza") # -> list[str]
79
+ result.direct_subsumers(PIZZA_NS + "BoxedPizza") # -> list[str] (Hasse-direct parents)
80
+ ```
81
+
82
+ ### Bundled examples
83
+
84
+ Three real ontologies ship inside the wheel, gzip-compressed (~200 KB total).
85
+ They classify with **no network access** — each `examples.X()` decompresses
86
+ its ontology into a per-user cache dir (`$XDG_CACHE_HOME/rustdl/examples` or
87
+ `~/.cache/rustdl/examples`) on first use, then reuses it. Each `examples.X_NS`
88
+ is the namespace, so a class IRI is the namespace plus the local name.
89
+
90
+ | helper | ontology | classes | notes |
91
+ |---|---|---|---|
92
+ | `pizza()` / `PIZZA_NS` | ontostart pizza | 88 | SULO-aligned pizza-making ontology; classifies instantly + complete |
93
+ | `sulo()` / `SULO_NS` | SULO (Simple Upper-Level Ontology) | 17 | tiny; classifies in milliseconds |
94
+ | `sio()` / `SIO_NS` | SIO (Semanticscience Integrated Ontology) | ~1600 | realistic larger workload; takes tens of seconds. Class IRIs are numeric codes, e.g. `SIO_NS + "SIO_000006"` ("process") |
95
+
96
+ ```python
97
+ import rustdl
98
+ from rustdl import examples
99
+
100
+ r = rustdl.classify(examples.sulo())
101
+ print(r.is_subclass(examples.SULO_NS + "StartTime", examples.SULO_NS + "Object"))
102
+ # -> True
63
103
  ```
64
104
 
65
105
  ## API
@@ -67,15 +107,20 @@ result.direct_subsumers("http://ex.org/Margherita") # -> list[str] (Hasse-direct
67
107
  ### Classification
68
108
 
69
109
  ```python
70
- result = rustdl.classify(path, *, per_pair_timeout_ms=None, saturation_only=False)
71
- result = rustdl.classify_bytes(data, format="ofn", *, per_pair_timeout_ms=None, saturation_only=False)
110
+ result = rustdl.classify(path, *, per_pair_timeout_ms=1000, saturation_only=False)
111
+ result = rustdl.classify_bytes(data, format="ofn", *, per_pair_timeout_ms=1000, saturation_only=False)
72
112
  ```
73
113
 
74
- - `per_pair_timeout_ms` — bound each subsumption test; pairs that exceed it
75
- default to "not subsumed" (a sound under-approximation robust against
76
- pathological SROIQ inputs).
114
+ - `per_pair_timeout_ms` — bound each subsumption test (**default 1000**;
115
+ `0` = unbounded). A pair that exceeds the budget is recorded as "not
116
+ subsumed": **sound** (never a false subsumption) but the result may be
117
+ **incomplete**. When that happens, an `IncompleteClassificationWarning`
118
+ is emitted and `result.complete` is `False`. Pass `0` for the complete,
119
+ unbounded classification. The default bounds pathological SROIQ inputs
120
+ so classification can't hang silently.
77
121
  - `saturation_only` — skip the tableau entirely; EL-closure-only
78
- under-approximation. Dramatically faster on mostly-EL ontologies.
122
+ under-approximation. Dramatically faster on mostly-EL ontologies, and
123
+ always `complete` (no tableau ⇒ no timeout).
79
124
 
80
125
  `classify` / `classify_bytes` return a `Classification`:
81
126
 
@@ -84,6 +129,8 @@ result = rustdl.classify_bytes(data, format="ofn", *, per_pair_timeout_ms=None,
84
129
  | `.classes` | `list[str]` | all declared class IRIs |
85
130
  | `.unsatisfiable` | `list[str]` | classes proved `⊑ ⊥` |
86
131
  | `.inconsistent` | `bool` | whole ontology unsatisfiable |
132
+ | `.complete` | `bool` | `False` if any pair hit the timeout (result may miss edges) |
133
+ | `.timed_out_pairs` | `int` | how many pairs hit the timeout |
87
134
  | `.is_subclass(sub, sup)` | `bool` | is `sub ⊑ sup` entailed? |
88
135
  | `.subclasses_of(cls)` | `list[str]` | every `D` with `D ⊑ cls` |
89
136
  | `.superclasses_of(cls)` | `list[str]` | every `D` with `cls ⊑ D` |
@@ -23,18 +23,58 @@ Wheels are published for CPython 3.10+ on Linux (x86_64, aarch64), macOS
23
23
  ```python
24
24
  import rustdl
25
25
 
26
- # Classify an ontology. Format auto-detected from the extension:
26
+ # A small OWL 2 DL ontology ships inside the wheel (gzip-compressed) no
27
+ # download needed. `examples.pizza()` returns its file path (decompressed
28
+ # into a per-user cache dir on first use); `examples.PIZZA_NS` is its
29
+ # namespace, so class IRIs are PIZZA_NS + local name (e.g. + "Pizza").
30
+ from rustdl.examples import pizza, PIZZA_NS, SULO_NS
31
+
32
+ # Classify. Format is auto-detected from the extension:
27
33
  # .ofn (OWL Functional), .owx (OWL/XML), .rdf / .owl (RDF/XML).
28
- result = rustdl.classify("pizza.ofn")
34
+ result = rustdl.classify(pizza())
29
35
 
30
- print(f"{len(result.classes)} classes, {len(result.unsatisfiable)} unsatisfiable")
36
+ print(f"{len(result.classes)} classes, {len(result.unsatisfiable)} unsatisfiable, "
37
+ f"complete={result.complete}")
38
+ # -> 88 classes, 0 unsatisfiable, complete=True
31
39
 
32
40
  # Query the computed hierarchy
33
- result.is_subclass("http://ex.org/Margherita", "http://ex.org/Pizza") # -> bool
34
- result.subclasses_of("http://ex.org/Pizza") # -> list[str]
35
- result.superclasses_of("http://ex.org/Margherita") # -> list[str]
36
- result.equivalent_classes("http://ex.org/Pizza") # -> list[str]
37
- result.direct_subsumers("http://ex.org/Margherita") # -> list[str] (Hasse-direct parents)
41
+ print(result.is_subclass(PIZZA_NS + "BoxedPizza", PIZZA_NS + "Pizza"))
42
+ # -> True
43
+ print(len(result.subclasses_of(PIZZA_NS + "FoodMaterial")))
44
+ # -> 25
45
+
46
+ # The pizza ontology is aligned to the SULO upper ontology, so reasoning
47
+ # spans both — e.g. a pizza-making timestamp is inferred to be a SULO StartTime:
48
+ print(result.is_subclass(PIZZA_NS + "BakingStartTime", SULO_NS + "StartTime"))
49
+ # -> True
50
+
51
+ # Other hierarchy queries (all take full class IRIs):
52
+ result.superclasses_of(PIZZA_NS + "Cheese") # -> list[str]
53
+ result.equivalent_classes(PIZZA_NS + "Pizza") # -> list[str]
54
+ result.direct_subsumers(PIZZA_NS + "BoxedPizza") # -> list[str] (Hasse-direct parents)
55
+ ```
56
+
57
+ ### Bundled examples
58
+
59
+ Three real ontologies ship inside the wheel, gzip-compressed (~200 KB total).
60
+ They classify with **no network access** — each `examples.X()` decompresses
61
+ its ontology into a per-user cache dir (`$XDG_CACHE_HOME/rustdl/examples` or
62
+ `~/.cache/rustdl/examples`) on first use, then reuses it. Each `examples.X_NS`
63
+ is the namespace, so a class IRI is the namespace plus the local name.
64
+
65
+ | helper | ontology | classes | notes |
66
+ |---|---|---|---|
67
+ | `pizza()` / `PIZZA_NS` | ontostart pizza | 88 | SULO-aligned pizza-making ontology; classifies instantly + complete |
68
+ | `sulo()` / `SULO_NS` | SULO (Simple Upper-Level Ontology) | 17 | tiny; classifies in milliseconds |
69
+ | `sio()` / `SIO_NS` | SIO (Semanticscience Integrated Ontology) | ~1600 | realistic larger workload; takes tens of seconds. Class IRIs are numeric codes, e.g. `SIO_NS + "SIO_000006"` ("process") |
70
+
71
+ ```python
72
+ import rustdl
73
+ from rustdl import examples
74
+
75
+ r = rustdl.classify(examples.sulo())
76
+ print(r.is_subclass(examples.SULO_NS + "StartTime", examples.SULO_NS + "Object"))
77
+ # -> True
38
78
  ```
39
79
 
40
80
  ## API
@@ -42,15 +82,20 @@ result.direct_subsumers("http://ex.org/Margherita") # -> list[str] (Hasse-direct
42
82
  ### Classification
43
83
 
44
84
  ```python
45
- result = rustdl.classify(path, *, per_pair_timeout_ms=None, saturation_only=False)
46
- result = rustdl.classify_bytes(data, format="ofn", *, per_pair_timeout_ms=None, saturation_only=False)
85
+ result = rustdl.classify(path, *, per_pair_timeout_ms=1000, saturation_only=False)
86
+ result = rustdl.classify_bytes(data, format="ofn", *, per_pair_timeout_ms=1000, saturation_only=False)
47
87
  ```
48
88
 
49
- - `per_pair_timeout_ms` — bound each subsumption test; pairs that exceed it
50
- default to "not subsumed" (a sound under-approximation robust against
51
- pathological SROIQ inputs).
89
+ - `per_pair_timeout_ms` — bound each subsumption test (**default 1000**;
90
+ `0` = unbounded). A pair that exceeds the budget is recorded as "not
91
+ subsumed": **sound** (never a false subsumption) but the result may be
92
+ **incomplete**. When that happens, an `IncompleteClassificationWarning`
93
+ is emitted and `result.complete` is `False`. Pass `0` for the complete,
94
+ unbounded classification. The default bounds pathological SROIQ inputs
95
+ so classification can't hang silently.
52
96
  - `saturation_only` — skip the tableau entirely; EL-closure-only
53
- under-approximation. Dramatically faster on mostly-EL ontologies.
97
+ under-approximation. Dramatically faster on mostly-EL ontologies, and
98
+ always `complete` (no tableau ⇒ no timeout).
54
99
 
55
100
  `classify` / `classify_bytes` return a `Classification`:
56
101
 
@@ -59,6 +104,8 @@ result = rustdl.classify_bytes(data, format="ofn", *, per_pair_timeout_ms=None,
59
104
  | `.classes` | `list[str]` | all declared class IRIs |
60
105
  | `.unsatisfiable` | `list[str]` | classes proved `⊑ ⊥` |
61
106
  | `.inconsistent` | `bool` | whole ontology unsatisfiable |
107
+ | `.complete` | `bool` | `False` if any pair hit the timeout (result may miss edges) |
108
+ | `.timed_out_pairs` | `int` | how many pairs hit the timeout |
62
109
  | `.is_subclass(sub, sup)` | `bool` | is `sub ⊑ sup` entailed? |
63
110
  | `.subclasses_of(cls)` | `list[str]` | every `D` with `D ⊑ cls` |
64
111
  | `.superclasses_of(cls)` | `list[str]` | every `D` with `cls ⊑ D` |
@@ -23,18 +23,58 @@ Wheels are published for CPython 3.10+ on Linux (x86_64, aarch64), macOS
23
23
  ```python
24
24
  import rustdl
25
25
 
26
- # Classify an ontology. Format auto-detected from the extension:
26
+ # A small OWL 2 DL ontology ships inside the wheel (gzip-compressed) no
27
+ # download needed. `examples.pizza()` returns its file path (decompressed
28
+ # into a per-user cache dir on first use); `examples.PIZZA_NS` is its
29
+ # namespace, so class IRIs are PIZZA_NS + local name (e.g. + "Pizza").
30
+ from rustdl.examples import pizza, PIZZA_NS, SULO_NS
31
+
32
+ # Classify. Format is auto-detected from the extension:
27
33
  # .ofn (OWL Functional), .owx (OWL/XML), .rdf / .owl (RDF/XML).
28
- result = rustdl.classify("pizza.ofn")
34
+ result = rustdl.classify(pizza())
29
35
 
30
- print(f"{len(result.classes)} classes, {len(result.unsatisfiable)} unsatisfiable")
36
+ print(f"{len(result.classes)} classes, {len(result.unsatisfiable)} unsatisfiable, "
37
+ f"complete={result.complete}")
38
+ # -> 88 classes, 0 unsatisfiable, complete=True
31
39
 
32
40
  # Query the computed hierarchy
33
- result.is_subclass("http://ex.org/Margherita", "http://ex.org/Pizza") # -> bool
34
- result.subclasses_of("http://ex.org/Pizza") # -> list[str]
35
- result.superclasses_of("http://ex.org/Margherita") # -> list[str]
36
- result.equivalent_classes("http://ex.org/Pizza") # -> list[str]
37
- result.direct_subsumers("http://ex.org/Margherita") # -> list[str] (Hasse-direct parents)
41
+ print(result.is_subclass(PIZZA_NS + "BoxedPizza", PIZZA_NS + "Pizza"))
42
+ # -> True
43
+ print(len(result.subclasses_of(PIZZA_NS + "FoodMaterial")))
44
+ # -> 25
45
+
46
+ # The pizza ontology is aligned to the SULO upper ontology, so reasoning
47
+ # spans both — e.g. a pizza-making timestamp is inferred to be a SULO StartTime:
48
+ print(result.is_subclass(PIZZA_NS + "BakingStartTime", SULO_NS + "StartTime"))
49
+ # -> True
50
+
51
+ # Other hierarchy queries (all take full class IRIs):
52
+ result.superclasses_of(PIZZA_NS + "Cheese") # -> list[str]
53
+ result.equivalent_classes(PIZZA_NS + "Pizza") # -> list[str]
54
+ result.direct_subsumers(PIZZA_NS + "BoxedPizza") # -> list[str] (Hasse-direct parents)
55
+ ```
56
+
57
+ ### Bundled examples
58
+
59
+ Three real ontologies ship inside the wheel, gzip-compressed (~200 KB total).
60
+ They classify with **no network access** — each `examples.X()` decompresses
61
+ its ontology into a per-user cache dir (`$XDG_CACHE_HOME/rustdl/examples` or
62
+ `~/.cache/rustdl/examples`) on first use, then reuses it. Each `examples.X_NS`
63
+ is the namespace, so a class IRI is the namespace plus the local name.
64
+
65
+ | helper | ontology | classes | notes |
66
+ |---|---|---|---|
67
+ | `pizza()` / `PIZZA_NS` | ontostart pizza | 88 | SULO-aligned pizza-making ontology; classifies instantly + complete |
68
+ | `sulo()` / `SULO_NS` | SULO (Simple Upper-Level Ontology) | 17 | tiny; classifies in milliseconds |
69
+ | `sio()` / `SIO_NS` | SIO (Semanticscience Integrated Ontology) | ~1600 | realistic larger workload; takes tens of seconds. Class IRIs are numeric codes, e.g. `SIO_NS + "SIO_000006"` ("process") |
70
+
71
+ ```python
72
+ import rustdl
73
+ from rustdl import examples
74
+
75
+ r = rustdl.classify(examples.sulo())
76
+ print(r.is_subclass(examples.SULO_NS + "StartTime", examples.SULO_NS + "Object"))
77
+ # -> True
38
78
  ```
39
79
 
40
80
  ## API
@@ -42,15 +82,20 @@ result.direct_subsumers("http://ex.org/Margherita") # -> list[str] (Hasse-direct
42
82
  ### Classification
43
83
 
44
84
  ```python
45
- result = rustdl.classify(path, *, per_pair_timeout_ms=None, saturation_only=False)
46
- result = rustdl.classify_bytes(data, format="ofn", *, per_pair_timeout_ms=None, saturation_only=False)
85
+ result = rustdl.classify(path, *, per_pair_timeout_ms=1000, saturation_only=False)
86
+ result = rustdl.classify_bytes(data, format="ofn", *, per_pair_timeout_ms=1000, saturation_only=False)
47
87
  ```
48
88
 
49
- - `per_pair_timeout_ms` — bound each subsumption test; pairs that exceed it
50
- default to "not subsumed" (a sound under-approximation robust against
51
- pathological SROIQ inputs).
89
+ - `per_pair_timeout_ms` — bound each subsumption test (**default 1000**;
90
+ `0` = unbounded). A pair that exceeds the budget is recorded as "not
91
+ subsumed": **sound** (never a false subsumption) but the result may be
92
+ **incomplete**. When that happens, an `IncompleteClassificationWarning`
93
+ is emitted and `result.complete` is `False`. Pass `0` for the complete,
94
+ unbounded classification. The default bounds pathological SROIQ inputs
95
+ so classification can't hang silently.
52
96
  - `saturation_only` — skip the tableau entirely; EL-closure-only
53
- under-approximation. Dramatically faster on mostly-EL ontologies.
97
+ under-approximation. Dramatically faster on mostly-EL ontologies, and
98
+ always `complete` (no tableau ⇒ no timeout).
54
99
 
55
100
  `classify` / `classify_bytes` return a `Classification`:
56
101
 
@@ -59,6 +104,8 @@ result = rustdl.classify_bytes(data, format="ofn", *, per_pair_timeout_ms=None,
59
104
  | `.classes` | `list[str]` | all declared class IRIs |
60
105
  | `.unsatisfiable` | `list[str]` | classes proved `⊑ ⊥` |
61
106
  | `.inconsistent` | `bool` | whole ontology unsatisfiable |
107
+ | `.complete` | `bool` | `False` if any pair hit the timeout (result may miss edges) |
108
+ | `.timed_out_pairs` | `int` | how many pairs hit the timeout |
62
109
  | `.is_subclass(sub, sup)` | `bool` | is `sub ⊑ sup` entailed? |
63
110
  | `.subclasses_of(cls)` | `list[str]` | every `D` with `D ⊑ cls` |
64
111
  | `.superclasses_of(cls)` | `list[str]` | every `D` with `cls ⊑ D` |
@@ -38,6 +38,25 @@ impl PyClassification {
38
38
  self.inner.stats().inconsistent
39
39
  }
40
40
 
41
+ /// Number of class pairs that exceeded the per-pair timeout and
42
+ /// were recorded as "not subsumed". `> 0` means the classification
43
+ /// is a sound under-approximation — no false subsumptions, but real
44
+ /// ones may be missing. `0` when classification ran to completion
45
+ /// (or no timeout was set).
46
+ #[getter]
47
+ fn timed_out_pairs(&self) -> usize {
48
+ self.inner.stats().timed_out_pairs
49
+ }
50
+
51
+ /// True iff classification ran to completion — no pair hit the
52
+ /// timeout. When `False`, the hierarchy may be missing real
53
+ /// subsumptions (see `timed_out_pairs`); re-classify with
54
+ /// `per_pair_timeout_ms=0` for the complete (unbounded) result.
55
+ #[getter]
56
+ fn complete(&self) -> bool {
57
+ self.inner.stats().timed_out_pairs == 0
58
+ }
59
+
41
60
  /// True iff `sub ⊑ sup` is entailed.
42
61
  fn is_subclass(&self, sub: &str, sup: &str) -> bool {
43
62
  self.inner.is_subclass(sub, sup)
@@ -74,7 +93,7 @@ impl PyClassification {
74
93
  /// `rustdl.classify(path)` — classify the ontology at `path`.
75
94
  /// Format auto-detected from the file extension.
76
95
  #[pyfunction]
77
- #[pyo3(signature = (path, *, per_pair_timeout_ms=None, saturation_only=false))]
96
+ #[pyo3(signature = (path, *, per_pair_timeout_ms=1000, saturation_only=false))]
78
97
  pub(crate) fn classify(
79
98
  path: &str,
80
99
  per_pair_timeout_ms: Option<u64>,
@@ -86,7 +105,7 @@ pub(crate) fn classify(
86
105
 
87
106
  /// `rustdl.classify_bytes(data, format="ofn")` — same but from bytes.
88
107
  #[pyfunction]
89
- #[pyo3(signature = (data, *, format, per_pair_timeout_ms=None, saturation_only=false))]
108
+ #[pyo3(signature = (data, *, format, per_pair_timeout_ms=1000, saturation_only=false))]
90
109
  pub(crate) fn classify_bytes(
91
110
  data: &[u8],
92
111
  format: &str,
@@ -103,9 +122,12 @@ fn do_classify(
103
122
  saturation_only: bool,
104
123
  ) -> PyResult<PyClassification> {
105
124
  use std::time::Duration;
125
+ // `None` or `0` → unbounded (complete); any positive value bounds
126
+ // each pair (sound under-approximation; check `.complete` after).
127
+ let bounded = per_pair_timeout_ms.filter(|&ms| ms > 0);
106
128
  let inner = if saturation_only {
107
129
  owl_dl_reasoner::classify_saturation_only(ontology).map_err(reason_error_to_py)?
108
- } else if let Some(ms) = per_pair_timeout_ms {
130
+ } else if let Some(ms) = bounded {
109
131
  owl_dl_reasoner::classify_top_down_with_timeout(ontology, Duration::from_millis(ms))
110
132
  .map_err(reason_error_to_py)?
111
133
  } else {
@@ -46,3 +46,33 @@ def test_superclasses_of(fixtures_dir):
46
46
  result = rustdl.classify(str(fixture))
47
47
  sups = result.superclasses_of("http://t/Adult")
48
48
  assert "http://t/Person" in sups
49
+
50
+
51
+ def test_completeness_signal_and_warning(fixtures_dir):
52
+ import warnings
53
+ fixture = fixtures_dir / "datatype" / "datatype_definition.ofn"
54
+
55
+ # Default budget on a tiny EL-ish ontology: completes, no warning.
56
+ with warnings.catch_warnings(record=True) as rec:
57
+ warnings.simplefilter("always")
58
+ r = rustdl.classify(str(fixture))
59
+ assert r.complete is True
60
+ assert r.timed_out_pairs == 0
61
+ assert not any(
62
+ issubclass(w.category, rustdl.IncompleteClassificationWarning) for w in rec
63
+ )
64
+
65
+
66
+ def test_saturation_only_is_complete(fixtures_dir):
67
+ fixture = fixtures_dir / "datatype" / "datatype_definition.ofn"
68
+ r = rustdl.classify(str(fixture), saturation_only=True)
69
+ # saturation-only never invokes the tableau, so no pair can time out
70
+ assert r.complete is True
71
+ assert r.timed_out_pairs == 0
72
+
73
+
74
+ def test_unbounded_timeout_accepted(fixtures_dir):
75
+ fixture = fixtures_dir / "datatype" / "datatype_definition.ofn"
76
+ # per_pair_timeout_ms=0 means unbounded — must classify, complete.
77
+ r = rustdl.classify(str(fixture), per_pair_timeout_ms=0)
78
+ assert r.complete is True
@@ -0,0 +1,34 @@
1
+ """Bundled example ontologies — must work fully offline (shipped in the wheel)."""
2
+ import os
3
+ import rustdl
4
+ from rustdl import examples
5
+
6
+
7
+ def test_all_three_examples_materialize():
8
+ for fn in (examples.pizza, examples.sulo, examples.sio):
9
+ path = fn()
10
+ assert os.path.exists(path)
11
+ assert os.path.getsize(path) > 0
12
+
13
+
14
+ def test_pizza_classifies_complete():
15
+ # ontostart pizza: 88 classes, no unsat, classifies instantly + complete.
16
+ r = rustdl.classify(examples.pizza())
17
+ assert len(r.classes) == 88
18
+ assert len(r.unsatisfiable) == 0
19
+ assert r.complete is True
20
+ ns = examples.PIZZA_NS
21
+ assert r.is_subclass(ns + "BoxedPizza", ns + "Pizza")
22
+ # cross-ontology: aligned to SULO upper ontology
23
+ assert r.is_subclass(ns + "BakingStartTime", examples.SULO_NS + "StartTime")
24
+
25
+
26
+ def test_sulo_classifies():
27
+ r = rustdl.classify(examples.sulo())
28
+ assert len(r.classes) == 17
29
+ assert r.complete is True
30
+
31
+
32
+ def test_namespace_constants_are_strings():
33
+ for ns in (examples.PIZZA_NS, examples.SULO_NS, examples.SIO_NS):
34
+ assert isinstance(ns, str) and ns
@@ -35,5 +35,6 @@ Changelog = "https://github.com/MaastrichtU-IDS/rustdl/blob/main/CHANGELOG.md"
35
35
  module-name = "rustdl._native"
36
36
  features = ["pyo3/extension-module"]
37
37
  strip = true
38
+ include = ["python/rustdl/data/*.owl.gz"]
38
39
  manifest-path = "crates/owl-dl-py/Cargo.toml"
39
40
  python-source = "python"