openmaterica 0.1.0.dev1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (704) hide show
  1. materica/README.md +33 -0
  2. materica/__init__.py +8 -0
  3. materica/core/README.md +72 -0
  4. materica/core/__init__.py +2 -0
  5. materica/core/canonical.py +92 -0
  6. materica/core/envelope.py +93 -0
  7. materica/core/hashing.py +38 -0
  8. materica/core/identifiers.py +67 -0
  9. materica/core/jsonio.py +102 -0
  10. materica/core/read.py +301 -0
  11. materica/core/reasons.py +46 -0
  12. materica/core/record.py +107 -0
  13. materica/core/resolve.py +82 -0
  14. materica/core/status.py +17 -0
  15. materica/core/vocabulary.py +139 -0
  16. materica/data/conformance/README.md +103 -0
  17. materica/data/conformance/hash/CASES.md +105 -0
  18. materica/data/conformance/hash/README.md +45 -0
  19. materica/data/conformance/hash/cases/HS-001.escaped_names.json +24 -0
  20. materica/data/conformance/hash/cases/HS-001.names_exact.json +24 -0
  21. materica/data/conformance/hash/cases/HS-001.nested_names_kept.json +24 -0
  22. materica/data/conformance/hash/cases/HS-001.outside_kept.json +24 -0
  23. materica/data/conformance/hash/cases/HS-001.provenance_anywhere.json +24 -0
  24. materica/data/conformance/hash/cases/HS-001.provenance_arrays.json +24 -0
  25. materica/data/conformance/hash/cases/HS-001.provenance_depth.json +24 -0
  26. materica/data/conformance/hash/cases/HS-001.provenance_inside_non_object.json +24 -0
  27. materica/data/conformance/hash/cases/HS-001.provenance_members.json +24 -0
  28. materica/data/conformance/hash/cases/HS-001.provenance_nested_in_provenance.json +24 -0
  29. materica/data/conformance/hash/cases/HS-001.provenance_not_object.json +24 -0
  30. materica/data/conformance/hash/cases/HS-001.top_level_absent.json +24 -0
  31. materica/data/conformance/hash/cases/HS-001.top_level_any_value.json +24 -0
  32. materica/data/conformance/hash/cases/HS-001.top_level_array.json +24 -0
  33. materica/data/conformance/hash/cases/HS-001.top_level_removed.json +24 -0
  34. materica/data/conformance/hash/cases/HS-001.top_level_scalar.json +24 -0
  35. materica/data/conformance/hash/cases/HS-002.material.json +24 -0
  36. materica/data/conformance/hash/cases/HS-002.material_table.json +24 -0
  37. materica/data/conformance/hash/cases/HS-002.overlay.json +24 -0
  38. materica/data/conformance/hash/cases/HS-002.string_escapes.json +24 -0
  39. materica/data/conformance/hash/cases/HS-003.depth_64.json +24 -0
  40. materica/data/conformance/hash/cases/HS-003.depth_64_scalar.json +24 -0
  41. materica/data/conformance/hash/cases/HS-003.integer_1e20.json +24 -0
  42. materica/data/conformance/hash/cases/HS-003.integer_1e21.json +24 -0
  43. materica/data/conformance/hash/cases/HS-003.integer_9007199254740993.json +24 -0
  44. materica/data/conformance/hash/cases/HS-003.largest_double.json +24 -0
  45. materica/data/conformance/hash/cases/HS-003.malformed_bom.json +27 -0
  46. materica/data/conformance/hash/cases/HS-003.malformed_depth_65.json +27 -0
  47. materica/data/conformance/hash/cases/HS-003.malformed_duplicate_name.json +27 -0
  48. materica/data/conformance/hash/cases/HS-003.malformed_duplicate_removed_member.json +27 -0
  49. materica/data/conformance/hash/cases/HS-003.malformed_nan.json +27 -0
  50. materica/data/conformance/hash/cases/HS-003.malformed_overflow.json +27 -0
  51. materica/data/conformance/hash/cases/HS-003.malformed_overlong_utf8.json +27 -0
  52. materica/data/conformance/hash/cases/HS-003.malformed_trailing_comma.json +27 -0
  53. materica/data/conformance/hash/cases/HS-003.malformed_unpaired_surrogate.json +27 -0
  54. materica/data/conformance/hash/cases/HS-003.negative_zero.json +24 -0
  55. materica/data/conformance/hash/cases/HS-003.nfc_decomposed.json +24 -0
  56. materica/data/conformance/hash/cases/HS-003.nfc_side_by_side.json +24 -0
  57. materica/data/conformance/hash/cases/HS-003.null_in_unknown_member.json +24 -0
  58. materica/data/conformance/hash/cases/HS-003.number_0_0000001.json +24 -0
  59. materica/data/conformance/hash/cases/HS-003.number_1.json +24 -0
  60. materica/data/conformance/hash/cases/HS-003.number_1_0.json +24 -0
  61. materica/data/conformance/hash/cases/HS-003.number_1e2.json +24 -0
  62. materica/data/conformance/hash/cases/HS-003.provenance_not_object.json +24 -0
  63. materica/data/conformance/hash/cases/HS-003.review_copy_at_depth.json +24 -0
  64. materica/data/conformance/hash/cases/HS-003.review_copy_view.json +24 -0
  65. materica/data/conformance/hash/cases/HS-003.true_beside_one.json +24 -0
  66. materica/data/conformance/hash/cases/HS-003.underflow.json +24 -0
  67. materica/data/conformance/hash/cases/HS-003.unknown_members_hashed.json +24 -0
  68. materica/data/conformance/hash/cases/HS-003.utf16_order_escaped.json +24 -0
  69. materica/data/conformance/hash/cases/HS-003.utf16_order_raw.json +24 -0
  70. materica/data/conformance/hash/cases/HS-010.control_hash_verifies.json +58 -0
  71. materica/data/conformance/hash/cases/HS-010.envelope_refused.json +58 -0
  72. materica/data/conformance/hash/cases/HS-010.licence_edited.json +61 -0
  73. materica/data/conformance/hash/cases/HS-010.member_added.json +61 -0
  74. materica/data/conformance/hash/cases/HS-010.name_edited.json +61 -0
  75. materica/data/conformance/hash/cases/HS-010.other_version.json +58 -0
  76. materica/data/conformance/hash/cases/HS-010.type_edited.json +61 -0
  77. materica/data/conformance/hash/cases/HS-010.value_edited.json +61 -0
  78. materica/data/conformance/hash/cases/HS-011.edited_after_pinning.json +61 -0
  79. materica/data/conformance/hash/cases/HS-011.stated_differs.json +58 -0
  80. materica/data/conformance/hash/cases/HS-011.stated_differs_recomputed_equals.json +58 -0
  81. materica/data/conformance/hash/inputs/depth_64.json +1 -0
  82. materica/data/conformance/hash/inputs/depth_64_scalar.json +1 -0
  83. materica/data/conformance/hash/inputs/interface_fixture.json +14 -0
  84. materica/data/conformance/hash/inputs/malformed_bom.json +1 -0
  85. materica/data/conformance/hash/inputs/malformed_depth_65.json +1 -0
  86. materica/data/conformance/hash/inputs/malformed_duplicate_name.json +1 -0
  87. materica/data/conformance/hash/inputs/malformed_duplicate_removed_member.json +1 -0
  88. materica/data/conformance/hash/inputs/malformed_nan.json +1 -0
  89. materica/data/conformance/hash/inputs/malformed_overflow.json +1 -0
  90. materica/data/conformance/hash/inputs/malformed_overlong_utf8.json +1 -0
  91. materica/data/conformance/hash/inputs/malformed_trailing_comma.json +1 -0
  92. materica/data/conformance/hash/inputs/malformed_unpaired_surrogate.json +1 -0
  93. materica/data/conformance/hash/inputs/nfc_decomposed.json +5 -0
  94. materica/data/conformance/hash/inputs/nfc_side_by_side.json +4 -0
  95. materica/data/conformance/hash/inputs/number_0_0000001.json +1 -0
  96. materica/data/conformance/hash/inputs/number_1.json +1 -0
  97. materica/data/conformance/hash/inputs/number_1_0.json +1 -0
  98. materica/data/conformance/hash/inputs/number_1e2.json +1 -0
  99. materica/data/conformance/hash/inputs/number_9007199254740993.json +1 -0
  100. materica/data/conformance/hash/inputs/number_integer_1e20.json +1 -0
  101. materica/data/conformance/hash/inputs/number_integer_1e21.json +1 -0
  102. materica/data/conformance/hash/inputs/number_largest_double.json +1 -0
  103. materica/data/conformance/hash/inputs/number_negative_zero.json +1 -0
  104. materica/data/conformance/hash/inputs/number_underflow.json +1 -0
  105. materica/data/conformance/hash/inputs/strings_canonical.json +4 -0
  106. materica/data/conformance/hash/inputs/true_beside_one.json +1 -0
  107. materica/data/conformance/hash/inputs/utf16_order_escaped.json +7 -0
  108. materica/data/conformance/hash/inputs/utf16_order_raw.json +7 -0
  109. materica/data/conformance/hash/inputs/view_escaped_names.json +7 -0
  110. materica/data/conformance/hash/inputs/view_names_exact.json +8 -0
  111. materica/data/conformance/hash/inputs/view_nested_names_kept.json +5 -0
  112. materica/data/conformance/hash/inputs/view_outside_kept.json +7 -0
  113. materica/data/conformance/hash/inputs/view_provenance_anywhere.json +5 -0
  114. materica/data/conformance/hash/inputs/view_provenance_arrays.json +11 -0
  115. materica/data/conformance/hash/inputs/view_provenance_depth.json +12 -0
  116. materica/data/conformance/hash/inputs/view_provenance_inside_non_object.json +1 -0
  117. materica/data/conformance/hash/inputs/view_provenance_members.json +7 -0
  118. materica/data/conformance/hash/inputs/view_provenance_nested_in_provenance.json +1 -0
  119. materica/data/conformance/hash/inputs/view_provenance_not_object.json +7 -0
  120. materica/data/conformance/hash/inputs/view_top_level_absent.json +1 -0
  121. materica/data/conformance/hash/inputs/view_top_level_any_value.json +1 -0
  122. materica/data/conformance/hash/inputs/view_top_level_array.json +1 -0
  123. materica/data/conformance/hash/inputs/view_top_level_removed.json +5 -0
  124. materica/data/conformance/hash/inputs/view_top_level_scalar.json +1 -0
  125. materica/data/conformance/hash/inputs/water_density_fixture.json +117 -0
  126. materica/data/conformance/hash/inputs/water_fixture.json +99 -0
  127. materica/data/conformance/hash/inputs/water_fixture_envelope_refused.json +96 -0
  128. materica/data/conformance/hash/inputs/water_fixture_licence_edited.json +99 -0
  129. materica/data/conformance/hash/inputs/water_fixture_member_added.json +100 -0
  130. materica/data/conformance/hash/inputs/water_fixture_name_edited.json +99 -0
  131. materica/data/conformance/hash/inputs/water_fixture_null_unknown.json +103 -0
  132. materica/data/conformance/hash/inputs/water_fixture_other_version.json +99 -0
  133. materica/data/conformance/hash/inputs/water_fixture_provenance_not_object.json +117 -0
  134. materica/data/conformance/hash/inputs/water_fixture_review_copy.json +139 -0
  135. materica/data/conformance/hash/inputs/water_fixture_review_copy_view.json +122 -0
  136. materica/data/conformance/hash/inputs/water_fixture_type_edited.json +99 -0
  137. materica/data/conformance/hash/inputs/water_fixture_unknown_members.json +128 -0
  138. materica/data/conformance/hash/inputs/water_fixture_value_edited.json +99 -0
  139. materica/data/conformance/hash/inputs/water_overlay_fixture.json +97 -0
  140. materica/data/conformance/plain_read/CASES.md +504 -0
  141. materica/data/conformance/plain_read/README.md +61 -0
  142. materica/data/conformance/plain_read/cases/PR-001.cbor.json +53 -0
  143. materica/data/conformance/plain_read/cases/PR-001.listing_yaml_not_listed.json +32 -0
  144. materica/data/conformance/plain_read/cases/PR-001.toml.json +53 -0
  145. materica/data/conformance/plain_read/cases/PR-001.yaml.json +53 -0
  146. materica/data/conformance/plain_read/cases/PR-002.body_not_object.json +53 -0
  147. materica/data/conformance/plain_read/cases/PR-002.bom.json +53 -0
  148. materica/data/conformance/plain_read/cases/PR-002.card_not_string.json +53 -0
  149. materica/data/conformance/plain_read/cases/PR-002.comment.json +53 -0
  150. materica/data/conformance/plain_read/cases/PR-002.content_hash_63_digits.json +53 -0
  151. materica/data/conformance/plain_read/cases/PR-002.content_hash_no_prefix.json +53 -0
  152. materica/data/conformance/plain_read/cases/PR-002.content_hash_not_string.json +53 -0
  153. materica/data/conformance/plain_read/cases/PR-002.content_hash_trailing_newline.json +53 -0
  154. materica/data/conformance/plain_read/cases/PR-002.content_hash_uppercase.json +53 -0
  155. materica/data/conformance/plain_read/cases/PR-002.content_hash_uppercase_pinned_as_stated.json +53 -0
  156. materica/data/conformance/plain_read/cases/PR-002.duplicate_member.json +53 -0
  157. materica/data/conformance/plain_read/cases/PR-002.duplicate_member_escaped.json +53 -0
  158. materica/data/conformance/plain_read/cases/PR-002.encoded_surrogate.json +53 -0
  159. materica/data/conformance/plain_read/cases/PR-002.extensions_not_object.json +53 -0
  160. materica/data/conformance/plain_read/cases/PR-002.fields_array.json +53 -0
  161. materica/data/conformance/plain_read/cases/PR-002.id_namespace_uppercase.json +53 -0
  162. materica/data/conformance/plain_read/cases/PR-002.id_not_string.json +53 -0
  163. materica/data/conformance/plain_read/cases/PR-002.id_without_namespace.json +53 -0
  164. materica/data/conformance/plain_read/cases/PR-002.infinity.json +53 -0
  165. materica/data/conformance/plain_read/cases/PR-002.invalid_json.json +53 -0
  166. materica/data/conformance/plain_read/cases/PR-002.known_section_fields_missing.json +53 -0
  167. materica/data/conformance/plain_read/cases/PR-002.known_section_not_object.json +53 -0
  168. materica/data/conformance/plain_read/cases/PR-002.licence_evidence_missing.json +53 -0
  169. materica/data/conformance/plain_read/cases/PR-002.licence_evidence_not_string.json +53 -0
  170. materica/data/conformance/plain_read/cases/PR-002.licence_not_object.json +53 -0
  171. materica/data/conformance/plain_read/cases/PR-002.licence_values_missing.json +53 -0
  172. materica/data/conformance/plain_read/cases/PR-002.local_id_empty.json +53 -0
  173. materica/data/conformance/plain_read/cases/PR-002.local_id_trailing_newline.json +53 -0
  174. materica/data/conformance/plain_read/cases/PR-002.local_id_with_space.json +53 -0
  175. materica/data/conformance/plain_read/cases/PR-002.missing_body.json +53 -0
  176. materica/data/conformance/plain_read/cases/PR-002.missing_content_hash.json +53 -0
  177. materica/data/conformance/plain_read/cases/PR-002.missing_id.json +53 -0
  178. materica/data/conformance/plain_read/cases/PR-002.missing_licence.json +53 -0
  179. materica/data/conformance/plain_read/cases/PR-002.missing_name.json +53 -0
  180. materica/data/conformance/plain_read/cases/PR-002.missing_record_type.json +53 -0
  181. materica/data/conformance/plain_read/cases/PR-002.missing_version.json +53 -0
  182. materica/data/conformance/plain_read/cases/PR-002.name_not_string.json +53 -0
  183. materica/data/conformance/plain_read/cases/PR-002.nan.json +53 -0
  184. materica/data/conformance/plain_read/cases/PR-002.negative_infinity.json +53 -0
  185. materica/data/conformance/plain_read/cases/PR-002.nesting_100000.json +53 -0
  186. materica/data/conformance/plain_read/cases/PR-002.nesting_65.json +53 -0
  187. materica/data/conformance/plain_read/cases/PR-002.number_overflow.json +53 -0
  188. materica/data/conformance/plain_read/cases/PR-002.number_overflow_exponent.json +53 -0
  189. materica/data/conformance/plain_read/cases/PR-002.overlay_base_content_hash_missing.json +53 -0
  190. materica/data/conformance/plain_read/cases/PR-002.overlay_base_content_hash_not_string.json +53 -0
  191. materica/data/conformance/plain_read/cases/PR-002.overlay_base_id_missing.json +53 -0
  192. materica/data/conformance/plain_read/cases/PR-002.overlay_base_id_not_string.json +53 -0
  193. materica/data/conformance/plain_read/cases/PR-002.overlay_base_missing.json +53 -0
  194. materica/data/conformance/plain_read/cases/PR-002.overlay_base_not_object.json +53 -0
  195. materica/data/conformance/plain_read/cases/PR-002.overlay_base_version_missing.json +53 -0
  196. materica/data/conformance/plain_read/cases/PR-002.overlay_base_version_not_string.json +53 -0
  197. materica/data/conformance/plain_read/cases/PR-002.overlay_purpose_missing.json +53 -0
  198. materica/data/conformance/plain_read/cases/PR-002.overlay_purpose_not_string.json +53 -0
  199. materica/data/conformance/plain_read/cases/PR-002.overlay_replaces_missing.json +53 -0
  200. materica/data/conformance/plain_read/cases/PR-002.overlay_replaces_not_object.json +53 -0
  201. materica/data/conformance/plain_read/cases/PR-002.overlay_scope_consumer_missing.json +53 -0
  202. materica/data/conformance/plain_read/cases/PR-002.overlay_scope_consumer_not_string.json +53 -0
  203. materica/data/conformance/plain_read/cases/PR-002.overlay_scope_missing.json +53 -0
  204. materica/data/conformance/plain_read/cases/PR-002.overlay_scope_model_configuration_hash_not_string.json +53 -0
  205. materica/data/conformance/plain_read/cases/PR-002.overlay_scope_model_empty.json +53 -0
  206. materica/data/conformance/plain_read/cases/PR-002.overlay_scope_model_name_missing.json +53 -0
  207. materica/data/conformance/plain_read/cases/PR-002.overlay_scope_model_name_not_string.json +53 -0
  208. materica/data/conformance/plain_read/cases/PR-002.overlay_scope_model_not_object.json +53 -0
  209. materica/data/conformance/plain_read/cases/PR-002.overlay_scope_model_version_missing.json +53 -0
  210. materica/data/conformance/plain_read/cases/PR-002.overlay_scope_model_version_not_string.json +53 -0
  211. materica/data/conformance/plain_read/cases/PR-002.overlay_scope_not_object.json +53 -0
  212. materica/data/conformance/plain_read/cases/PR-002.overlay_scope_run_not_string.json +53 -0
  213. materica/data/conformance/plain_read/cases/PR-002.overlong.json +53 -0
  214. materica/data/conformance/plain_read/cases/PR-002.read_escaped_nul.json +31 -0
  215. materica/data/conformance/plain_read/cases/PR-002.read_nesting_64.json +31 -0
  216. materica/data/conformance/plain_read/cases/PR-002.read_noncharacter.json +31 -0
  217. materica/data/conformance/plain_read/cases/PR-002.read_noncharacter_escaped.json +31 -0
  218. materica/data/conformance/plain_read/cases/PR-002.record_type_not_string.json +53 -0
  219. materica/data/conformance/plain_read/cases/PR-002.sections_missing.json +53 -0
  220. materica/data/conformance/plain_read/cases/PR-002.sections_not_object.json +53 -0
  221. materica/data/conformance/plain_read/cases/PR-002.trailing_comma.json +53 -0
  222. materica/data/conformance/plain_read/cases/PR-002.trailing_content.json +53 -0
  223. materica/data/conformance/plain_read/cases/PR-002.truncated_utf8.json +53 -0
  224. materica/data/conformance/plain_read/cases/PR-002.unescaped_control_character.json +53 -0
  225. materica/data/conformance/plain_read/cases/PR-002.unpaired_low_surrogate_escape.json +53 -0
  226. materica/data/conformance/plain_read/cases/PR-002.unpaired_surrogate_escape.json +53 -0
  227. materica/data/conformance/plain_read/cases/PR-002.utf16be.json +53 -0
  228. materica/data/conformance/plain_read/cases/PR-002.utf16le.json +53 -0
  229. materica/data/conformance/plain_read/cases/PR-002.utf16le_bom.json +53 -0
  230. materica/data/conformance/plain_read/cases/PR-002.utf32be.json +53 -0
  231. materica/data/conformance/plain_read/cases/PR-002.utf32le.json +53 -0
  232. materica/data/conformance/plain_read/cases/PR-002.version_leading_zero.json +53 -0
  233. materica/data/conformance/plain_read/cases/PR-002.version_not_string.json +53 -0
  234. materica/data/conformance/plain_read/cases/PR-002.version_off_pattern.json +53 -0
  235. materica/data/conformance/plain_read/cases/PR-004.interface_missing_licence.json +53 -0
  236. materica/data/conformance/plain_read/cases/PR-004.interface_missing_name.json +53 -0
  237. materica/data/conformance/plain_read/cases/PR-004.material_and_overlay_listed.json +36 -0
  238. materica/data/conformance/plain_read/cases/PR-004.material_listed.json +31 -0
  239. materica/data/conformance/plain_read/cases/PR-004.namespaced_type_missing_name.json +53 -0
  240. materica/data/conformance/plain_read/cases/PR-004.overlay_licence_evidence_not_string.json +53 -0
  241. materica/data/conformance/plain_read/cases/PR-004.overlay_listed.json +31 -0
  242. materica/data/conformance/plain_read/cases/PR-004.overlay_missing_body.json +53 -0
  243. materica/data/conformance/plain_read/cases/PR-004.overlay_missing_licence.json +53 -0
  244. materica/data/conformance/plain_read/cases/PR-004.overlay_missing_name.json +53 -0
  245. materica/data/conformance/plain_read/cases/PR-004.overlay_missing_name_not_listed.json +32 -0
  246. materica/data/conformance/plain_read/cases/PR-004.overlay_missing_record_type.json +53 -0
  247. materica/data/conformance/plain_read/cases/PR-004.overlay_missing_schema_version.json +53 -0
  248. materica/data/conformance/plain_read/cases/PR-004.overlay_scope_model_complete_listed.json +31 -0
  249. materica/data/conformance/plain_read/cases/PR-004.unknown_type_missing_body.json +53 -0
  250. materica/data/conformance/plain_read/cases/PR-006.all_sources.json +46 -0
  251. materica/data/conformance/plain_read/cases/PR-006.array_source_not_listed.json +32 -0
  252. materica/data/conformance/plain_read/cases/PR-006.document_type_without_record_type_skipped.json +32 -0
  253. materica/data/conformance/plain_read/cases/PR-006.engine_crosswalk_skipped.json +32 -0
  254. materica/data/conformance/plain_read/cases/PR-006.id_only_object_not_listed.json +32 -0
  255. materica/data/conformance/plain_read/cases/PR-006.interface_skipped.json +32 -0
  256. materica/data/conformance/plain_read/cases/PR-006.namespaced_type_skipped.json +32 -0
  257. materica/data/conformance/plain_read/cases/PR-006.number_source_not_listed.json +32 -0
  258. materica/data/conformance/plain_read/cases/PR-006.record_with_document_type_member_listed.json +31 -0
  259. materica/data/conformance/plain_read/cases/PR-006.scene_manifest_skipped.json +32 -0
  260. materica/data/conformance/plain_read/cases/PR-006.unknown_type_skipped.json +32 -0
  261. materica/data/conformance/plain_read/cases/PR-007.interface.json +53 -0
  262. materica/data/conformance/plain_read/cases/PR-007.interface_other_version.json +53 -0
  263. materica/data/conformance/plain_read/cases/PR-007.interface_pin_mismatch.json +53 -0
  264. materica/data/conformance/plain_read/cases/PR-007.namespaced_type.json +53 -0
  265. materica/data/conformance/plain_read/cases/PR-007.record_type_capitalised.json +53 -0
  266. materica/data/conformance/plain_read/cases/PR-007.unknown_type.json +53 -0
  267. materica/data/conformance/plain_read/cases/PR-026.minor_0_0_1.json +53 -0
  268. materica/data/conformance/plain_read/cases/PR-026.minor_0_10_0.json +53 -0
  269. materica/data/conformance/plain_read/cases/PR-026.minor_0_2_0.json +53 -0
  270. materica/data/conformance/plain_read/cases/PR-026.minor_0_2_0_not_listed.json +26 -0
  271. materica/data/conformance/plain_read/cases/PR-027.major_1_0_0.json +53 -0
  272. materica/data/conformance/plain_read/cases/PR-027.major_1_1_0.json +53 -0
  273. materica/data/conformance/plain_read/cases/PR-027.major_2_0_0.json +53 -0
  274. materica/data/conformance/plain_read/cases/PR-048.absent.json +53 -0
  275. materica/data/conformance/plain_read/cases/PR-048.arabic_indic_digits.json +53 -0
  276. materica/data/conformance/plain_read/cases/PR-048.leading_zero_major.json +53 -0
  277. materica/data/conformance/plain_read/cases/PR-048.leading_zero_minor.json +53 -0
  278. materica/data/conformance/plain_read/cases/PR-048.major_100_digits.json +53 -0
  279. materica/data/conformance/plain_read/cases/PR-048.minor_100_digits.json +53 -0
  280. materica/data/conformance/plain_read/cases/PR-048.not_string_array.json +53 -0
  281. materica/data/conformance/plain_read/cases/PR-048.not_string_null.json +53 -0
  282. materica/data/conformance/plain_read/cases/PR-048.not_string_number.json +53 -0
  283. materica/data/conformance/plain_read/cases/PR-048.other_version_before_envelope.json +53 -0
  284. materica/data/conformance/plain_read/cases/PR-048.patch_0_1_7_listed.json +31 -0
  285. materica/data/conformance/plain_read/cases/PR-048.patch_100_digits_listed.json +31 -0
  286. materica/data/conformance/plain_read/cases/PR-048.pre_release.json +53 -0
  287. materica/data/conformance/plain_read/cases/PR-048.trailing_newline.json +53 -0
  288. materica/data/conformance/plain_read/cases/PR-048.trailing_space.json +53 -0
  289. materica/data/conformance/plain_read/cases/PR-048.two_components.json +53 -0
  290. materica/data/conformance/plain_read/cases/PR-049.body_null.json +53 -0
  291. materica/data/conformance/plain_read/cases/PR-049.card_null.json +53 -0
  292. materica/data/conformance/plain_read/cases/PR-049.extensions_null.json +53 -0
  293. materica/data/conformance/plain_read/cases/PR-049.fields_null.json +53 -0
  294. materica/data/conformance/plain_read/cases/PR-049.known_section_null.json +53 -0
  295. materica/data/conformance/plain_read/cases/PR-049.licence_evidence_null.json +53 -0
  296. materica/data/conformance/plain_read/cases/PR-049.licence_null.json +53 -0
  297. materica/data/conformance/plain_read/cases/PR-049.licence_values_null.json +53 -0
  298. materica/data/conformance/plain_read/cases/PR-049.name_null.json +53 -0
  299. materica/data/conformance/plain_read/cases/PR-049.overlay_base_content_hash_null.json +53 -0
  300. materica/data/conformance/plain_read/cases/PR-049.overlay_base_id_null.json +53 -0
  301. materica/data/conformance/plain_read/cases/PR-049.overlay_base_null.json +53 -0
  302. materica/data/conformance/plain_read/cases/PR-049.overlay_base_version_null.json +53 -0
  303. materica/data/conformance/plain_read/cases/PR-049.overlay_purpose_null.json +53 -0
  304. materica/data/conformance/plain_read/cases/PR-049.overlay_replaces_null.json +53 -0
  305. materica/data/conformance/plain_read/cases/PR-049.overlay_scope_consumer_null.json +53 -0
  306. materica/data/conformance/plain_read/cases/PR-049.overlay_scope_model_configuration_hash_null.json +53 -0
  307. materica/data/conformance/plain_read/cases/PR-049.overlay_scope_model_null.json +53 -0
  308. materica/data/conformance/plain_read/cases/PR-049.overlay_scope_null.json +53 -0
  309. materica/data/conformance/plain_read/cases/PR-049.overlay_scope_run_null.json +53 -0
  310. materica/data/conformance/plain_read/cases/PR-049.record_type_null.json +53 -0
  311. materica/data/conformance/plain_read/cases/PR-049.sections_null.json +53 -0
  312. materica/data/conformance/plain_read/cases/PR-049.unknown_top_level_member_null_listed.json +31 -0
  313. materica/data/conformance/plain_read/cases/PR-300.no_records.json +51 -0
  314. materica/data/conformance/plain_read/cases/PR-300.record_binary_bytes.json +53 -0
  315. materica/data/conformance/plain_read/cases/PR-300.record_empty_file.json +53 -0
  316. materica/data/conformance/plain_read/cases/PR-300.request_empty_file.json +27 -0
  317. materica/data/conformance/plain_read/cases/PR-300.request_nesting_100000.json +27 -0
  318. materica/data/conformance/plain_read/cases/PR-301.hash_and_pin_mismatch_hs.json +61 -0
  319. materica/data/conformance/plain_read/cases/PR-301.hash_and_pin_mismatch_no_hs.json +60 -0
  320. materica/data/conformance/plain_read/cases/PR-301.incomplete_and_unit_mismatch.json +57 -0
  321. materica/data/conformance/plain_read/cases/PR-301.step0_ends_read.json +53 -0
  322. materica/data/conformance/plain_read/cases/PR-301.step1_ends_read.json +53 -0
  323. materica/data/conformance/plain_read/cases/PR-301.step2_ends_read.json +53 -0
  324. materica/data/conformance/plain_read/cases/PR-301.three_codes_step0.json +68 -0
  325. materica/data/conformance/plain_read/cases/PR-301.three_codes_step0_with_fd.json +65 -0
  326. materica/data/conformance/plain_read/cases/PR-301.want_suite_and_incomplete.json +59 -0
  327. materica/data/conformance/plain_read/cases/PR-301.want_suite_and_incomplete_with_fd.json +56 -0
  328. materica/data/conformance/plain_read/cases/PR-308.no_want.json +52 -0
  329. materica/data/conformance/plain_read/cases/PR-308.tolerance_with_other_operating_condition.json +54 -0
  330. materica/data/conformance/plain_read/cases/PR-308.tolerance_without_operating_conditions.json +48 -0
  331. materica/data/conformance/plain_read/cases/PR-310.absent.json +53 -0
  332. materica/data/conformance/plain_read/cases/PR-310.hash_mismatch.json +59 -0
  333. materica/data/conformance/plain_read/cases/PR-310.malformed.json +53 -0
  334. materica/data/conformance/plain_read/cases/PR-310.other_version.json +53 -0
  335. materica/data/conformance/plain_read/cases/PR-310.pin_mismatch.json +53 -0
  336. materica/data/conformance/plain_read/cases/PR-310.request_incomplete.json +53 -0
  337. materica/data/conformance/plain_read/cases/PR-310.request_unit_mismatch.json +54 -0
  338. materica/data/conformance/plain_read/cases/PR-310.unknown_type.json +53 -0
  339. materica/data/conformance/plain_read/cases/PR-310.want_mismatch.json +56 -0
  340. materica/data/conformance/plain_read/cases/PR-320.accept_entry_with_unit_accepted.json +59 -0
  341. materica/data/conformance/plain_read/cases/PR-320.operating_range_lo_above_hi_wrong_unit.json +65 -0
  342. materica/data/conformance/plain_read/cases/PR-320.operating_range_per_minute.json +61 -0
  343. materica/data/conformance/plain_read/cases/PR-320.operating_range_three_numbers_wrong_unit.json +66 -0
  344. materica/data/conformance/plain_read/cases/PR-320.operating_token_condition_with_unit.json +58 -0
  345. materica/data/conformance/plain_read/cases/PR-320.operating_unit_array.json +56 -0
  346. materica/data/conformance/plain_read/cases/PR-320.operating_unit_escaped_k_accepted.json +53 -0
  347. materica/data/conformance/plain_read/cases/PR-320.operating_unit_kelvin_sign.json +54 -0
  348. materica/data/conformance/plain_read/cases/PR-320.operating_unit_kelvin_sign_escaped.json +54 -0
  349. materica/data/conformance/plain_read/cases/PR-320.operating_unit_lowercase_k.json +54 -0
  350. materica/data/conformance/plain_read/cases/PR-320.operating_unit_null.json +54 -0
  351. materica/data/conformance/plain_read/cases/PR-320.operating_unit_number.json +54 -0
  352. materica/data/conformance/plain_read/cases/PR-320.operating_unit_per_s.json +58 -0
  353. materica/data/conformance/plain_read/cases/PR-320.operating_unit_s_minus_1.json +58 -0
  354. materica/data/conformance/plain_read/cases/PR-320.operating_unit_trailing_space.json +54 -0
  355. materica/data/conformance/plain_read/cases/PR-320.operating_unregistered_condition_with_unit.json +58 -0
  356. materica/data/conformance/plain_read/cases/PR-320.operating_value_and_range_wrong_unit.json +62 -0
  357. materica/data/conformance/plain_read/cases/PR-320.operating_value_cel.json +54 -0
  358. materica/data/conformance/plain_read/cases/PR-320.operating_value_missing_wrong_unit.json +57 -0
  359. materica/data/conformance/plain_read/cases/PR-320.operating_value_not_number_wrong_unit.json +58 -0
  360. materica/data/conformance/plain_read/cases/PR-320.operating_without_tolerance_cel.json +46 -0
  361. materica/data/conformance/plain_read/cases/PR-320.specimen_size_mm.json +58 -0
  362. materica/data/conformance/plain_read/cases/PR-320.tolerance_and_accept_wrong_unit.json +61 -0
  363. materica/data/conformance/plain_read/cases/PR-320.tolerance_below_zero_wrong_unit.json +58 -0
  364. materica/data/conformance/plain_read/cases/PR-320.tolerance_cel.json +54 -0
  365. materica/data/conformance/plain_read/cases/PR-320.tolerance_for_token_condition_with_unit.json +60 -0
  366. materica/data/conformance/plain_read/cases/PR-320.tolerance_unit_array.json +56 -0
  367. materica/data/conformance/plain_read/cases/PR-320.tolerance_unit_escaped_k_accepted.json +53 -0
  368. materica/data/conformance/plain_read/cases/PR-320.tolerance_unit_kelvin_sign.json +54 -0
  369. materica/data/conformance/plain_read/cases/PR-320.tolerance_unit_null.json +54 -0
  370. materica/data/conformance/plain_read/cases/PR-320.tolerance_unit_number.json +54 -0
  371. materica/data/conformance/plain_read/cases/PR-320.tolerance_unregistered_condition_with_unit.json +60 -0
  372. materica/data/conformance/plain_read/cases/PR-320.tolerance_value_not_number_wrong_unit.json +58 -0
  373. materica/data/conformance/plain_read/cases/PR-320.tolerance_without_operating_condition_wrong_unit.json +64 -0
  374. materica/data/conformance/plain_read/cases/PR-327.label_hs.json +58 -0
  375. materica/data/conformance/plain_read/cases/PR-327.label_no_hs.json +60 -0
  376. materica/data/conformance/plain_read/cases/PR-327.pin.json +55 -0
  377. materica/data/conformance/plain_read/cases/PR-327.pin_no_hs.json +58 -0
  378. materica/data/conformance/plain_read/cases/PR-328.array_source_malformed.json +54 -0
  379. materica/data/conformance/plain_read/cases/PR-328.engine_crosswalk_named_absent.json +54 -0
  380. materica/data/conformance/plain_read/cases/PR-328.id_only_object_malformed.json +54 -0
  381. materica/data/conformance/plain_read/cases/PR-328.ill_formed_hash_other_version_absent.json +53 -0
  382. materica/data/conformance/plain_read/cases/PR-328.no_candidate_absent.json +53 -0
  383. materica/data/conformance/plain_read/cases/PR-328.number_source_malformed.json +54 -0
  384. materica/data/conformance/plain_read/cases/PR-328.other_version_of_id_absent.json +53 -0
  385. materica/data/conformance/plain_read/cases/PR-328.other_version_supplied_absent.json +53 -0
  386. materica/data/conformance/plain_read/cases/PR-328.scene_manifest_absent.json +54 -0
  387. materica/data/conformance/plain_read/cases/PR-328.set_aside_and_unparsed_malformed.json +54 -0
  388. materica/data/conformance/plain_read/cases/PR-328.string_source_malformed.json +54 -0
  389. materica/data/conformance/plain_read/cases/PR-328.unparsed_source_malformed.json +54 -0
  390. materica/data/conformance/plain_read/cases/PR-328.unrelated_malformed_candidate_absent.json +53 -0
  391. materica/data/conformance/plain_read/cases/PR-328.version_not_string_source_malformed.json +54 -0
  392. materica/data/conformance/plain_read/cases/PR-329.hash_selects_other_version_copy.json +54 -0
  393. materica/data/conformance/plain_read/cases/PR-329.hash_selects_unknown_type_copy.json +54 -0
  394. materica/data/conformance/plain_read/cases/PR-329.identical_copies_read_once.json +54 -0
  395. materica/data/conformance/plain_read/cases/PR-329.match_beside_ill_formed_copy.json +54 -0
  396. materica/data/conformance/plain_read/cases/PR-329.match_beside_ill_formed_hash_other_version.json +54 -0
  397. materica/data/conformance/plain_read/cases/PR-329.match_beside_unparsed_source.json +54 -0
  398. materica/data/conformance/plain_read/cases/PR-329.none_with_hash_absent_content_hash.json +54 -0
  399. materica/data/conformance/plain_read/cases/PR-329.none_with_hash_beside_array_source.json +54 -0
  400. materica/data/conformance/plain_read/cases/PR-329.none_with_hash_beside_id_only_source.json +54 -0
  401. materica/data/conformance/plain_read/cases/PR-329.none_with_hash_beside_ill_formed_hash_other_version.json +54 -0
  402. materica/data/conformance/plain_read/cases/PR-329.none_with_hash_beside_malformed_other_candidate.json +54 -0
  403. materica/data/conformance/plain_read/cases/PR-329.none_with_hash_beside_number_source.json +54 -0
  404. materica/data/conformance/plain_read/cases/PR-329.none_with_hash_beside_scene_manifest.json +54 -0
  405. materica/data/conformance/plain_read/cases/PR-329.none_with_hash_beside_string_source.json +54 -0
  406. materica/data/conformance/plain_read/cases/PR-329.none_with_hash_beside_unparsed_source.json +54 -0
  407. materica/data/conformance/plain_read/cases/PR-329.none_with_hash_beside_version_not_string_source.json +54 -0
  408. materica/data/conformance/plain_read/cases/PR-329.none_with_hash_ill_formed_content_hash.json +54 -0
  409. materica/data/conformance/plain_read/cases/PR-329.none_with_hash_null_content_hash.json +54 -0
  410. materica/data/conformance/plain_read/cases/PR-329.none_with_hash_one_candidate.json +53 -0
  411. materica/data/conformance/plain_read/cases/PR-329.none_with_hash_several_candidates.json +54 -0
  412. materica/data/conformance/plain_read/cases/PR-329.two_with_hash_card_differs.json +54 -0
  413. materica/data/conformance/plain_read/cases/PR-329.two_with_hash_whitespace_differs.json +54 -0
  414. materica/data/conformance/plain_read/cases/PR-330.accept_for_numeric_condition.json +53 -0
  415. materica/data/conformance/plain_read/cases/PR-330.accept_list_accepted.json +58 -0
  416. materica/data/conformance/plain_read/cases/PR-330.accept_list_non_string.json +59 -0
  417. materica/data/conformance/plain_read/cases/PR-330.accept_not_list.json +57 -0
  418. materica/data/conformance/plain_read/cases/PR-330.condition_not_registered.json +59 -0
  419. materica/data/conformance/plain_read/cases/PR-330.field_empty_part.json +53 -0
  420. materica/data/conformance/plain_read/cases/PR-330.field_missing.json +52 -0
  421. materica/data/conformance/plain_read/cases/PR-330.field_no_dot.json +53 -0
  422. materica/data/conformance/plain_read/cases/PR-330.field_not_string.json +53 -0
  423. materica/data/conformance/plain_read/cases/PR-330.field_three_parts.json +53 -0
  424. materica/data/conformance/plain_read/cases/PR-330.field_trailing_newline.json +53 -0
  425. materica/data/conformance/plain_read/cases/PR-330.field_uppercase.json +53 -0
  426. materica/data/conformance/plain_read/cases/PR-330.not_json_bom.json +27 -0
  427. materica/data/conformance/plain_read/cases/PR-330.not_json_duplicate_member.json +27 -0
  428. materica/data/conformance/plain_read/cases/PR-330.not_json_nan.json +27 -0
  429. materica/data/conformance/plain_read/cases/PR-330.not_json_nesting_65.json +27 -0
  430. materica/data/conformance/plain_read/cases/PR-330.not_json_trailing_comma.json +27 -0
  431. materica/data/conformance/plain_read/cases/PR-330.not_object_array.json +30 -0
  432. materica/data/conformance/plain_read/cases/PR-330.not_object_string.json +27 -0
  433. materica/data/conformance/plain_read/cases/PR-330.operating_conditions_not_object.json +45 -0
  434. materica/data/conformance/plain_read/cases/PR-330.operating_conditions_not_object_beside_tolerance.json +57 -0
  435. materica/data/conformance/plain_read/cases/PR-330.operating_entry_not_object.json +51 -0
  436. materica/data/conformance/plain_read/cases/PR-330.operating_unit_missing.json +53 -0
  437. materica/data/conformance/plain_read/cases/PR-330.operating_value_and_range.json +58 -0
  438. materica/data/conformance/plain_read/cases/PR-330.operating_value_missing.json +53 -0
  439. materica/data/conformance/plain_read/cases/PR-330.operating_value_not_number.json +54 -0
  440. materica/data/conformance/plain_read/cases/PR-330.range_lo_above_hi.json +61 -0
  441. materica/data/conformance/plain_read/cases/PR-330.range_not_numbers.json +61 -0
  442. materica/data/conformance/plain_read/cases/PR-330.range_one_number.json +60 -0
  443. materica/data/conformance/plain_read/cases/PR-330.range_three_numbers.json +62 -0
  444. materica/data/conformance/plain_read/cases/PR-330.record_content_hash_not_string.json +55 -0
  445. materica/data/conformance/plain_read/cases/PR-330.record_id_missing.json +52 -0
  446. materica/data/conformance/plain_read/cases/PR-330.record_id_not_string.json +53 -0
  447. materica/data/conformance/plain_read/cases/PR-330.record_not_object.json +49 -0
  448. materica/data/conformance/plain_read/cases/PR-330.record_version_missing.json +52 -0
  449. materica/data/conformance/plain_read/cases/PR-330.record_version_not_string.json +53 -0
  450. materica/data/conformance/plain_read/cases/PR-330.record_without_content_hash.json +52 -0
  451. materica/data/conformance/plain_read/cases/PR-330.requirement_condition_empty.json +49 -0
  452. materica/data/conformance/plain_read/cases/PR-330.requirement_condition_not_object.json +49 -0
  453. materica/data/conformance/plain_read/cases/PR-330.requirement_conditions_not_object.json +53 -0
  454. materica/data/conformance/plain_read/cases/PR-330.requirement_missing.json +42 -0
  455. materica/data/conformance/plain_read/cases/PR-330.requirement_not_object.json +43 -0
  456. materica/data/conformance/plain_read/cases/PR-330.target_missing.json +45 -0
  457. materica/data/conformance/plain_read/cases/PR-330.target_neither_record_nor_region.json +48 -0
  458. materica/data/conformance/plain_read/cases/PR-330.target_not_object.json +46 -0
  459. materica/data/conformance/plain_read/cases/PR-330.tolerance_and_accept.json +57 -0
  460. materica/data/conformance/plain_read/cases/PR-330.tolerance_below_zero.json +54 -0
  461. materica/data/conformance/plain_read/cases/PR-330.tolerance_beside_accept_for_token_condition.json +63 -0
  462. materica/data/conformance/plain_read/cases/PR-330.tolerance_for_token_condition_without_unit.json +59 -0
  463. materica/data/conformance/plain_read/cases/PR-330.tolerance_negative_zero_accepted.json +53 -0
  464. materica/data/conformance/plain_read/cases/PR-330.tolerance_not_object.json +51 -0
  465. materica/data/conformance/plain_read/cases/PR-330.tolerance_unit_missing.json +53 -0
  466. materica/data/conformance/plain_read/cases/PR-330.tolerance_value_missing.json +53 -0
  467. materica/data/conformance/plain_read/cases/PR-330.tolerance_value_not_number.json +54 -0
  468. materica/data/conformance/plain_read/cases/PR-330.unknown_member_in_operating_condition.json +54 -0
  469. materica/data/conformance/plain_read/cases/PR-330.unknown_member_in_reference.json +54 -0
  470. materica/data/conformance/plain_read/cases/PR-330.unknown_member_in_requirement.json +54 -0
  471. materica/data/conformance/plain_read/cases/PR-330.unknown_member_in_target.json +54 -0
  472. materica/data/conformance/plain_read/cases/PR-330.unknown_member_in_tolerance.json +54 -0
  473. materica/data/conformance/plain_read/cases/PR-330.unknown_member_top_level.json +60 -0
  474. materica/data/conformance/plain_read/cases/PR-330.want_not_string.json +53 -0
  475. materica/data/conformance/plain_read/cases/PR-330.want_unknown_token.json +53 -0
  476. materica/data/conformance/plain_read/cases/PR-330.want_wrong_case.json +53 -0
  477. materica/data/conformance/plain_read/cases/PR-331.incomplete_and_unit_mismatch_once_each.json +58 -0
  478. materica/data/conformance/plain_read/cases/PR-331.malformed_once_step1.json +54 -0
  479. materica/data/conformance/plain_read/cases/PR-331.malformed_once_step1_pin.json +54 -0
  480. materica/data/conformance/plain_read/cases/PR-331.malformed_once_step3.json +53 -0
  481. materica/data/conformance/plain_read/cases/PR-331.request_incomplete_once_per_condition.json +54 -0
  482. materica/data/conformance/plain_read/cases/PR-331.request_incomplete_once_without_condition.json +52 -0
  483. materica/data/conformance/plain_read/cases/PR-331.request_incomplete_two_conditions.json +65 -0
  484. materica/data/conformance/plain_read/cases/PR-331.request_incomplete_with_and_without_condition.json +57 -0
  485. materica/data/conformance/plain_read/cases/PR-331.request_unit_mismatch_once.json +54 -0
  486. materica/data/conformance/plain_read/cases/PR-331.request_unit_mismatch_two_conditions.json +62 -0
  487. materica/data/conformance/plain_read/cases/PR-331.unregistered_condition_once.json +59 -0
  488. materica/data/conformance/plain_read/cases/PR-332.bounds_absent.json +53 -0
  489. materica/data/conformance/plain_read/cases/PR-332.components_absent.json +53 -0
  490. materica/data/conformance/plain_read/cases/PR-332.coverage_with_fd_absent.json +56 -0
  491. materica/data/conformance/plain_read/cases/PR-332.coverage_without_fd.json +56 -0
  492. materica/data/conformance/plain_read/cases/PR-332.evidence_absent.json +53 -0
  493. materica/data/conformance/plain_read/cases/PR-332.fit_with_fd_absent.json +56 -0
  494. materica/data/conformance/plain_read/cases/PR-332.fit_without_fd.json +56 -0
  495. materica/data/conformance/plain_read/cases/PR-332.reference_data_with_fd_absent.json +56 -0
  496. materica/data/conformance/plain_read/cases/PR-332.reference_data_without_fd.json +56 -0
  497. materica/data/conformance/plain_read/inputs/empty_file.json +0 -0
  498. materica/data/conformance/plain_read/inputs/engine_crosswalk_fixture.json +62 -0
  499. materica/data/conformance/plain_read/inputs/glycerol_fixture.json +87 -0
  500. materica/data/conformance/plain_read/inputs/interface_fixture.json +14 -0
  501. materica/data/conformance/plain_read/inputs/interface_fixture_copy.json +14 -0
  502. materica/data/conformance/plain_read/inputs/interface_fixture_edited.json +14 -0
  503. materica/data/conformance/plain_read/inputs/interface_fixture_edited_stale_hash.json +14 -0
  504. materica/data/conformance/plain_read/inputs/interface_missing_licence.json +10 -0
  505. materica/data/conformance/plain_read/inputs/interface_missing_name.json +13 -0
  506. materica/data/conformance/plain_read/inputs/interface_schema_0_2_0.json +14 -0
  507. materica/data/conformance/plain_read/inputs/namespaced_type_fixture.json +14 -0
  508. materica/data/conformance/plain_read/inputs/namespaced_type_missing_name.json +13 -0
  509. materica/data/conformance/plain_read/inputs/overlay_base_content_hash_missing.json +102 -0
  510. materica/data/conformance/plain_read/inputs/overlay_base_content_hash_not_string.json +103 -0
  511. materica/data/conformance/plain_read/inputs/overlay_base_content_hash_null.json +103 -0
  512. materica/data/conformance/plain_read/inputs/overlay_base_id_missing.json +102 -0
  513. materica/data/conformance/plain_read/inputs/overlay_base_id_not_string.json +103 -0
  514. materica/data/conformance/plain_read/inputs/overlay_base_id_null.json +103 -0
  515. materica/data/conformance/plain_read/inputs/overlay_base_missing.json +98 -0
  516. materica/data/conformance/plain_read/inputs/overlay_base_not_object.json +99 -0
  517. materica/data/conformance/plain_read/inputs/overlay_base_null.json +99 -0
  518. materica/data/conformance/plain_read/inputs/overlay_base_version_missing.json +102 -0
  519. materica/data/conformance/plain_read/inputs/overlay_base_version_not_string.json +103 -0
  520. materica/data/conformance/plain_read/inputs/overlay_base_version_null.json +103 -0
  521. materica/data/conformance/plain_read/inputs/overlay_licence_evidence_number.json +103 -0
  522. materica/data/conformance/plain_read/inputs/overlay_missing_body.json +13 -0
  523. materica/data/conformance/plain_read/inputs/overlay_missing_licence.json +99 -0
  524. materica/data/conformance/plain_read/inputs/overlay_missing_name.json +102 -0
  525. materica/data/conformance/plain_read/inputs/overlay_missing_record_type.json +102 -0
  526. materica/data/conformance/plain_read/inputs/overlay_missing_schema_version.json +102 -0
  527. materica/data/conformance/plain_read/inputs/overlay_purpose_missing.json +102 -0
  528. materica/data/conformance/plain_read/inputs/overlay_purpose_not_string.json +103 -0
  529. materica/data/conformance/plain_read/inputs/overlay_purpose_null.json +103 -0
  530. materica/data/conformance/plain_read/inputs/overlay_replaces_missing.json +24 -0
  531. materica/data/conformance/plain_read/inputs/overlay_replaces_not_object.json +25 -0
  532. materica/data/conformance/plain_read/inputs/overlay_replaces_null.json +25 -0
  533. materica/data/conformance/plain_read/inputs/overlay_scope_consumer_missing.json +101 -0
  534. materica/data/conformance/plain_read/inputs/overlay_scope_consumer_not_string.json +103 -0
  535. materica/data/conformance/plain_read/inputs/overlay_scope_consumer_null.json +103 -0
  536. materica/data/conformance/plain_read/inputs/overlay_scope_missing.json +100 -0
  537. materica/data/conformance/plain_read/inputs/overlay_scope_model_complete.json +109 -0
  538. materica/data/conformance/plain_read/inputs/overlay_scope_model_configuration_hash_not_string.json +108 -0
  539. materica/data/conformance/plain_read/inputs/overlay_scope_model_configuration_hash_null.json +108 -0
  540. materica/data/conformance/plain_read/inputs/overlay_scope_model_empty.json +105 -0
  541. materica/data/conformance/plain_read/inputs/overlay_scope_model_name_missing.json +107 -0
  542. materica/data/conformance/plain_read/inputs/overlay_scope_model_name_not_string.json +108 -0
  543. materica/data/conformance/plain_read/inputs/overlay_scope_model_not_object.json +105 -0
  544. materica/data/conformance/plain_read/inputs/overlay_scope_model_null.json +105 -0
  545. materica/data/conformance/plain_read/inputs/overlay_scope_model_version_missing.json +107 -0
  546. materica/data/conformance/plain_read/inputs/overlay_scope_model_version_not_string.json +108 -0
  547. materica/data/conformance/plain_read/inputs/overlay_scope_not_object.json +101 -0
  548. materica/data/conformance/plain_read/inputs/overlay_scope_null.json +101 -0
  549. materica/data/conformance/plain_read/inputs/overlay_scope_run_not_string.json +109 -0
  550. materica/data/conformance/plain_read/inputs/overlay_scope_run_null.json +109 -0
  551. materica/data/conformance/plain_read/inputs/record_binary_bytes.json +0 -0
  552. materica/data/conformance/plain_read/inputs/request_bom.json +27 -0
  553. materica/data/conformance/plain_read/inputs/request_duplicate_member.json +29 -0
  554. materica/data/conformance/plain_read/inputs/request_nan.json +28 -0
  555. materica/data/conformance/plain_read/inputs/request_nesting_100000.json +28 -0
  556. materica/data/conformance/plain_read/inputs/request_nesting_65.json +28 -0
  557. materica/data/conformance/plain_read/inputs/request_trailing_comma.json +27 -0
  558. materica/data/conformance/plain_read/inputs/scene_manifest_fixture.json +36 -0
  559. materica/data/conformance/plain_read/inputs/source_array_of_record.json +89 -0
  560. materica/data/conformance/plain_read/inputs/source_id_only.json +3 -0
  561. materica/data/conformance/plain_read/inputs/source_number.json +1 -0
  562. materica/data/conformance/plain_read/inputs/source_string.json +1 -0
  563. materica/data/conformance/plain_read/inputs/unknown_type_fixture.json +14 -0
  564. materica/data/conformance/plain_read/inputs/unknown_type_missing_body.json +13 -0
  565. materica/data/conformance/plain_read/inputs/unknown_type_two_envelope_faults.json +10 -0
  566. materica/data/conformance/plain_read/inputs/water_body_wrong_type.json +14 -0
  567. materica/data/conformance/plain_read/inputs/water_card_wrong_type.json +87 -0
  568. materica/data/conformance/plain_read/inputs/water_content_hash_63_digits.json +87 -0
  569. materica/data/conformance/plain_read/inputs/water_content_hash_no_prefix.json +87 -0
  570. materica/data/conformance/plain_read/inputs/water_content_hash_not_string.json +87 -0
  571. materica/data/conformance/plain_read/inputs/water_content_hash_null.json +87 -0
  572. materica/data/conformance/plain_read/inputs/water_content_hash_trailing_newline.json +87 -0
  573. materica/data/conformance/plain_read/inputs/water_content_hash_uppercase.json +87 -0
  574. materica/data/conformance/plain_read/inputs/water_document_type_without_record_type.json +87 -0
  575. materica/data/conformance/plain_read/inputs/water_escaped_nul.json +87 -0
  576. materica/data/conformance/plain_read/inputs/water_extensions_array.json +88 -0
  577. materica/data/conformance/plain_read/inputs/water_fault_bom.json +87 -0
  578. materica/data/conformance/plain_read/inputs/water_fault_comment.json +88 -0
  579. materica/data/conformance/plain_read/inputs/water_fault_control_character.json +87 -0
  580. materica/data/conformance/plain_read/inputs/water_fault_duplicate_member.json +88 -0
  581. materica/data/conformance/plain_read/inputs/water_fault_duplicate_member_escaped.json +88 -0
  582. materica/data/conformance/plain_read/inputs/water_fault_encoded_surrogate.json +87 -0
  583. materica/data/conformance/plain_read/inputs/water_fault_infinity.json +87 -0
  584. materica/data/conformance/plain_read/inputs/water_fault_nan.json +87 -0
  585. materica/data/conformance/plain_read/inputs/water_fault_negative_infinity.json +87 -0
  586. materica/data/conformance/plain_read/inputs/water_fault_nesting_100000.json +88 -0
  587. materica/data/conformance/plain_read/inputs/water_fault_nesting_65.json +88 -0
  588. materica/data/conformance/plain_read/inputs/water_fault_number_1e400.json +87 -0
  589. materica/data/conformance/plain_read/inputs/water_fault_number_overflow.json +87 -0
  590. materica/data/conformance/plain_read/inputs/water_fault_overlong.json +87 -0
  591. materica/data/conformance/plain_read/inputs/water_fault_trailing_comma.json +87 -0
  592. materica/data/conformance/plain_read/inputs/water_fault_trailing_content.json +88 -0
  593. materica/data/conformance/plain_read/inputs/water_fault_truncated.json +86 -0
  594. materica/data/conformance/plain_read/inputs/water_fault_truncated_utf8.json +87 -0
  595. materica/data/conformance/plain_read/inputs/water_fault_unpaired_high_surrogate.json +87 -0
  596. materica/data/conformance/plain_read/inputs/water_fault_unpaired_low_surrogate.json +87 -0
  597. materica/data/conformance/plain_read/inputs/water_fault_utf16be.json +0 -0
  598. materica/data/conformance/plain_read/inputs/water_fault_utf16le.json +0 -0
  599. materica/data/conformance/plain_read/inputs/water_fault_utf16le_bom.json +0 -0
  600. materica/data/conformance/plain_read/inputs/water_fault_utf32be.json +0 -0
  601. materica/data/conformance/plain_read/inputs/water_fault_utf32le.json +0 -0
  602. materica/data/conformance/plain_read/inputs/water_fields_array.json +20 -0
  603. materica/data/conformance/plain_read/inputs/water_fixture.cbor +1 -0
  604. materica/data/conformance/plain_read/inputs/water_fixture.json +87 -0
  605. materica/data/conformance/plain_read/inputs/water_fixture.toml +86 -0
  606. materica/data/conformance/plain_read/inputs/water_fixture.yaml +60 -0
  607. materica/data/conformance/plain_read/inputs/water_fixture_as_interface.json +14 -0
  608. materica/data/conformance/plain_read/inputs/water_fixture_edited.json +87 -0
  609. materica/data/conformance/plain_read/inputs/water_fixture_edited_2.json +87 -0
  610. materica/data/conformance/plain_read/inputs/water_fixture_edited_stale_hash.json +87 -0
  611. materica/data/conformance/plain_read/inputs/water_fixture_other_card.json +87 -0
  612. materica/data/conformance/plain_read/inputs/water_fixture_reformatted.json +1 -0
  613. materica/data/conformance/plain_read/inputs/water_fixture_schema_0_2_0.json +87 -0
  614. materica/data/conformance/plain_read/inputs/water_fixture_v2.json +87 -0
  615. materica/data/conformance/plain_read/inputs/water_fixture_v2_content_hash_uppercase.json +87 -0
  616. materica/data/conformance/plain_read/inputs/water_fluid_section_number.json +18 -0
  617. materica/data/conformance/plain_read/inputs/water_fluid_section_without_fields.json +18 -0
  618. materica/data/conformance/plain_read/inputs/water_id_uppercase_namespace.json +87 -0
  619. materica/data/conformance/plain_read/inputs/water_id_without_namespace.json +87 -0
  620. materica/data/conformance/plain_read/inputs/water_id_wrong_type.json +87 -0
  621. materica/data/conformance/plain_read/inputs/water_licence_evidence_missing.json +86 -0
  622. materica/data/conformance/plain_read/inputs/water_licence_evidence_wrong_type.json +87 -0
  623. materica/data/conformance/plain_read/inputs/water_licence_values_missing.json +86 -0
  624. materica/data/conformance/plain_read/inputs/water_licence_wrong_type.json +84 -0
  625. materica/data/conformance/plain_read/inputs/water_local_id_empty.json +87 -0
  626. materica/data/conformance/plain_read/inputs/water_local_id_space.json +87 -0
  627. materica/data/conformance/plain_read/inputs/water_local_id_trailing_newline.json +87 -0
  628. materica/data/conformance/plain_read/inputs/water_missing_body.json +13 -0
  629. materica/data/conformance/plain_read/inputs/water_missing_content_hash.json +86 -0
  630. materica/data/conformance/plain_read/inputs/water_missing_id.json +86 -0
  631. materica/data/conformance/plain_read/inputs/water_missing_licence.json +83 -0
  632. materica/data/conformance/plain_read/inputs/water_missing_name.json +86 -0
  633. materica/data/conformance/plain_read/inputs/water_missing_record_type.json +86 -0
  634. materica/data/conformance/plain_read/inputs/water_missing_version.json +86 -0
  635. materica/data/conformance/plain_read/inputs/water_name_wrong_type.json +89 -0
  636. materica/data/conformance/plain_read/inputs/water_nesting_64.json +88 -0
  637. materica/data/conformance/plain_read/inputs/water_noncharacter.json +87 -0
  638. materica/data/conformance/plain_read/inputs/water_noncharacter_escaped.json +87 -0
  639. materica/data/conformance/plain_read/inputs/water_null_body.json +14 -0
  640. materica/data/conformance/plain_read/inputs/water_null_card.json +87 -0
  641. materica/data/conformance/plain_read/inputs/water_null_extensions.json +88 -0
  642. materica/data/conformance/plain_read/inputs/water_null_fields.json +20 -0
  643. materica/data/conformance/plain_read/inputs/water_null_known_section.json +18 -0
  644. materica/data/conformance/plain_read/inputs/water_null_licence.json +84 -0
  645. materica/data/conformance/plain_read/inputs/water_null_licence_evidence.json +87 -0
  646. materica/data/conformance/plain_read/inputs/water_null_licence_values.json +87 -0
  647. materica/data/conformance/plain_read/inputs/water_null_name.json +87 -0
  648. materica/data/conformance/plain_read/inputs/water_null_record_type.json +87 -0
  649. materica/data/conformance/plain_read/inputs/water_null_sections.json +16 -0
  650. materica/data/conformance/plain_read/inputs/water_overlay_fixture.json +103 -0
  651. materica/data/conformance/plain_read/inputs/water_record_type_capitalised.json +87 -0
  652. materica/data/conformance/plain_read/inputs/water_record_type_wrong_type.json +87 -0
  653. materica/data/conformance/plain_read/inputs/water_schema_00_1_0.json +87 -0
  654. materica/data/conformance/plain_read/inputs/water_schema_0_01_0.json +87 -0
  655. materica/data/conformance/plain_read/inputs/water_schema_0_0_1.json +87 -0
  656. materica/data/conformance/plain_read/inputs/water_schema_0_1.json +87 -0
  657. materica/data/conformance/plain_read/inputs/water_schema_0_10_0.json +87 -0
  658. materica/data/conformance/plain_read/inputs/water_schema_0_1_0_rc1.json +87 -0
  659. materica/data/conformance/plain_read/inputs/water_schema_0_1_7.json +87 -0
  660. materica/data/conformance/plain_read/inputs/water_schema_0_2_0_bad_licence.json +84 -0
  661. materica/data/conformance/plain_read/inputs/water_schema_0_2_0_missing_name.json +86 -0
  662. materica/data/conformance/plain_read/inputs/water_schema_1_0_0.json +87 -0
  663. materica/data/conformance/plain_read/inputs/water_schema_1_1_0.json +87 -0
  664. materica/data/conformance/plain_read/inputs/water_schema_2_0_0.json +87 -0
  665. materica/data/conformance/plain_read/inputs/water_schema_absent.json +86 -0
  666. materica/data/conformance/plain_read/inputs/water_schema_arabic_indic.json +87 -0
  667. materica/data/conformance/plain_read/inputs/water_schema_array.json +89 -0
  668. materica/data/conformance/plain_read/inputs/water_schema_major_100_digits.json +87 -0
  669. materica/data/conformance/plain_read/inputs/water_schema_minor_100_digits.json +87 -0
  670. materica/data/conformance/plain_read/inputs/water_schema_null.json +87 -0
  671. materica/data/conformance/plain_read/inputs/water_schema_number.json +87 -0
  672. materica/data/conformance/plain_read/inputs/water_schema_patch_100_digits.json +87 -0
  673. materica/data/conformance/plain_read/inputs/water_schema_trailing_newline.json +87 -0
  674. materica/data/conformance/plain_read/inputs/water_schema_trailing_space.json +87 -0
  675. materica/data/conformance/plain_read/inputs/water_sections_array.json +16 -0
  676. materica/data/conformance/plain_read/inputs/water_sections_missing.json +14 -0
  677. materica/data/conformance/plain_read/inputs/water_unknown_member_null.json +88 -0
  678. materica/data/conformance/plain_read/inputs/water_version_01_0_0.json +87 -0
  679. materica/data/conformance/plain_read/inputs/water_version_1_0.json +87 -0
  680. materica/data/conformance/plain_read/inputs/water_version_wrong_type.json +87 -0
  681. materica/data/conformance/plain_read/inputs/water_with_document_type_member.json +88 -0
  682. materica/io/README.md +10 -0
  683. materica/io/__init__.py +2 -0
  684. materica/io/plain.py +17 -0
  685. materica/py.typed +0 -0
  686. materica/schema/0.1/README.md +15 -0
  687. materica/schema/0.1/case.json +82 -0
  688. materica/schema/0.1/read_request.json +104 -0
  689. materica/schema/0.1/read_result.json +37 -0
  690. materica/schema/0.1/record.reader.json +253 -0
  691. materica/schema/0.1/record.writer.json +192 -0
  692. materica/schema/0.1/vocabulary/README.md +17 -0
  693. materica/schema/0.1/vocabulary/acceptances.json +15 -0
  694. materica/schema/0.1/vocabulary/conditions.json +63 -0
  695. materica/schema/0.1/vocabulary/fields.json +83 -0
  696. materica/schema/0.1/vocabulary/reasons.json +292 -0
  697. materica/schema/0.1/vocabulary/specimen_facts.json +49 -0
  698. materica/schema/README.md +29 -0
  699. materica/shapes.py +409 -0
  700. materica/shapes.pyi +366 -0
  701. openmaterica-0.1.0.dev1.dist-info/METADATA +71 -0
  702. openmaterica-0.1.0.dev1.dist-info/RECORD +704 -0
  703. openmaterica-0.1.0.dev1.dist-info/WHEEL +4 -0
  704. openmaterica-0.1.0.dev1.dist-info/licenses/LICENSE +201 -0
