metaobjects 0.19.0__tar.gz → 0.19.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (390) hide show
  1. {metaobjects-0.19.0 → metaobjects-0.19.2}/PKG-INFO +1 -1
  2. {metaobjects-0.19.0 → metaobjects-0.19.2}/pyproject.toml +1 -1
  3. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/generators/entity_model.py +99 -34
  4. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/spec_metamodel/field.json +1 -1
  5. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/spec_metamodel/validator.json +2 -2
  6. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/golden/extends/expected/Program.py +1 -1
  7. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/golden/nested-array/expected/AuthorBrief.py +9 -2
  8. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/golden/nested-array/expected/PostBrief.py +6 -0
  9. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/golden/scalars/expected/Metric.py +6 -0
  10. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/golden/scalars/expected/Report.py +10 -1
  11. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/golden/vanilla/expected/Subscriber.py +1 -1
  12. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_cli_staleness_nudge.py +4 -4
  13. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_entity_model.py +54 -2
  14. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_validation_conformance.py +15 -5
  15. {metaobjects-0.19.0 → metaobjects-0.19.2}/uv.lock +1 -1
  16. {metaobjects-0.19.0 → metaobjects-0.19.2}/.gitignore +0 -0
  17. {metaobjects-0.19.0 → metaobjects-0.19.2}/LICENSE +0 -0
  18. {metaobjects-0.19.0 → metaobjects-0.19.2}/README.md +0 -0
  19. {metaobjects-0.19.0 → metaobjects-0.19.2}/hatch_build.py +0 -0
  20. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/__init__.py +0 -0
  21. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/agent_context/__init__.py +0 -0
  22. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/agent_context/scaffold.py +0 -0
  23. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/apidocs/__init__.py +0 -0
  24. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/apidocs/api_model.py +0 -0
  25. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/apidocs/builder.py +0 -0
  26. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/apidocs/naming.py +0 -0
  27. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/apidocs/paths.py +0 -0
  28. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/apidocs/renderer.py +0 -0
  29. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/attr_class_map.py +0 -0
  30. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/cli.py +0 -0
  31. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/KNOWN_GAPS.md +0 -0
  32. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/__init__.py +0 -0
  33. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/config.py +0 -0
  34. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/constants.py +0 -0
  35. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/extract_delegate_emitter.py +0 -0
  36. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/extract_schema_emitter.py +0 -0
  37. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/format.py +0 -0
  38. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/fr010_field_mapping.py +0 -0
  39. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/generator.py +0 -0
  40. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/generator_registry.py +0 -0
  41. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/generators/__init__.py +0 -0
  42. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/generators/extractor_generator.py +0 -0
  43. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/generators/filter_allowlist_generator.py +0 -0
  44. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/generators/fr019_shared_enum.py +0 -0
  45. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/generators/m2m_codegen.py +0 -0
  46. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/generators/output_parser_generator.py +0 -0
  47. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/generators/output_prompt_generator.py +0 -0
  48. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/generators/payload_vo_generator.py +0 -0
  49. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/generators/render_helper_generator.py +0 -0
  50. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/generators/router_generator.py +0 -0
  51. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/generators/template_generator.py +0 -0
  52. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/generators/tph_plan.py +0 -0
  53. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/generators/trace_helper_generator.py +0 -0
  54. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/instance_artifacts.py +0 -0
  55. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/output_format_spec_emitter.py +0 -0
  56. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/overwrite_policy.py +0 -0
  57. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/runner.py +0 -0
  58. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/runtime/__init__.py +0 -0
  59. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/runtime/filter_parser.py +0 -0
  60. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/template_codegen/__init__.py +0 -0
  61. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/template_codegen/output_pattern.py +0 -0
  62. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/template_codegen/template_data.py +0 -0
  63. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/template_codegen/template_spec.py +0 -0
  64. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/codegen/type_map.py +0 -0
  65. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/core_types.py +0 -0
  66. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/datatype.py +0 -0
  67. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/documentation/__init__.py +0 -0
  68. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/documentation/doc_constants.py +0 -0
  69. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/documentation/doc_provider.py +0 -0
  70. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/documentation/doc_schema.py +0 -0
  71. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/errors.py +0 -0
  72. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/loader/__init__.py +0 -0
  73. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/loader/merge.py +0 -0
  74. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/loader/meta_data_loader.py +0 -0
  75. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/loader/registered_validation.py +0 -0
  76. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/loader/sources/__init__.py +0 -0
  77. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/loader/sources/directory_source.py +0 -0
  78. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/loader/sources/file_source.py +0 -0
  79. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/loader/sources/meta_data_source.py +0 -0
  80. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/loader/sources/uri_source.py +0 -0
  81. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/loader/validate_discriminator.py +0 -0
  82. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/loader/validate_field_readonly.py +0 -0
  83. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/loader/validate_source_escapes.py +0 -0
  84. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/loader/validate_source_parameter_ref.py +0 -0
  85. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/loader/validate_source_physical_names.py +0 -0
  86. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/loader/validation_passes.py +0 -0
  87. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/__init__.py +0 -0
  88. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/__init__.py +0 -0
  89. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/attr/__init__.py +0 -0
  90. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/attr/attr_constants.py +0 -0
  91. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/attr/meta_attr.py +0 -0
  92. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/field/__init__.py +0 -0
  93. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/field/field_constants.py +0 -0
  94. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/field/meta_field.py +0 -0
  95. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/identity/__init__.py +0 -0
  96. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/identity/identity_constants.py +0 -0
  97. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/identity/meta_identity.py +0 -0
  98. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/index/__init__.py +0 -0
  99. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/index/index_constants.py +0 -0
  100. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/index/meta_index.py +0 -0
  101. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/object/__init__.py +0 -0
  102. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/object/meta_object.py +0 -0
  103. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/object/meta_object_aware.py +0 -0
  104. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/object/object_class_registry.py +0 -0
  105. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/object/object_constants.py +0 -0
  106. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/object/object_extract.py +0 -0
  107. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/object/value_object.py +0 -0
  108. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/relationship/__init__.py +0 -0
  109. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/relationship/derive_m2m_fields.py +0 -0
  110. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/relationship/meta_relationship.py +0 -0
  111. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/relationship/relationship_constants.py +0 -0
  112. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/validator/__init__.py +0 -0
  113. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/core/validator/validator_constants.py +0 -0
  114. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/meta_data.py +0 -0
  115. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/meta_root.py +0 -0
  116. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/persistence/__init__.py +0 -0
  117. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/persistence/db/__init__.py +0 -0
  118. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/persistence/db/db_constants.py +0 -0
  119. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/persistence/db/db_provider.py +0 -0
  120. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/persistence/origin/__init__.py +0 -0
  121. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/persistence/origin/meta_origin.py +0 -0
  122. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/persistence/origin/origin_constants.py +0 -0
  123. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/persistence/source/__init__.py +0 -0
  124. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/persistence/source/meta_source.py +0 -0
  125. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/persistence/source/source_constants.py +0 -0
  126. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/presentation/__init__.py +0 -0
  127. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/presentation/layout/__init__.py +0 -0
  128. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/presentation/layout/layout_constants.py +0 -0
  129. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/presentation/layout/meta_layout.py +0 -0
  130. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/presentation/ui/__init__.py +0 -0
  131. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/presentation/ui/ui_provider.py +0 -0
  132. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/presentation/view/__init__.py +0 -0
  133. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/presentation/view/meta_view.py +0 -0
  134. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/presentation/view/view_constants.py +0 -0
  135. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/provider_extends.py +0 -0
  136. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/template/__init__.py +0 -0
  137. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/template/meta_template.py +0 -0
  138. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/template/prompt_provider.py +0 -0
  139. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/meta/template/template_constants.py +0 -0
  140. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/naming_refs.py +0 -0
  141. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/parser.py +0 -0
  142. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/parser_yaml.py +0 -0
  143. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/provider.py +0 -0
  144. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/py.typed +0 -0
  145. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/registry.py +0 -0
  146. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/registry_manifest.py +0 -0
  147. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/__init__.py +0 -0
  148. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/email_document.py +0 -0
  149. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/escapers.py +0 -0
  150. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/extract/KNOWN_GAPS.md +0 -0
  151. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/extract/__init__.py +0 -0
  152. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/extract/coerce.py +0 -0
  153. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/extract/extract.py +0 -0
  154. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/extract/extract_map.py +0 -0
  155. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/extract/json_forgiving_reader.py +0 -0
  156. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/extract/locate.py +0 -0
  157. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/extract/normalize.py +0 -0
  158. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/extract/strip.py +0 -0
  159. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/extract/types.py +0 -0
  160. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/extract/xml_forgiving_reader.py +0 -0
  161. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/filesystem_provider.py +0 -0
  162. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/prompt/__init__.py +0 -0
  163. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/prompt/output_format_renderer.py +0 -0
  164. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/prompt/output_format_spec.py +0 -0
  165. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/prompt/prompt_field.py +0 -0
  166. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/prompt/prompt_overrides.py +0 -0
  167. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/prompt/prompt_style.py +0 -0
  168. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/renderer.py +0 -0
  169. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/render/verify.py +0 -0
  170. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/runtime/__init__.py +0 -0
  171. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/runtime/llm_recorder.py +0 -0
  172. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/runtime/n2m_resolver.py +0 -0
  173. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/runtime/object_manager.py +0 -0
  174. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/runtime/tph.py +0 -0
  175. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/serializer_json.py +0 -0
  176. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/shared/__init__.py +0 -0
  177. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/shared/base_types.py +0 -0
  178. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/shared/separators.py +0 -0
  179. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/shared/structural.py +0 -0
  180. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/source/__init__.py +0 -0
  181. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/source/error_source.py +0 -0
  182. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/source/json_path.py +0 -0
  183. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/source/semantic_diff.py +0 -0
  184. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/source/yaml_positions.py +0 -0
  185. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/spec_metamodel/__init__.py +0 -0
  186. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/spec_metamodel/attr.json +0 -0
  187. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/spec_metamodel/db.json +0 -0
  188. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/spec_metamodel/documentation.json +0 -0
  189. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/spec_metamodel/identity.json +0 -0
  190. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/spec_metamodel/index.json +0 -0
  191. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/spec_metamodel/layout.json +0 -0
  192. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/spec_metamodel/object.json +0 -0
  193. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/spec_metamodel/origin.json +0 -0
  194. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/spec_metamodel/prompt.json +0 -0
  195. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/spec_metamodel/relationship.json +0 -0
  196. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/spec_metamodel/source.json +0 -0
  197. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/spec_metamodel/template.json +0 -0
  198. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/spec_metamodel/ui-web.json +0 -0
  199. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/spec_metamodel/ui.json +0 -0
  200. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/spec_metamodel/view.json +0 -0
  201. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/super_resolve.py +0 -0
  202. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/validation_types.py +0 -0
  203. {metaobjects-0.19.0 → metaobjects-0.19.2}/src/metaobjects/yaml_desugar.py +0 -0
  204. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/__init__.py +0 -0
  205. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/__init__.py +0 -0
  206. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/golden/extends/expected/BaseEntity.py +0 -0
  207. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/golden/extends/meta.json +0 -0
  208. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/golden/nested-array/meta.json +0 -0
  209. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/golden/scalars/meta.json +0 -0
  210. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/golden/vanilla/meta.json +0 -0
  211. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_abstract_conformance.py +0 -0
  212. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_api_docs_builder.py +0 -0
  213. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_api_docs_paths.py +0 -0
  214. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_cli.py +0 -0
  215. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_cli_providers.py +0 -0
  216. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_cli_registry.py +0 -0
  217. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_cli_verify_strict.py +0 -0
  218. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_cli_verify_subverbs.py +0 -0
  219. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_constants_config.py +0 -0
  220. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_enum_conformance.py +0 -0
  221. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_extends_abstract_field_inheritance.py +0 -0
  222. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_extractor_generator.py +0 -0
  223. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_filter_allowlist_generator.py +0 -0
  224. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_format.py +0 -0
  225. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_fr010_nested_object_prompt.py +0 -0
  226. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_fr010_output_codegen.py +0 -0
  227. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_fr019_shared_provided_conformance.py +0 -0
  228. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_generator.py +0 -0
  229. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_generator_extension_seams.py +0 -0
  230. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_golden.py +0 -0
  231. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_inherit_without_restate_gate.py +0 -0
  232. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_inheritance_conformance.py +0 -0
  233. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_instance_artifacts.py +0 -0
  234. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_m2m_codegen.py +0 -0
  235. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_origin_nullability.py +0 -0
  236. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_output_parser_generator.py +0 -0
  237. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_overwrite_policy.py +0 -0
  238. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_payload_vo_generator.py +0 -0
  239. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_projection_compile.py +0 -0
  240. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_render_helper_conformance.py +0 -0
  241. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_render_helper_generator.py +0 -0
  242. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_reverse_finders.py +0 -0
  243. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_router_generator.py +0 -0
  244. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_runner.py +0 -0
  245. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_template_data.py +0 -0
  246. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_template_generator.py +0 -0
  247. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_template_output_pattern.py +0 -0
  248. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_template_scope_helpers.py +0 -0
  249. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_template_scope_walk.py +0 -0
  250. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_template_spec.py +0 -0
  251. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_tph_codegen.py +0 -0
  252. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_trace_helper_generator.py +0 -0
  253. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_type_map.py +0 -0
  254. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/codegen/test_write_through.py +0 -0
  255. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/__init__.py +0 -0
  256. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/capabilities.py +0 -0
  257. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/conformance-expected-failures.json +0 -0
  258. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/conformance_adapter.py +0 -0
  259. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/corpus.py +0 -0
  260. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/expected_failures.py +0 -0
  261. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/fixture_discovery.py +0 -0
  262. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/navigator.py +0 -0
  263. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/test_api_docs_cross_port_conformance.py +0 -0
  264. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/test_conformance.py +0 -0
  265. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/test_extract_conformance.py +0 -0
  266. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/test_extract_object_verdict.py +0 -0
  267. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/test_fr010_loader_attrs.py +0 -0
  268. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/test_fr011_attrs.py +0 -0
  269. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/test_generator_registry_conformance.py +0 -0
  270. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/test_object_model_conformance.py +0 -0
  271. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/test_provider_composition_conformance.py +0 -0
  272. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/test_registry_conformance.py +0 -0
  273. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/test_runner_hardfail.py +0 -0
  274. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/test_spec_metamodel_embed.py +0 -0
  275. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/test_strict_attr_load.py +0 -0
  276. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/test_template_codegen_conformance.py +0 -0
  277. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/test_template_generator_conformance.py +0 -0
  278. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/test_yaml_conformance.py +0 -0
  279. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/conformance/yaml-conformance-expected-failures.json +0 -0
  280. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/__init__.py +0 -0
  281. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/api_contract_assertions.py +0 -0
  282. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/api_contract_jsonb_server.py +0 -0
  283. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/api_contract_m2m_server.py +0 -0
  284. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/api_contract_server.py +0 -0
  285. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/generated_jsonb_app.py +0 -0
  286. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/generated_m2m_app.py +0 -0
  287. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/generated_router_app.py +0 -0
  288. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/generated_tph_app.py +0 -0
  289. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/meta_ai_trace.yaml +0 -0
  290. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/normalization.py +0 -0
  291. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/postgres_container.py +0 -0
  292. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/query_runner.py +0 -0
  293. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/scenarios.py +0 -0
  294. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/test_api_contract.py +0 -0
  295. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/test_api_contract_generated.py +0 -0
  296. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/test_api_contract_jsonb.py +0 -0
  297. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/test_api_contract_m2m.py +0 -0
  298. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/test_api_contract_m2m_generated.py +0 -0
  299. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/test_api_contract_tph_generated.py +0 -0
  300. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/test_generated_router_uuid_pk.py +0 -0
  301. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/test_llm_call_trace.py +0 -0
  302. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/test_normalization.py +0 -0
  303. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/test_query_scenarios.py +0 -0
  304. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/integration/test_runtime_return_types.py +0 -0
  305. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/open_closed_proof_test.py +0 -0
  306. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/__init__.py +0 -0
  307. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/extract/__init__.py +0 -0
  308. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/extract/test_coerce.py +0 -0
  309. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/extract/test_extract.py +0 -0
  310. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/extract/test_extract_map.py +0 -0
  311. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/extract/test_json_forgiving_reader.py +0 -0
  312. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/extract/test_locate.py +0 -0
  313. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/extract/test_model.py +0 -0
  314. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/extract/test_normalize.py +0 -0
  315. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/extract/test_strip.py +0 -0
  316. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/extract/test_xml_forgiving_reader.py +0 -0
  317. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/prompt/__init__.py +0 -0
  318. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/prompt/test_output_format_renderer.py +0 -0
  319. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/test_email_document.py +0 -0
  320. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/test_filesystem_provider.py +0 -0
  321. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/test_output_format_renderer_nested.py +0 -0
  322. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/test_output_prompt_conformance.py +0 -0
  323. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/test_render_conformance.py +0 -0
  324. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/test_render_max_chars.py +0 -0
  325. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/test_verify.py +0 -0
  326. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/render/test_verify_conformance.py +0 -0
  327. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/source/__init__.py +0 -0
  328. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/source/test_fr5c_merge_attribution.py +0 -0
  329. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/source/test_fr5d_reference_resolution.py +0 -0
  330. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/source/test_fr5e_database_source_shape.py +0 -0
  331. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/source/test_json_path.py +0 -0
  332. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/source/test_semantic_diff.py +0 -0
  333. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/source/test_source_on_node.py +0 -0
  334. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/source/test_yaml_positions.py +0 -0
  335. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/test_api_docs_accuracy.py +0 -0
  336. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/__init__.py +0 -0
  337. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_agent_context_staleness.py +0 -0
  338. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_capabilities.py +0 -0
  339. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_common_attrs.py +0 -0
  340. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_core_types.py +0 -0
  341. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_effective_package.py +0 -0
  342. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_errors.py +0 -0
  343. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_field_enum.py +0 -0
  344. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_field_map_validation.py +0 -0
  345. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_field_uuid_dbcolumntype.py +0 -0
  346. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_fr016_source_name_and_kind_aliases.py +0 -0
  347. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_index_lookup.py +0 -0
  348. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_llm_recorder.py +0 -0
  349. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_loader.py +0 -0
  350. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_loader_bom.py +0 -0
  351. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_loader_class.py +0 -0
  352. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_merge.py +0 -0
  353. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_meta_attr.py +0 -0
  354. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_meta_data.py +0 -0
  355. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_meta_source.py +0 -0
  356. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_module_shortcuts.py +0 -0
  357. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_n2m_resolver.py +0 -0
  358. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_n2m_resolver_inherited.py +0 -0
  359. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_object_manager_autoset_stamping.py +0 -0
  360. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_object_manager_uuid_coercion.py +0 -0
  361. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_object_manager_write_through.py +0 -0
  362. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_one_primary_source.py +0 -0
  363. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_parser.py +0 -0
  364. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_parser_yaml.py +0 -0
  365. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_provider.py +0 -0
  366. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_provider_extension.py +0 -0
  367. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_registry.py +0 -0
  368. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_registry_completeness.py +0 -0
  369. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_registry_extend.py +0 -0
  370. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_registry_sealed.py +0 -0
  371. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_relationship_referential_actions.py +0 -0
  372. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_resolution_key.py +0 -0
  373. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_runtime_resolution_key_binding.py +0 -0
  374. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_serializer.py +0 -0
  375. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_shared_constants.py +0 -0
  376. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_smoke.py +0 -0
  377. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_source_escapes.py +0 -0
  378. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_sources.py +0 -0
  379. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_strict_child_placement.py +0 -0
  380. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_super_resolve.py +0 -0
  381. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_template_toolcall.py +0 -0
  382. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_template_wrong_subtype_attrs.py +0 -0
  383. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_validation_attr_schema.py +0 -0
  384. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_validation_filter_values.py +0 -0
  385. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_validation_origin_195.py +0 -0
  386. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_validation_origin_paths.py +0 -0
  387. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_validation_sort_field.py +0 -0
  388. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_validation_warnings.py +0 -0
  389. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_write_coercion_arrays.py +0 -0
  390. {metaobjects-0.19.0 → metaobjects-0.19.2}/tests/unit/test_yaml_desugar.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: metaobjects