materica/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # `materica`
2
+
3
+ The Python package. It implements the reader side of the OpenMaterica specification (`docs/specification/`).
4
+ The specification is normative: where this code and it differ, the code is wrong.
5
+
6
+ ## Layers
7
+
8
+ The package is built in layers (AD 7.1), and a module imports only from its own layer or a lower one.
9
+
10
+ | Layer | Directory | What it holds |
11
+ |---|---|---|
12
+ | L0, schemas | `schema/`, `shapes.py` | the JSON Schemas (`schema/README.md`), and the JSON shapes as TypedDicts generated from them |
13
+ | L1, data | `data/`, `schema/0.1/vocabulary/` | the specification's conformance cases and the inputs they supply (`data/conformance/`, with their own `README.md`), and its vocabulary, published with the schemas |
14
+ | L2, core | `core/` | strict JSON, the canonical form and the content hash; identifiers, the envelope checks and the read up to step 5; Python's standard library only (`core/README.md`) |
15
+ | L4, readers | `io/` | files into the core's types (`io/README.md`) |
16
+
17
+ The authoring tools (L3), the sampling helpers (`sample/`, L5) and the command line (`tools/`, L6) arrive in
18
+ later steps. `tests/unit/test_source_files.py` walks every module's imports: a module imports only its own
19
+ layer or a lower one; `core/` imports only the standard library, itself and `shapes.py`, which imports only the
20
+ standard library; and nothing imports `materica_authoring`.
21
+
22
+ ## What holds across the package
23
+
24
+ - No run-time dependency (AD 7.2): the built wheel declares none (`scripts/check_wheel.py`).
25
+ - It is typed (PEP 561) and ships `py.typed`. `mypy --strict` and pyright in strict mode pass over it, and a
26
+ consumer's code type-checks against the installed wheel (`tests/typing/`). `shapes.pyi`, which type checkers
27
+ read in place of `shapes.py`, marks what a read returns read-only (PEP 705).
28
+ - Everything under `data/` and `schema/` ships in the wheel byte for byte, since the conformance inputs are
29
+ byte-exact and the reader loads the vocabulary (`scripts/check_wheel.py`).
30
+ - Generated files are never edited by hand. `scripts/` regenerates them and CI fails on any difference: the
31
+ vocabulary from the specification's tables, the reader schema and the shapes from the writer schemas
32
+ (CONTRIBUTING, "Changing the schema").
33
+ - `__init__.py` holds the public API built so far: `content_hash`, `load_records` and `read`.
materica/__init__.py ADDED
@@ -0,0 +1,8 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """OpenMaterica: material records and the reader of their specification (`docs/specification/`)."""
3
+
4
+ from materica.core.hashing import content_hash
5
+ from materica.core.read import read
6
+ from materica.io.plain import load_records
7
+
8
+ __all__ = ["content_hash", "load_records", "read"]
@@ -0,0 +1,72 @@
1
+ # `materica.core`
2
+
3
+ The core (layer L2, AD 7.1): the code that reads and checks records. It uses Python's standard library only
4
+ (AD 7.2, CONTRIBUTING constraint 3), so it adds nothing to a consumer's dependencies; the shapes it types its
5
+ results with (`materica.shapes`, generated) use the standard library only too.
6
+
7
+ ## The data paths
8
+
9
+ The content hash:
10
+
11
+ ```
12
+ bytes ─▶ jsonio.parse ─▶ value ─▶ hashing.hashable_view ─▶ view ─▶ canonical.canonicalize ─▶ bytes ─▶ SHA-256
13
+ │ (hashing.content_hash runs these three, and writes "sha256:<hex>")
14
+ └─▶ Reason("malformed")
15
+ ```
16
+
17
+ A read, steps 0 to 5 of `read_side_contract.md` section 3:
18
+
19
+ ```
20
+ request ─▶ read.ReadRequest.from_json ─▶ step 0, the request on its own ─▶ reasons, or a ReadRequest
21
+ │
22
+ sources ─▶ record.RecordStore.add ─▶ candidates by id and version, ▼
23
+ and the unreadable sources resolve.resolve_record
24
+ 1 the candidate that states the pin
25
+ 2 its schema version ┐
26
+ 3 envelope.py's checks ├ kept on the Record
27
+ 5 its type ┘
28
+ 4 the hash, with HS: recomputed on every read,
29
+ between steps 3 and 5
30
+ │
31
+ read.ReadResult (status, reasons, labels) ◀────────┘ or NotImplementedError for steps 6 to 13
32
+ ```
33
+
34
+ | Module | Implements |
35
+ |---|---|
36
+ | `reasons.py` | a reason as `read_side_contract.md` section 2 shapes it, each code and condition once; codes from the table in section 4 |
37
+ | `status.py` | the three statuses of a read, and the worst of several (section 2) |
38
+ | `jsonio.py` | `record_format.md` section 1 item 6, strict JSON; `JsonValue`, the type of what it reads |
39
+ | `canonical.py` | `record_format.md` section 9 item 2: RFC 8785, with no Unicode normalisation |
40
+ | `hashing.py` | `record_format.md` section 9 items 1 and 2: what the hash leaves out, and the hash |
41
+ | `identifiers.py` | `record_format.md` sections 7 and 8: identifiers and versions, matched in full; material references |
42
+ | `vocabulary.py` | the tokens of the specification's tables, read from `schema/0.1/vocabulary/` |
43
+ | `envelope.py` | the reader schema's checks by hand (`record_format.md` section 1 item 2) |
44
+ | `record.py` | the records a read resolves among, and the checks that depend on one record alone (steps 2, 3 and 5) |
45
+ | `resolve.py` | steps 1 to 5: a material reference to the record it pins, or the reasons it is refused |
46
+ | `read.py` | the request's own check (step 0), and the read; steps 6 to 13 are not built yet |
47
+
48
+ The conformance cases HS-001 to HS-003 check the hash end to end; the plain-read cases, HS-010 and HS-011 the
49
+ read up to step 5 (`tests/conformance/`).
50
+
51
+ ## Invariants
52
+
53
+ - **Results, never exceptions, for content.** `parse` gives a value or `malformed` for any bytes, running out
54
+ of stack or memory included, and a read gives a result for any request and any records. An exception means
55
+ a misuse of the Python API (`canonicalize` given a value `parse` would never give; claims no reader makes, a
56
+ suite that does not exist or claims without plain read) or a step not built yet: a read whose answer a later
57
+ step would decide raises `NotImplementedError` rather than give one, whatever else is wrong with the request
58
+ (`tests/property/test_read_properties.py`, `tests/unit/test_read.py`).
59
+ - **A request is JSON text or a value.** Text is a `str` or bytes-like (`bytes`, `bytearray`, `memoryview`),
60
+ read like a record's bytes; a `str` is always text, as a JSON string is never a request. Any other value is
61
+ read as the JSON text `json.dumps` writes of it.
62
+ - **Every number is a float.** An integer reads as the nearest double; `JsonValue` has no `int`, and
63
+ `canonicalize` refuses one. A request given as a Python value is read through JSON text, so its integers too.
64
+ (The reader's properties compare types exactly; `tests/unit/test_canonical.py`.)
65
+ - **Stored JSON is never mutated.** `hashable_view` builds new containers and leaves its argument as it was
66
+ (`tests/unit/test_hashing.py`); a `Record` keeps the value its bytes parse to as it is.
67
+ - **Identifiers match in full**, by `re.fullmatch` with character classes written out
68
+ (`tests/property/test_version_properties.py`).
69
+ - **One envelope check, in two forms.** `envelope.py` and `schema/0.1/record.reader.json` accept and refuse
70
+ the same records (`tests/spec_sync/test_envelope.py`, `tests/property/test_envelope_properties.py`).
71
+ - **Standard library only**, with `materica.shapes`, itself standard library only, and, for type checkers
72
+ only, `typing_extensions`; relative imports are checked like absolute ones (`tests/unit/test_source_files.py`).
@@ -0,0 +1,2 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """The core (layer L2, AD 7.1): Python's standard library only (AD 7.2, CONTRIBUTING constraint 3)."""
@@ -0,0 +1,92 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """RFC 8785 canonical JSON, which the content hash is taken over (`record_format.md` section 9 item 2)."""
3
+
4
+ import math
5
+
6
+ from materica.core.jsonio import JsonValue
7
+
8
+ _ESCAPES = {code: f"\\u{code:04x}" for code in range(0x20)} | {
9
+ ord('"'): '\\"',
10
+ ord("\\"): "\\\\",
11
+ ord("\b"): "\\b",
12
+ ord("\f"): "\\f",
13
+ ord("\n"): "\\n",
14
+ ord("\r"): "\\r",
15
+ ord("\t"): "\\t",
16
+ }
17
+
18
+
19
+ def canonicalize(value: JsonValue) -> bytes:
20
+ """`value`, as `parse` gives it, serialised by RFC 8785 in UTF-8.
21
+
22
+ Strings are written as they are, never Unicode-normalised. A value `parse` would never give raises rather
23
+ than being written: `TypeError` for an `int` or a tuple, say, and `ValueError` for a number that is not
24
+ finite or a lone surrogate.
25
+ """
26
+ parts: list[str] = []
27
+ _write(value, parts)
28
+ return "".join(parts).encode("utf-8")
29
+
30
+
31
+ def _write(value: JsonValue, parts: list[str]) -> None:
32
+ if value is None:
33
+ parts.append("null")
34
+ elif isinstance(value, bool):
35
+ parts.append("true" if value else "false")
36
+ elif isinstance(value, float):
37
+ parts.append(_number(value))
38
+ elif isinstance(value, str):
39
+ parts.append(_string(value))
40
+ elif isinstance(value, list):
41
+ parts.append("[")
42
+ for index, item in enumerate(value):
43
+ if index:
44
+ parts.append(",")
45
+ _write(item, parts)
46
+ parts.append("]")
47
+ elif isinstance(value, dict):
48
+ parts.append("{")
49
+ for index, name in enumerate(sorted(value, key=_utf16_units)):
50
+ if index:
51
+ parts.append(",")
52
+ parts.append(_string(name))
53
+ parts.append(":")
54
+ _write(value[name], parts)
55
+ parts.append("}")
56
+ else:
57
+ raise TypeError(f"not a JSON value as parse gives it: {type(value).__name__}")
58
+
59
+
60
+ def _number(number: float) -> str:
61
+ """ECMAScript's `Number.prototype.toString`, as RFC 8785 section 3.2.2.3 requires."""
62
+ if not math.isfinite(number):
63
+ raise ValueError(f"{number} has no JSON form")
64
+ if number == 0:
65
+ return "0"
66
+ # repr gives the fewest digits that read back as the same double, the nearest where several do, as
67
+ # ECMAScript does. Here the double is 0.<digits> times 10**point.
68
+ mantissa, _, exponent = repr(abs(number)).partition("e")
69
+ whole, _, fraction = mantissa.partition(".")
70
+ written = whole + fraction
71
+ digits = written.strip("0")
72
+ leading_zeros = len(written) - len(written.lstrip("0"))
73
+ point = len(whole) - leading_zeros + int(exponent or "0")
74
+ count = len(digits)
75
+ sign = "-" if number < 0 else ""
76
+ if count <= point <= 21:
77
+ return sign + digits + "0" * (point - count)
78
+ if 0 < point <= 21:
79
+ return sign + digits[:point] + "." + digits[point:]
80
+ if -6 < point <= 0:
81
+ return sign + "0." + "0" * -point + digits
82
+ fraction_part = "." + digits[1:] if count > 1 else ""
83
+ return f"{sign}{digits[0]}{fraction_part}e{point - 1:+d}"
84
+
85
+
86
+ def _string(text: str) -> str:
87
+ return '"' + text.translate(_ESCAPES) + '"'
88
+
89
+
90
+ def _utf16_units(name: str) -> bytes:
91
+ # Big-endian bytes order as the UTF-16 code units they encode.
92
+ return name.encode("utf-16-be")
@@ -0,0 +1,93 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """The reader schema's checks, written by hand (`record_format.md` section 1 item 2), so that the core reads
3
+ records with no JSON Schema validator.
4
+
5
+ `schema/0.1/record.reader.json` states the same checks for other languages. Tests hold the two to agreement,
6
+ on every conformance input and on records drawn near each boundary of the item.
7
+ """
8
+
9
+ from materica.core.identifiers import CONTENT_HASH, RECORD_ID, VERSION, Version
10
+ from materica.core.jsonio import JsonValue
11
+ from materica.core.vocabulary import VOCABULARY
12
+
13
+ SCHEMA_VERSION = Version("0", "1", "0")
14
+ """The schema version these checks are the reader schema of."""
15
+
16
+ Members = dict[str, type[object]]
17
+
18
+ _KINDS: dict[type[object], str] = {str: "a string", dict: "an object"}
19
+ _ENVELOPE: Members = {
20
+ "schema_version": str,
21
+ "record_type": str,
22
+ "id": str,
23
+ "version": str,
24
+ "name": str,
25
+ "licence": dict,
26
+ "content_hash": str,
27
+ "body": dict,
28
+ }
29
+ _PATTERNS = {"id": RECORD_ID, "version": VERSION, "content_hash": CONTENT_HASH}
30
+
31
+
32
+ def envelope_problems(record: JsonValue) -> list[str]:
33
+ """Each way `record` breaks the reader schema of schema 0.1, in words: none where it passes.
34
+
35
+ The body is checked by its `record_type`: a material's sections, as far as this version knows them, and an
36
+ overlay's members. A body of another type, a section of another name, `extensions`' contents, a section's
37
+ `specimen` and every value field are left unchecked.
38
+ """
39
+ if not isinstance(record, dict):
40
+ return ["the record is not an object"]
41
+ problems = _members(record, "", _ENVELOPE, {"card": str})
42
+ for name, pattern in _PATTERNS.items():
43
+ value = record.get(name)
44
+ if isinstance(value, str) and not pattern.fullmatch(value):
45
+ problems.append(f"{name} does not match its pattern: {value!r}")
46
+ licence, body = record.get("licence"), record.get("body")
47
+ if isinstance(licence, dict):
48
+ problems += _members(licence, "licence.", {"values": str, "evidence": str})
49
+ if isinstance(body, dict) and record.get("record_type") == "material":
50
+ problems += _material_body(body)
51
+ elif isinstance(body, dict) and record.get("record_type") == "overlay":
52
+ problems += _overlay_body(body)
53
+ return problems
54
+
55
+
56
+ def _material_body(body: dict[str, JsonValue]) -> list[str]:
57
+ problems = _members(body, "body.", {"sections": dict}, {"extensions": dict})
58
+ sections = body.get("sections")
59
+ if isinstance(sections, dict):
60
+ for name in sorted(VOCABULARY.sections & sections.keys()):
61
+ section = sections[name]
62
+ if isinstance(section, dict):
63
+ problems += _members(section, f"body.sections.{name}.", {"fields": dict})
64
+ else:
65
+ problems.append(f"body.sections.{name} is not an object")
66
+ return problems
67
+
68
+
69
+ def _overlay_body(body: dict[str, JsonValue]) -> list[str]:
70
+ problems = _members(body, "body.", {"purpose": str, "base": dict, "scope": dict, "replaces": dict})
71
+ base, scope = body.get("base"), body.get("scope")
72
+ if isinstance(base, dict):
73
+ problems += _members(base, "body.base.", {"id": str, "version": str, "content_hash": str})
74
+ if isinstance(scope, dict):
75
+ optional: Members = {"model": dict, "model_configuration_hash": str, "run": str}
76
+ problems += _members(scope, "body.scope.", {"consumer": str}, optional)
77
+ model = scope.get("model")
78
+ if isinstance(model, dict):
79
+ problems += _members(model, "body.scope.model.", {"name": str, "version": str})
80
+ return problems
81
+
82
+
83
+ def _members(
84
+ value: dict[str, JsonValue], where: str, required: Members, optional: Members | None = None
85
+ ) -> list[str]:
86
+ problems: list[str] = []
87
+ for name, kind in (required | (optional or {})).items():
88
+ if name not in value:
89
+ if name in required:
90
+ problems.append(f"{where}{name} is missing")
91
+ elif not isinstance(value[name], kind):
92
+ problems.append(f"{where}{name} is not {_KINDS[kind]}")
93
+ return problems
@@ -0,0 +1,38 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """The content hash of a record, or of any JSON value (`record_format.md` section 9)."""
3
+
4
+ import hashlib
5
+
6
+ from materica.core.canonical import canonicalize
7
+ from materica.core.jsonio import JsonValue
8
+
9
+
10
+ def hashable_view(value: JsonValue) -> JsonValue:
11
+ """`value` without the members `record_format.md` section 9 item 1 removes; `value` is left unchanged.
12
+
13
+ The top-level `content_hash` and `card` go only when `value` is an object. `review` and `copy` go at any
14
+ depth inside an object that is the value of a member named `provenance`, through objects and arrays.
15
+ """
16
+ if isinstance(value, dict):
17
+ value = {name: member for name, member in value.items() if name not in ("content_hash", "card")}
18
+ return _view(value, inside_provenance=False)
19
+
20
+
21
+ def _view(value: JsonValue, *, inside_provenance: bool) -> JsonValue:
22
+ if isinstance(value, dict):
23
+ return {
24
+ name: _view(
25
+ member,
26
+ inside_provenance=inside_provenance or (name == "provenance" and isinstance(member, dict)),
27
+ )
28
+ for name, member in value.items()
29
+ if not (inside_provenance and name in ("review", "copy"))
30
+ }
31
+ if isinstance(value, list):
32
+ return [_view(item, inside_provenance=inside_provenance) for item in value]
33
+ return value
34
+
35
+
36
+ def content_hash(value: JsonValue) -> str:
37
+ """`sha256:` and the lowercase hexadecimal SHA-256 of `value`'s hashable view in RFC 8785 form."""
38
+ return "sha256:" + hashlib.sha256(canonicalize(hashable_view(value))).hexdigest()
@@ -0,0 +1,67 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Identifiers and versions (`record_format.md` sections 7 and 8), and material references.
3
+
4
+ Every pattern here is matched in full, with `re.fullmatch`, never searched: `$` also matches before a final
5
+ newline. Character classes are written out, since `\\d` would match any Unicode digit.
6
+ """
7
+
8
+ import functools
9
+ import re
10
+ from dataclasses import dataclass
11
+
12
+ from materica import shapes
13
+
14
+ NAMESPACE = re.compile(r"[a-z0-9_]+")
15
+ RECORD_ID = re.compile(r"[a-z0-9_]+/[A-Za-z0-9_.-]+")
16
+ FAMILY_ID = re.compile(r"[a-z0-9_]+(?:\.[a-z0-9_]+)+\.v[1-9][0-9]*")
17
+ VERSION = re.compile(r"(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)")
18
+ _COMPONENT = re.compile(r"0|[1-9][0-9]*")
19
+ CONTENT_HASH = re.compile(r"sha256:[0-9a-f]{64}")
20
+ # A request's field, `<section>.<field>` (`read_side_contract.md` section 1).
21
+ FIELD = re.compile(r"[a-z0-9_]+\.[a-z0-9_]+")
22
+
23
+
24
+ @functools.total_ordering
25
+ @dataclass(frozen=True)
26
+ class Version:
27
+ """`MAJOR.MINOR.PATCH`, its components kept as their digits.
28
+
29
+ Section 8 compares components as numbers. With no leading zeros, which construction refuses, comparing
30
+ their lengths and then their digits gives that order for any length, where `int` refuses more than 4300
31
+ digits.
32
+ """
33
+
34
+ major: str
35
+ minor: str
36
+ patch: str
37
+
38
+ def __post_init__(self) -> None:
39
+ for component in (self.major, self.minor, self.patch):
40
+ if not _COMPONENT.fullmatch(component):
41
+ raise ValueError(f"not a version component: {component!r}")
42
+
43
+ def __lt__(self, other: object) -> bool:
44
+ if not isinstance(other, Version):
45
+ return NotImplemented
46
+ return self._key() < other._key()
47
+
48
+ def _key(self) -> tuple[tuple[int, str], ...]:
49
+ return tuple((len(component), component) for component in (self.major, self.minor, self.patch))
50
+
51
+
52
+ def parse_version(text: str) -> Version | None:
53
+ """The version `text` writes, or None where it does not match section 8's pattern in full."""
54
+ matched = VERSION.fullmatch(text)
55
+ return None if matched is None else Version(matched[1], matched[2], matched[3])
56
+
57
+
58
+ @dataclass(frozen=True)
59
+ class MaterialRef:
60
+ """A material reference: a record's `id` and `version`, and its `content_hash` as the pin."""
61
+
62
+ id: str
63
+ version: str
64
+ content_hash: str
65
+
66
+ def to_json(self) -> shapes.MaterialRef:
67
+ return {"id": self.id, "version": self.version, "content_hash": self.content_hash}
@@ -0,0 +1,102 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Strict JSON: bytes to a value, or the reason `malformed` (`record_format.md` section 1 item 6).
3
+
4
+ The item applies to records, scene documents, engine crosswalks, read requests and conformance case files.
5
+ """
6
+
7
+ import codecs
8
+ import json
9
+ import math
10
+ import re
11
+ from collections.abc import Iterator
12
+ from typing import NoReturn, TypeAlias
13
+
14
+ from materica.core.reasons import Reason
15
+
16
+ JsonValue: TypeAlias = bool | float | str | list["JsonValue"] | dict[str, "JsonValue"] | None
17
+ """A value as `parse` gives it: every number is a float."""
18
+
19
+ MAX_DEPTH = 64
20
+
21
+ # A whole string, so that brackets inside one are skipped, or a bracket.
22
+ _STRING_OR_BRACKET = re.compile(r'"[^"\\]*(?:\\.[^"\\]*)*"|[][{}]', re.DOTALL)
23
+ _SURROGATE = re.compile("[\ud800-\udfff]")
24
+
25
+
26
+ def parse(data: bytes) -> JsonValue | Reason:
27
+ """Read `data` by `record_format.md` section 1 item 6.
28
+
29
+ Gives the value, or `Reason("malformed")` with a detail for anything that item refuses. Never raises for
30
+ any bytes.
31
+ """
32
+ try:
33
+ return _parse(data)
34
+ except (ValueError, RecursionError, MemoryError) as error:
35
+ return Reason("malformed", detail=str(error) or type(error).__name__)
36
+
37
+
38
+ def _parse(data: bytes) -> JsonValue:
39
+ if data.startswith(codecs.BOM_UTF8):
40
+ raise ValueError("a byte-order mark")
41
+ text = data.decode("utf-8")
42
+ # Counted before json runs, so that json never recurses deeper than this: 100000 levels would exhaust
43
+ # its stack.
44
+ if _nesting_exceeds(text, MAX_DEPTH):
45
+ raise ValueError(f"nested more than {MAX_DEPTH} deep")
46
+ value: JsonValue = json.loads(
47
+ text, object_pairs_hook=_object, parse_float=_double, parse_int=_double, parse_constant=_constant
48
+ )
49
+ # json joins a paired surrogate escape into one character and keeps an unpaired one; the strict decoding
50
+ # above has refused any surrogate written as bytes.
51
+ if any(_SURROGATE.search(string) for string in _strings(value)):
52
+ raise ValueError("an unpaired surrogate escape")
53
+ return value
54
+
55
+
56
+ def _nesting_exceeds(text: str, limit: int) -> bool:
57
+ depth = 0
58
+ for token in _STRING_OR_BRACKET.finditer(text):
59
+ if token.group() in ("[", "{"):
60
+ depth += 1
61
+ if depth > limit:
62
+ return True
63
+ elif token.group() in ("]", "}"):
64
+ depth -= 1
65
+ return False
66
+
67
+
68
+ def _object(pairs: list[tuple[str, JsonValue]]) -> dict[str, JsonValue]:
69
+ members: dict[str, JsonValue] = {}
70
+ for name, value in pairs:
71
+ if name in members:
72
+ raise ValueError(f"the member name {name!r} repeated")
73
+ members[name] = value
74
+ return members
75
+
76
+
77
+ def _double(text: str) -> float:
78
+ # Integers come here too, as text: int() refuses more than 4300 digits, and float(int) overflows where
79
+ # float(text) rounds. json's pure-Python scanner, used where its C one is missing, matches any Unicode
80
+ # digit as a digit.
81
+ if not text.isascii():
82
+ raise ValueError(f"not a JSON number: {text!r}")
83
+ number = float(text)
84
+ if math.isinf(number):
85
+ raise ValueError("a number that rounds to an infinity")
86
+ return number
87
+
88
+
89
+ def _constant(name: str) -> NoReturn:
90
+ raise ValueError(f"{name} is not JSON")
91
+
92
+
93
+ def _strings(value: JsonValue) -> Iterator[str]:
94
+ if isinstance(value, str):
95
+ yield value
96
+ elif isinstance(value, list):
97
+ for item in value:
98
+ yield from _strings(item)
99
+ elif isinstance(value, dict):
100
+ for name, member in value.items():
101
+ yield name
102
+ yield from _strings(member)