3
- Version: 0.19.0
3
+ Version: 0.19.2
4
4
  Summary: Cross-language metadata standard: declare typed entities once, generate idiomatic drift-checked code across languages — Python port.
5
5
  Project-URL: Homepage, https://metaobjects.dev
6
6
  Project-URL: Repository, https://github.com/metaobjectsdev/metaobjects
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "metaobjects"
3
- version = "0.19.0"
3
+ version = "0.19.2"
4
4
  description = "Cross-language metadata standard: declare typed entities once, generate idiomatic drift-checked code across languages — Python port."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -5,7 +5,10 @@ import re
5
5
 
6
6
  from metaobjects.meta.core.field.meta_field import MetaField
7
7
  from metaobjects.meta.core.object.meta_object import MetaObject
8
- from metaobjects.meta.core.object.object_constants import OBJECT_SUBTYPE_ENTITY
8
+ from metaobjects.meta.core.object.object_constants import (
9
+ OBJECT_SUBTYPE_ENTITY,
10
+ OBJECT_SUBTYPE_VALUE,
11
+ )
9
12
  from metaobjects.meta.core.field import field_constants as fc
10
13
  from metaobjects.meta.core.identity.identity_constants import (
11
14
  GENERATION_INCREMENT,
@@ -96,7 +99,7 @@ def _first_attr(field: MetaField, sub_type: str, attr_name: str) -> object | Non
96
99
  return None
97
100
 
98
101
 
99
- def _validator_constraints(field: MetaField) -> dict[str, object]:
102
+ def _validator_constraints(field: MetaField, *, wire: bool) -> dict[str, object]:
100
103
  """Map the field's ``validator.*`` children + field attrs to Pydantic ``Field``
101
104
  kwargs. Cross-port-canonical semantics (TS is the reference):
102
105
 
@@ -104,6 +107,20 @@ def _validator_constraints(field: MetaField) -> dict[str, object]:
104
107
  - ``validator.numeric @min/@max`` -> ``ge=``/``le=`` (numeric value bounds)
105
108
  - ``validator.length @min`` + field ``@maxLength`` -> ``min_length=``/``max_length=``
106
109
  - ``validator.array @min/@max`` -> list ``min_length=``/``max_length=`` (element count)
110
+
111
+ *wire* gates FR-036 Pin 1 (#224): Pin 1 is a WIRE-TIER rule (it governs the
112
+ generated Create/Patch input-validation models a router binds against), never
113
+ an in-process one — an ``object.entity``/``object.value`` READ model applies
114
+ every OTHER constraint above unconditionally but must not self-validate Pin 1
115
+ at construction (that broke a downstream adopter's in-process prompt-payload
116
+ ``object.value`` models on legitimately-empty slots). Callers building a read
117
+ model (``_field_line``) pass ``wire=False``; callers building a wire model
118
+ (``_create_field_line``/``_patch_field_line``) pass ``wire=True``.
119
+
120
+ *wire* is keyword-only and REQUIRED (no default, item 5 of the #224
121
+ cleanup): a forgotten flag at a future wire call site must fail loudly
122
+ (``TypeError``) at generation time rather than silently falling back to a
123
+ permissive read-model tier.
107
124
  """
108
125
  kwargs: dict[str, object] = {}
109
126
 
@@ -158,16 +175,27 @@ def _validator_constraints(field: MetaField) -> dict[str, object]:
158
175
  if field.attrs().get(fc.FIELD_ATTR_STRING_FORMAT) == fc.STRING_FORMAT_HOSTNAME:
159
176
  kwargs["pattern"] = _HOSTNAME_REGEX
160
177
 
161
- # FR-036 Pin 1 — a @required non-array string is non-empty: reject null / "" but
162
- # ACCEPT whitespace-only. Emit an implicit min_length of 1, keeping the stricter
163
- # floor if a validator.length @min already set one.
178
+ # FR-036 Pin 1 (#224 WIRE TIER ONLY) — a @required non-array string is
179
+ # non-empty by default: reject null / "" but ACCEPT whitespace-only. Emit an
180
+ # implicit min_length of 1 ONLY when no validator.length @min was authored.
181
+ # Never applied to the in-process read model (wire=False).
182
+ #
183
+ # An explicitly authored @min is always AUTHORITATIVE over the implicit floor
184
+ # (ADR-0044 ruling on #224) — @min: 0 restores "must be provided, may be
185
+ # empty" by opting out of the non-empty floor entirely. Per the cross-port
186
+ # emission pin, an authored @min: 0 emits NO minimum constraint at all
187
+ # (cleanest, deterministic output across ports), so it is popped rather than
188
+ # kept as min_length=0.
164
189
  if (
165
- field.sub_type == fc.FIELD_SUBTYPE_STRING
190
+ wire
191
+ and field.sub_type == fc.FIELD_SUBTYPE_STRING
166
192
  and not field_is_array(field)
167
193
  and field.attrs().get(fc.FIELD_ATTR_REQUIRED) is True
168
194
  ):
169
- existing_min = kwargs.get("min_length")
170
- kwargs["min_length"] = max(1, existing_min) if isinstance(existing_min, int) else 1
195
+ if min_len is None:
196
+ kwargs["min_length"] = 1
197
+ elif min_len == 0:
198
+ kwargs.pop("min_length", None)
171
199
 
172
200
  return kwargs
173
201
 
@@ -182,7 +210,7 @@ def _constraint_parts(constraints: dict[str, object]) -> list[str]:
182
210
 
183
211
 
184
212
  def _type_expr_for_field(
185
- field: MetaField, imports: set[str], config: GenConfig
213
+ field: MetaField, imports: set[str], config: GenConfig, *, wire: bool
186
214
  ) -> tuple[str, str | None]:
187
215
  """The Python annotation text for *field* (arrays wrapped in ``list[...]``) plus the
188
216
  shared-enum class name when the field resolves to one (used to render an enum
@@ -191,7 +219,16 @@ def _type_expr_for_field(
191
219
 
192
220
  FR-019: a field resolving to a package-level shared enum is typed by the materialized
193
221
  standalone class (imported from the shared ``enums`` module) or — when @provided — an
194
- external module; inline enums keep their ``Literal[...]`` (py_type_for)."""
222
+ external module; inline enums keep their ``Literal[...]`` (py_type_for).
223
+
224
+ *wire* (#224): in a wire context (create/patch), a ``field.object``/``field.map``
225
+ ``@objectRef`` annotates with the referenced VO's own WIRE model (``<Ref>Create``)
226
+ rather than its read model, so a required-string Pin 1 violation nested inside the
227
+ VO still validates on the wire (api-contract jsonb r10). A VO's own Create lines
228
+ are emitted through this same wire path, so nested-VO-in-VO recurses naturally.
229
+
230
+ *wire* is keyword-only and REQUIRED (no default, item 5 of the #224 cleanup)
231
+ — see ``_validator_constraints`` for the rationale."""
195
232
  shared = (
196
233
  fr019.shared_enum_for_field(field)
197
234
  if field.sub_type == fc.FIELD_SUBTYPE_ENUM
@@ -220,11 +257,20 @@ def _type_expr_for_field(
220
257
  # A field.object (-> VO) and a field.map with @objectRef (-> dict[str, VO]) both
221
258
  # reference a value-object by name; import it so the emitted annotation resolves.
222
259
  # @objectRef is FQN-expanded at load; the generated VOs live flat in one package,
223
- # so import by the bare class name.
260
+ # so import by the bare class name. #224 — a WIRE context binds the referenced
261
+ # VO's <Ref>Create instead (see docstring above).
224
262
  ref = field.attrs().get(fc.FIELD_ATTR_OBJECT_REF)
225
263
  if ref:
226
264
  ref_name = str(ref).split("::")[-1]
227
- imports.add(f"from .{ref_name} import {ref_name}")
265
+ bound_name = f"{ref_name}Create" if wire else ref_name
266
+ imports.add(f"from .{ref_name} import {bound_name}")
267
+ if wire:
268
+ if field.sub_type == fc.FIELD_SUBTYPE_MAP:
269
+ type_expr = f"dict[str, {bound_name}]"
270
+ elif field_is_array(field):
271
+ type_expr = f"list[{bound_name}]"
272
+ else:
273
+ type_expr = bound_name
228
274
  return type_expr, enum_type_name
229
275
 
230
276
 
@@ -246,7 +292,7 @@ def origin_guaranteed_non_null(field: MetaField) -> bool:
246
292
 
247
293
  def _field_line(field: MetaField, imports: set[str], config: GenConfig) -> tuple[str, bool]:
248
294
  """Return (source line, uses_field). Collects required imports into *imports*."""
249
- type_expr, enum_type_name = _type_expr_for_field(field, imports, config)
295
+ type_expr, enum_type_name = _type_expr_for_field(field, imports, config, wire=False)
250
296
  required = field.attrs().get(fc.FIELD_ATTR_REQUIRED) is True
251
297
  default_raw = field.attrs().get(fc.FIELD_ATTR_DEFAULT)
252
298
  # A server-side expression default (now(), gen_random_uuid(), CURRENT_TIMESTAMP)
@@ -254,7 +300,7 @@ def _field_line(field: MetaField, imports: set[str], config: GenConfig) -> tuple
254
300
  # its required/optional shape). Only literal defaults become Pydantic defaults.
255
301
  has_default = default_raw is not None and not _is_sql_expr_default(default_raw)
256
302
 
257
- parts = _constraint_parts(_validator_constraints(field))
303
+ parts = _constraint_parts(_validator_constraints(field, wire=False))
258
304
  uses_field = bool(parts)
259
305
 
260
306
  # @default — render an enum member (Type.MEMBER, UPPER_CASE) or a Python literal.
@@ -330,14 +376,18 @@ def _create_field_line(
330
376
  field: MetaField, imports: set[str], config: GenConfig
331
377
  ) -> tuple[str, bool]:
332
378
  """A CREATE-model field line (FR-036): keyed by the WIRE name (``field.name``) and
333
- carrying the same per-field constraints as the read model. A ``@required`` field
379
+ carrying the WIRE-TIER per-field constraints (#224 includes FR-036 Pin 1
380
+ non-empty-string; the read model does NOT carry Pin 1). A ``@required`` field
334
381
  that is SERVER-FILLED — it has ANY ``@default`` (a literal OR a SQL expression such
335
382
  as ``now()`` / ``gen_random_uuid()`` / ``CURRENT_TIMESTAMP``) or an ``@autoSet`` — is
336
383
  emitted OPTIONAL, because the DB / trigger provides it and a POST that omits it must
337
384
  not 400 (mirrors the TS InsertSchema ``fieldWillBeOptional``). A literal ``@default``
338
385
  is preserved as the Python default; a SQL-expression default / ``@autoSet`` carries
339
- no Python default (the server fills it). Returns (source line, uses_field)."""
340
- type_expr, enum_type_name = _type_expr_for_field(field, imports, config)
386
+ no Python default (the server fills it). Also used, unchanged, to emit an
387
+ ``object.value``'s own ``<Name>Create`` wire model (#224) the PK/TPH/derived-field
388
+ guards in the caller no-op for a VO carrying none of those. Returns (source line,
389
+ uses_field)."""
390
+ type_expr, enum_type_name = _type_expr_for_field(field, imports, config, wire=True)
341
391
  required = field.attrs().get(fc.FIELD_ATTR_REQUIRED) is True
342
392
  default_raw = field.attrs().get(fc.FIELD_ATTR_DEFAULT)
343
393
  literal_default = default_raw is not None and not _is_sql_expr_default(default_raw)
@@ -349,7 +399,7 @@ def _create_field_line(
349
399
  server_filled = default_raw is not None or is_auto_set
350
400
  create_required = required and not server_filled
351
401
 
352
- parts = _constraint_parts(_validator_constraints(field))
402
+ parts = _constraint_parts(_validator_constraints(field, wire=True))
353
403
  uses_field = bool(parts)
354
404
 
355
405
  py_name = field.name # FR-036 #3 — validation models key by the WIRE name (field.name)
@@ -383,12 +433,12 @@ def _patch_field_line(
383
433
  field: MetaField, imports: set[str], config: GenConfig
384
434
  ) -> tuple[str, bool]:
385
435
  """A PATCH-model field line: the field is made Optional (default ``None``) yet
386
- carries the SAME per-field constraints as the create model, so a present, non-null
387
- value is validated with the create rules (FR-036) while an absent field is left
388
- untouched. A ``@default`` is never emitted (a patch does not default a column).
389
- Returns (source line, uses_field)."""
390
- type_expr, _enum = _type_expr_for_field(field, imports, config)
391
- parts = _constraint_parts(_validator_constraints(field))
436
+ carries the SAME wire-tier per-field constraints as the create model (#224), so a
437
+ present, non-null value is validated with the create rules (FR-036) while an
438
+ absent field is left untouched. A ``@default`` is never emitted (a patch does not
439
+ default a column). Returns (source line, uses_field)."""
440
+ type_expr, _enum = _type_expr_for_field(field, imports, config, wire=True)
441
+ parts = _constraint_parts(_validator_constraints(field, wire=True))
392
442
  py_name = field.name # FR-036 #3 — validation models key by the WIRE name (field.name)
393
443
  if parts:
394
444
  return f" {py_name}: {type_expr} | None = Field(default=None, {', '.join(parts)})", True
@@ -478,8 +528,10 @@ class EntityModelGenerator:
478
528
  ``@autoSet``; FR-036 #1) is made optional. Keyed by the wire name; a TPH
479
529
  subtype's discriminator is pinned to its ``Literal`` value (the route injects it
480
530
  from the URL, so it stays optional with a default). M:N navigations are omitted
481
- (a create body targets columns, not relations). Returns ``(lines, uses_field)``.
482
- Override to add/transform create-model lines."""
531
+ (a create body targets columns, not relations). Also used, unchanged, to emit an
532
+ ``object.value``'s own wire model (#224) — a VO has no PK/TPH/derived fields, so
533
+ those guards simply no-op. Returns ``(lines, uses_field)``. Override to
534
+ add/transform create-model lines."""
483
535
  cfg = config if config is not None else GenConfig(out_dir="")
484
536
  auto_gen_pk = _auto_gen_pk_field_names(entity)
485
537
  binding = tph_subtype_binding(entity)
@@ -576,27 +628,37 @@ class EntityModelGenerator:
576
628
  imports.add("from typing import Literal")
577
629
  body = lines if lines else [" pass"]
578
630
 
579
- # FR-036 — an object.entity also emits two flat validation models the generated
631
+ # FR-036 — an object.entity emits two flat WIRE-validation models the generated
580
632
  # router binds: a ``<Name>Create`` (POST-body shape: auto-gen PK / @readOnly
581
633
  # omitted, @default/@autoSet optional, other @required required) and an
582
634
  # all-optional ``<Name>Patch`` (PATCH-body shape: PK excluded). Both key by the
583
- # WIRE name and carry the field constraints, so present values are validated with
584
- # the create rules. Value objects / projections are never routed, so they emit
585
- # neither (only the read model). See findings #1–#4.
586
- emit_validation_models = entity.sub_type == OBJECT_SUBTYPE_ENTITY
635
+ # WIRE name and carry the wire-tier field constraints (#224 includes FR-036
636
+ # Pin 1), so present values are validated with the create rules.
637
+ #
638
+ # #224 — an object.value is reached OVER THE WIRE too: it nests into an entity's
639
+ # Create/Patch body via a field.object/field.map ``@objectRef`` (see
640
+ # ``_type_expr_for_field``'s wire mode), so it also emits its own ``<Name>Create``
641
+ # wire model — Create only, since a nested VO is whole-value replace on both POST
642
+ # and PATCH (the same reason TS embeds one ``<Ref>InsertSchema`` in both Insert
643
+ # and Update schemas; no separate VO ``Patch`` shape exists). A ``<Name>Patch`` is
644
+ # entity-only (PK exclusion + partial-update semantics are entity-specific).
645
+ # object.projection is read-only and never routed — it emits neither.
646
+ emit_create = entity.sub_type in (OBJECT_SUBTYPE_ENTITY, OBJECT_SUBTYPE_VALUE)
647
+ emit_patch = entity.sub_type == OBJECT_SUBTYPE_ENTITY
587
648
  create_lines: list[str] = []
588
649
  create_uses_field = False
589
650
  patch_lines: list[str] = []
590
651
  patch_uses_field = False
591
- if emit_validation_models:
652
+ if emit_create:
592
653
  create_lines, create_uses_field = self._emit_create_lines(entity, imports, config)
654
+ if emit_patch:
593
655
  patch_lines, patch_uses_field = self._emit_patch_lines(entity, imports, config)
594
656
 
595
657
  # Import only the pydantic names actually referenced. The main model imports
596
658
  # BaseModel only when it has no super, but the flat Create/Patch models always
597
659
  # subclass BaseModel, so their presence forces the import regardless.
598
660
  pyd_names: list[str] = []
599
- if entity.super_data is None or emit_validation_models:
661
+ if entity.super_data is None or emit_create or emit_patch:
600
662
  pyd_names.append("BaseModel")
601
663
  if uses_field or create_uses_field or patch_uses_field:
602
664
  pyd_names.append("Field")
@@ -612,7 +674,7 @@ class EntityModelGenerator:
612
674
  if pyd_names:
613
675
  parts += [f"from pydantic import {', '.join(pyd_names)}", ""]
614
676
  parts += ["", self._emit_class_header(entity, base_class), *body]
615
- if emit_validation_models:
677
+ if emit_create:
616
678
  parts += [
617
679
  "",
618
680
  "",
@@ -620,6 +682,9 @@ class EntityModelGenerator:
620
682
  ' """GENERATED — CREATE input: auto-gen PK / @readOnly omitted; '
621
683
  '@default/@autoSet optional; present values validated (FR-036)."""',
622
684
  *create_lines,
685
+ ]
686
+ if emit_patch:
687
+ parts += [
623
688
  "",
624
689
  "",
625
690
  f"class {entity.name}Patch(BaseModel):",
@@ -10,7 +10,7 @@
10
10
  { "type": "validator", "subType": "*", "name": "*", "min": 0, "max": null },
11
11
  { "type": "view", "subType": "*", "name": "*", "min": 0, "max": null },
12
12
  { "type": "origin", "subType": "*", "name": "*", "min": 0, "max": null },
13
- { "type": "attr", "subType": "boolean", "name": "required", "min": 0, "max": 1, "description": "When true, the field is NOT NULL. Equivalent to attaching a validator.required child." },
13
+ { "type": "attr", "subType": "boolean", "name": "required", "min": 0, "max": 1, "description": "When true, the field is NOT NULL. Equivalent to attaching a validator.required child. On a non-array string, generated wire-tier input validation (create/patch) additionally rejects the empty string by default — whitespace is accepted — unless an explicit validator.length @min: 0 opts back to presence-only. In-process read models never enforce this at construction." },
14
14
  { "type": "attr", "subType": "boolean", "name": "readOnly", "min": 0, "max": 1, "description": "FR-013: when true, the field is read-only — codegen emits no setter / writable property, the persistence layer skips the column on INSERT/UPDATE, and Zod/Pydantic/class-validator schemas mark it read-only on input variants. The value is populated by the database (computed column, default expression, trigger), by replication, or by another external owner." },
15
15
  { "type": "attr", "name": "default", "min": 0, "max": 1, "description": "Default value applied to the column when no value is supplied. Its type follows the field's own subtype (string / boolean / number / ...). Converted at consumption time via MetaField.defaultValue()." },
16
16
  { "type": "attr", "subType": "boolean", "name": "unique", "min": 0, "max": 1, "description": "When true, the field gets a column-level UNIQUE constraint." }
@@ -13,8 +13,8 @@
13
13
  {
14
14
  "type": "validator",
15
15
  "subType": "required",
16
- "description": "Fails when the value is null/empty (NOT NULL). Equivalent to @required on the owning field.",
17
- "whenToUse": "A field must be present (NOT NULL). Declare it instead of hand-writing a null/empty check."
16
+ "description": "Fails when the value is null (NOT NULL). Equivalent to @required on the owning field: on a non-array string, generated wire-tier input validation also rejects the empty string by default unless an explicit validator.length @min: 0 opts back to presence-only.",
17
+ "whenToUse": "A field must be present (NOT NULL). Declare it instead of hand-writing a presence check."
18
18
  },
19
19
  {
20
20
  "type": "validator",
@@ -10,7 +10,7 @@ from .BaseEntity import BaseEntity
10
10
 
11
11
 
12
12
  class Program(BaseEntity):
13
- name: str = Field(min_length=1)
13
+ name: str
14
14
 
15
15
 
16
16
  class ProgramCreate(BaseModel):
@@ -6,9 +6,16 @@ from __future__ import annotations
6
6
 
7
7
  from pydantic import BaseModel, Field
8
8
 
9
- from .PostBrief import PostBrief
9
+ from .PostBrief import PostBrief, PostBriefCreate
10
10
 
11
11
 
12
12
  class AuthorBrief(BaseModel):
13
- displayName: str = Field(min_length=1)
13
+ displayName: str
14
14
  posts: list[PostBrief] | None = None
15
+
16
+
17
+ class AuthorBriefCreate(BaseModel):
18
+ """GENERATED — CREATE input: auto-gen PK / @readOnly omitted; @default/@autoSet optional; present values validated (FR-036)."""
19
+
20
+ displayName: str = Field(min_length=1)
21
+ posts: list[PostBriefCreate] | None = None
@@ -9,3 +9,9 @@ from pydantic import BaseModel
9
9
 
10
10
  class PostBrief(BaseModel):
11
11
  title: str | None = None
12
+
13
+
14
+ class PostBriefCreate(BaseModel):
15
+ """GENERATED — CREATE input: auto-gen PK / @readOnly omitted; @default/@autoSet optional; present values validated (FR-036)."""
16
+
17
+ title: str | None = None
@@ -9,3 +9,9 @@ from pydantic import BaseModel
9
9
 
10
10
  class Metric(BaseModel):
11
11
  label: str | None = None
12
+
13
+
14
+ class MetricCreate(BaseModel):
15
+ """GENERATED — CREATE input: auto-gen PK / @readOnly omitted; @default/@autoSet optional; present values validated (FR-036)."""
16
+
17
+ label: str | None = None
@@ -9,7 +9,7 @@ from decimal import Decimal
9
9
 
10
10
  from pydantic import BaseModel
11
11
 
12
- from .Metric import Metric
12
+ from .Metric import Metric, MetricCreate
13
13
 
14
14
 
15
15
  class Report(BaseModel):
@@ -17,3 +17,12 @@ class Report(BaseModel):
17
17
  total: Decimal
18
18
  revenue: int
19
19
  metrics: list[Metric] | None = None
20
+
21
+
22
+ class ReportCreate(BaseModel):
23
+ """GENERATED — CREATE input: auto-gen PK / @readOnly omitted; @default/@autoSet optional; present values validated (FR-036)."""
24
+
25
+ generatedAt: datetime.datetime
26
+ total: Decimal
27
+ revenue: int
28
+ metrics: list[MetricCreate] | None = None
@@ -8,7 +8,7 @@ from pydantic import BaseModel, Field
8
8
 
9
9
 
10
10
  class Subscriber(BaseModel):
11
- email: str = Field(min_length=1, max_length=200)
11
+ email: str = Field(max_length=200)
12
12
  subscribed: bool | None = None
13
13
 
14
14
 
@@ -47,7 +47,7 @@ def test_gen_nudges_on_stale_manifest(tmp_path, capsys, monkeypatch) -> None:
47
47
  assert rc == 0 # advisory: never changes the exit code
48
48
  err = capsys.readouterr().err
49
49
  assert "0.0.1-old" in err
50
- assert "metaobjects agent-docs" in err
50
+ assert "npx meta agent-docs" in err
51
51
 
52
52
 
53
53
  def test_verify_nudges_on_stale_manifest(tmp_path, capsys, monkeypatch) -> None:
@@ -65,7 +65,7 @@ def test_verify_nudges_on_stale_manifest(tmp_path, capsys, monkeypatch) -> None:
65
65
  assert rc == 0
66
66
  err = capsys.readouterr().err
67
67
  assert "0.0.1-old" in err
68
- assert "metaobjects agent-docs" in err
68
+ assert "npx meta agent-docs" in err
69
69
 
70
70
 
71
71
  def test_gen_silent_when_no_manifest(tmp_path, capsys, monkeypatch) -> None:
@@ -76,7 +76,7 @@ def test_gen_silent_when_no_manifest(tmp_path, capsys, monkeypatch) -> None:
76
76
  rc = main(["gen", meta_dir, "--out", str(out)])
77
77
  assert rc == 0
78
78
  err = capsys.readouterr().err
79
- assert "metaobjects agent-docs" not in err
79
+ assert "npx meta agent-docs" not in err
80
80
 
81
81
 
82
82
  def test_gen_silent_on_corrupt_manifest(tmp_path, capsys, monkeypatch) -> None:
@@ -90,4 +90,4 @@ def test_gen_silent_on_corrupt_manifest(tmp_path, capsys, monkeypatch) -> None:
90
90
  rc = main(["gen", meta_dir, "--out", str(out)])
91
91
  assert rc == 0
92
92
  err = capsys.readouterr().err
93
- assert "metaobjects agent-docs" not in err
93
+ assert "npx meta agent-docs" not in err
@@ -32,6 +32,14 @@ def _entity(
32
32
  return o
33
33
 
34
34
 
35
+ def _value(name: str, fields: list[MetaField], *, package: str | None = None) -> MetaObject:
36
+ o = MetaObject(TYPE_OBJECT, "value", name)
37
+ o.package = package
38
+ for f in fields:
39
+ o.add_child(f)
40
+ return o
41
+
42
+
35
43
  def _f(
36
44
  name: str,
37
45
  sub: str,
@@ -85,9 +93,14 @@ def test_vanilla_entity_model() -> None:
85
93
  assert "@generated by metaobjects" in out
86
94
  assert "from pydantic import BaseModel, Field" in out
87
95
  assert "class Subscriber(BaseModel):" in out
88
- # FR-036 Pin 1: a @required string carries an implicit min_length=1 (non-empty).
96
+ # #224 — FR-036 Pin 1 (implicit min_length=1 on a @required string) is WIRE-TIER
97
+ # ONLY: the READ model carries no implicit floor (other constraints, like
98
+ # @maxLength, still apply); the WIRE model (SubscriberCreate) keeps Pin 1.
99
+ read_model = out.split("class SubscriberCreate")[0]
100
+ assert "email: str = Field(max_length=200)" in read_model
101
+ assert "min_length" not in read_model
102
+ assert "subscribed: bool | None = None" in read_model
89
103
  assert "email: str = Field(min_length=1, max_length=200)" in out
90
- assert "subscribed: bool | None = None" in out
91
104
 
92
105
 
93
106
  def test_extends_subclasses_base_and_imports_it() -> None:
@@ -308,3 +321,42 @@ def test_patch_model_excludes_primary_key() -> None:
308
321
 
309
322
  assert "id" not in mod.ArticlePatch.model_fields
310
323
  assert "name" in mod.ArticlePatch.model_fields
324
+
325
+
326
+ # --------------------------------------------------------------------------- #
327
+ # #224 — FR-036 Pin 1 (@required non-array string ⇒ non-empty) is a WIRE-TIER
328
+ # rule, not an in-process one. A downstream adopter's in-process prompt-payload
329
+ # object.value models broke on legitimately-empty slots because the read model
330
+ # self-validated at construction. The fix scopes Pin 1 to the wire (Create/Patch)
331
+ # models; the in-process read model (entity OR value) carries no implicit floor,
332
+ # and a nested object.value keeps wire-tier enforcement via its own <Name>Create.
333
+ # --------------------------------------------------------------------------- #
334
+
335
+
336
+ def test_value_object_required_string_accepts_empty_in_process() -> None:
337
+ """The adopter's exact repro: an in-process object.value with a @required
338
+ string must construct cleanly with "" — Pin 1 does not apply in-process."""
339
+ e = _value("Slots", [_f("goal", fc.FIELD_SUBTYPE_STRING, required=True)])
340
+ mod = _load_models(e)
341
+ assert mod.Slots(goal="").goal == ""
342
+
343
+
344
+ def test_value_object_wire_create_model_still_rejects_empty_required_string() -> None:
345
+ """Tier separation, direction 2 — the VO's own WIRE model (<Name>Create) keeps
346
+ Pin 1: a required string still rejects "" there, so nesting a VO into an
347
+ entity's wire body (api-contract jsonb r10) stays enforced."""
348
+ e = _value("Slots", [_f("goal", fc.FIELD_SUBTYPE_STRING, required=True)])
349
+ mod = _load_models(e)
350
+ with pytest.raises(ValidationError):
351
+ mod.SlotsCreate(goal="")
352
+
353
+
354
+ def test_entity_read_model_no_longer_carries_implicit_min_length() -> None:
355
+ """Issue §4 (same fix, zero marginal cost) — the ENTITY read model also loses
356
+ the implicit min_length=1: reading an existing row with "" must not throw.
357
+ The entity's wire Create model still enforces it (proven elsewhere)."""
358
+ e = _entity("Widget", [_f("name", fc.FIELD_SUBTYPE_STRING, required=True)], package="app::w")
359
+ mod = _load_models(e)
360
+ assert mod.Widget(name="").name == ""
361
+ with pytest.raises(ValidationError):
362
+ mod.WidgetCreate(name="")
@@ -1,10 +1,17 @@
1
1
  """SP-C validation-conformance runner (Python port).
2
2
 
3
- Loads the shared corpus, generates the ``Account`` Pydantic model via the
4
- entity-model generator, execs the generated source into a live module, then
5
- constructs the model from each corpus payload. Construct OK -> valid; a
3
+ Loads the shared corpus, generates the ``AccountCreate`` Pydantic model (the
4
+ generated input-validation artifact mirrors the TS runner, which asserts
5
+ against ``AccountInsertSchema``, not the plain read model) via the entity-model
6
+ generator, execs the generated source into a live module, then constructs the
7
+ model from each corpus payload. Construct OK -> valid; a
6
8
  ``pydantic.ValidationError`` -> invalid. Asserts the single-source ``expectValid``
7
9
  boolean verdicts (canonical across all 5 ports).
10
+
11
+ #224 — the runner builds ``AccountCreate``, not the plain ``Account`` read model:
12
+ FR-036 Pin 1 (required non-array string ⇒ non-empty) is scoped to the WIRE tier
13
+ (the input-validation artifact a router binds against), not the in-process read
14
+ model, so asserting against the read model would no longer exercise Pin 1 at all.
8
15
  """
9
16
  from __future__ import annotations
10
17
 
@@ -40,11 +47,14 @@ def _load_account_entity() -> MetaObject:
40
47
 
41
48
 
42
49
  def _build_generated_model() -> type[BaseModel]:
43
- """Generate the Account Pydantic model source and exec it into a module namespace."""
50
+ """Generate the Account Pydantic wire-validation model source and exec it into a
51
+ module namespace. #224 — ``AccountCreate`` (the generated input-validation
52
+ artifact), not the plain ``Account`` read model: FR-036 Pin 1 lives on the wire
53
+ tier only."""
44
54
  source = render_entity_model(_load_account_entity())
45
55
  namespace: dict[str, object] = {}
46
56
  exec(compile(source, "<generated Account.py>", "exec"), namespace) # noqa: S102
47
- model = namespace["Account"]
57
+ model = namespace["AccountCreate"]
48
58
  assert isinstance(model, type) and issubclass(model, BaseModel)
49
59
  return model
50
60
 
@@ -250,7 +250,7 @@ wheels = [
250
250
 
251
251
  [[package]]
252
252
  name = "metaobjects"
253
- version = "0.15.12"
253
+ version = "0.19.1"
254
254
  source = { editable = "." }
255
255
  dependencies = [
256
256
  { name = "pyyaml" },
File without changes
File without changes
File without changes