metaobjects 1.0.5rc10__tar.gz → 1.0.7__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 (472) hide show
  1. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/PKG-INFO +3 -2
  2. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/README.md +2 -1
  3. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/pyproject.toml +1 -1
  4. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/cli.py +55 -4
  5. metaobjects-1.0.7/src/metaobjects/codegen/eject.py +168 -0
  6. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/generator_registry.py +30 -1
  7. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/generators/router_generator.py +35 -3
  8. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/runner.py +15 -1
  9. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/extract/extract.py +29 -2
  10. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/extract/locate.py +24 -1
  11. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/extract/strip.py +8 -0
  12. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/extract/xml_forgiving_reader.py +62 -6
  13. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_cli_registry.py +3 -0
  14. metaobjects-1.0.7/tests/codegen/test_eject.py +145 -0
  15. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_gen_state_keying.py +34 -0
  16. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/test_extract_conformance.py +2 -2
  17. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/uv.lock +1 -1
  18. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/.gitignore +0 -0
  19. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/LICENSE +0 -0
  20. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/hatch_build.py +0 -0
  21. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/scripts/generate_embedded_library.py +0 -0
  22. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/__init__.py +0 -0
  23. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/agent_context/__init__.py +0 -0
  24. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/agent_context/scaffold.py +0 -0
  25. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/apidocs/__init__.py +0 -0
  26. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/apidocs/api_model.py +0 -0
  27. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/apidocs/builder.py +0 -0
  28. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/apidocs/naming.py +0 -0
  29. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/apidocs/paths.py +0 -0
  30. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/apidocs/renderer.py +0 -0
  31. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/attr_class_map.py +0 -0
  32. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/KNOWN_GAPS.md +0 -0
  33. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/__init__.py +0 -0
  34. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/collision_names.py +0 -0
  35. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/config.py +0 -0
  36. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/constants.py +0 -0
  37. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/extract_delegate_emitter.py +0 -0
  38. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/extract_schema_emitter.py +0 -0
  39. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/format.py +0 -0
  40. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/fr010_field_mapping.py +0 -0
  41. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/generator.py +0 -0
  42. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/generators/__init__.py +0 -0
  43. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/generators/entity_model.py +0 -0
  44. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/generators/extractor_generator.py +0 -0
  45. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/generators/filter_allowlist_generator.py +0 -0
  46. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/generators/find_inbound.py +0 -0
  47. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/generators/fr019_shared_enum.py +0 -0
  48. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/generators/m2m_codegen.py +0 -0
  49. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/generators/names_generator.py +0 -0
  50. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/generators/output_parser_generator.py +0 -0
  51. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/generators/output_prompt_generator.py +0 -0
  52. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/generators/render_helper_generator.py +0 -0
  53. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/generators/template_generator.py +0 -0
  54. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/generators/tph_plan.py +0 -0
  55. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/generators/trace_helper_generator.py +0 -0
  56. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/instance_artifacts.py +0 -0
  57. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/metaobjects-config.schema.json +0 -0
  58. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/output_format_spec_emitter.py +0 -0
  59. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/overwrite_policy.py +0 -0
  60. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/project_config.py +0 -0
  61. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/runtime/__init__.py +0 -0
  62. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/runtime/constraint_errors.py +0 -0
  63. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/runtime/filter_parser.py +0 -0
  64. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/template_codegen/__init__.py +0 -0
  65. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/template_codegen/output_pattern.py +0 -0
  66. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/template_codegen/template_data.py +0 -0
  67. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/template_codegen/template_spec.py +0 -0
  68. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/type_map.py +0 -0
  69. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/codegen/value_objects.py +0 -0
  70. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/config/__init__.py +0 -0
  71. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/config/dependencies.py +0 -0
  72. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/config/neutral_config.py +0 -0
  73. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/config/source_resolver.py +0 -0
  74. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/core_types.py +0 -0
  75. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/datatype.py +0 -0
  76. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/documentation/__init__.py +0 -0
  77. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/documentation/doc_constants.py +0 -0
  78. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/documentation/doc_provider.py +0 -0
  79. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/documentation/doc_schema.py +0 -0
  80. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/errors.py +0 -0
  81. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/library/__init__.py +0 -0
  82. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/library/embedded_library.py +0 -0
  83. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/library/library_sources.py +0 -0
  84. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/loader/__init__.py +0 -0
  85. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/loader/merge.py +0 -0
  86. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/loader/meta_data_loader.py +0 -0
  87. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/loader/registered_validation.py +0 -0
  88. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/loader/sources/__init__.py +0 -0
  89. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/loader/sources/directory_source.py +0 -0
  90. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/loader/sources/file_source.py +0 -0
  91. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/loader/sources/meta_data_source.py +0 -0
  92. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/loader/sources/uri_source.py +0 -0
  93. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/loader/validate_discriminator.py +0 -0
  94. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/loader/validate_enum_normalize_ambiguity.py +0 -0
  95. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/loader/validate_field_mutability.py +0 -0
  96. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/loader/validate_source_escapes.py +0 -0
  97. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/loader/validate_source_parameter_ref.py +0 -0
  98. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/loader/validate_source_physical_names.py +0 -0
  99. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/loader/validation_passes.py +0 -0
  100. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/__init__.py +0 -0
  101. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/__init__.py +0 -0
  102. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/attr/__init__.py +0 -0
  103. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/attr/attr_constants.py +0 -0
  104. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/attr/meta_attr.py +0 -0
  105. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/field/__init__.py +0 -0
  106. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/field/field_constants.py +0 -0
  107. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/field/meta_field.py +0 -0
  108. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/identity/__init__.py +0 -0
  109. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/identity/identity_constants.py +0 -0
  110. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/identity/meta_identity.py +0 -0
  111. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/index/__init__.py +0 -0
  112. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/index/index_constants.py +0 -0
  113. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/index/meta_index.py +0 -0
  114. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/object/__init__.py +0 -0
  115. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/object/meta_object.py +0 -0
  116. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/object/meta_object_aware.py +0 -0
  117. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/object/object_class_registry.py +0 -0
  118. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/object/object_constants.py +0 -0
  119. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/object/object_extract.py +0 -0
  120. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/object/value_object.py +0 -0
  121. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/relationship/__init__.py +0 -0
  122. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/relationship/derive_m2m_fields.py +0 -0
  123. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/relationship/meta_relationship.py +0 -0
  124. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/relationship/relationship_constants.py +0 -0
  125. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/relationship/relationship_references.py +0 -0
  126. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/requirement/__init__.py +0 -0
  127. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/requirement/meta_requirement.py +0 -0
  128. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/requirement/requirement_constants.py +0 -0
  129. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/validator/__init__.py +0 -0
  130. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/core/validator/validator_constants.py +0 -0
  131. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/meta_data.py +0 -0
  132. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/meta_root.py +0 -0
  133. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/persistence/__init__.py +0 -0
  134. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/persistence/db/__init__.py +0 -0
  135. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/persistence/db/db_constants.py +0 -0
  136. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/persistence/db/db_provider.py +0 -0
  137. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/persistence/origin/__init__.py +0 -0
  138. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/persistence/origin/meta_origin.py +0 -0
  139. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/persistence/origin/origin_constants.py +0 -0
  140. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/persistence/source/__init__.py +0 -0
  141. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/persistence/source/meta_source.py +0 -0
  142. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/persistence/source/source_constants.py +0 -0
  143. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/presentation/__init__.py +0 -0
  144. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/presentation/layout/__init__.py +0 -0
  145. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/presentation/layout/layout_constants.py +0 -0
  146. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/presentation/layout/meta_layout.py +0 -0
  147. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/presentation/ui/__init__.py +0 -0
  148. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/presentation/ui/ui_provider.py +0 -0
  149. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/presentation/view/__init__.py +0 -0
  150. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/presentation/view/meta_view.py +0 -0
  151. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/presentation/view/view_constants.py +0 -0
  152. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/provider_extends.py +0 -0
  153. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/template/__init__.py +0 -0
  154. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/template/meta_template.py +0 -0
  155. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/template/prompt_provider.py +0 -0
  156. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta/template/template_constants.py +0 -0
  157. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/meta_endpoint.py +0 -0
  158. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/naming.py +0 -0
  159. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/naming_refs.py +0 -0
  160. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/parser.py +0 -0
  161. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/parser_yaml.py +0 -0
  162. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/provider.py +0 -0
  163. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/py.typed +0 -0
  164. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/registry.py +0 -0
  165. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/registry_manifest.py +0 -0
  166. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/__init__.py +0 -0
  167. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/email_document.py +0 -0
  168. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/escapers.py +0 -0
  169. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/extract/KNOWN_GAPS.md +0 -0
  170. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/extract/__init__.py +0 -0
  171. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/extract/coerce.py +0 -0
  172. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/extract/extract_map.py +0 -0
  173. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/extract/json_forgiving_reader.py +0 -0
  174. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/extract/normalize.py +0 -0
  175. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/extract/types.py +0 -0
  176. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/filesystem_provider.py +0 -0
  177. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/payload_accessors.py +0 -0
  178. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/prompt/__init__.py +0 -0
  179. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/prompt/output_format_renderer.py +0 -0
  180. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/prompt/output_format_spec.py +0 -0
  181. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/prompt/prompt_field.py +0 -0
  182. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/prompt/prompt_overrides.py +0 -0
  183. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/prompt/prompt_style.py +0 -0
  184. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/renderer.py +0 -0
  185. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/render/verify.py +0 -0
  186. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/runtime/__init__.py +0 -0
  187. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/runtime/llm_recorder.py +0 -0
  188. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/runtime/n2m_resolver.py +0 -0
  189. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/runtime/object_manager.py +0 -0
  190. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/runtime/tph.py +0 -0
  191. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/scope.py +0 -0
  192. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/serializer_json.py +0 -0
  193. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/shared/__init__.py +0 -0
  194. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/shared/base_types.py +0 -0
  195. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/shared/separators.py +0 -0
  196. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/shared/structural.py +0 -0
  197. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/source/__init__.py +0 -0
  198. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/source/error_source.py +0 -0
  199. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/source/json_path.py +0 -0
  200. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/source/semantic_diff.py +0 -0
  201. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/source/yaml_positions.py +0 -0
  202. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/source_resolution.py +0 -0
  203. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/spec_metamodel/__init__.py +0 -0
  204. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/spec_metamodel/attr.json +0 -0
  205. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/spec_metamodel/db.json +0 -0
  206. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/spec_metamodel/documentation.json +0 -0
  207. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/spec_metamodel/field.json +0 -0
  208. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/spec_metamodel/identity.json +0 -0
  209. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/spec_metamodel/index.json +0 -0
  210. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/spec_metamodel/layout.json +0 -0
  211. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/spec_metamodel/object.json +0 -0
  212. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/spec_metamodel/origin.json +0 -0
  213. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/spec_metamodel/prompt.json +0 -0
  214. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/spec_metamodel/relationship.json +0 -0
  215. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/spec_metamodel/requirement.json +0 -0
  216. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/spec_metamodel/source.json +0 -0
  217. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/spec_metamodel/template.json +0 -0
  218. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/spec_metamodel/ui-web.json +0 -0
  219. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/spec_metamodel/ui.json +0 -0
  220. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/spec_metamodel/validator.json +0 -0
  221. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/spec_metamodel/view.json +0 -0
  222. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/super_resolve.py +0 -0
  223. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/validation_types.py +0 -0
  224. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/src/metaobjects/yaml_desugar.py +0 -0
  225. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/__init__.py +0 -0
  226. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/__init__.py +0 -0
  227. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/gen_suite.py +0 -0
  228. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/golden/extends/expected/BaseEntity.py +0 -0
  229. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/golden/extends/expected/Program.py +0 -0
  230. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/golden/extends/meta.json +0 -0
  231. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/golden/nested-array/expected/AuthorBrief.py +0 -0
  232. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/golden/nested-array/expected/PostBrief.py +0 -0
  233. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/golden/nested-array/meta.json +0 -0
  234. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/golden/scalars/expected/Metric.py +0 -0
  235. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/golden/scalars/expected/Report.py +0 -0
  236. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/golden/scalars/meta.json +0 -0
  237. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/golden/vanilla/expected/Subscriber.py +0 -0
  238. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/golden/vanilla/meta.json +0 -0
  239. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_abstract_conformance.py +0 -0
  240. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_api_docs_builder.py +0 -0
  241. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_api_docs_paths.py +0 -0
  242. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_cli.py +0 -0
  243. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_cli_config_gen.py +0 -0
  244. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_cli_config_verify.py +0 -0
  245. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_cli_dependencies.py +0 -0
  246. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_cli_providers.py +0 -0
  247. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_cli_render_helper_template_root.py +0 -0
  248. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_cli_staleness_nudge.py +0 -0
  249. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_cli_verify_strict.py +0 -0
  250. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_cli_verify_subverbs.py +0 -0
  251. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_codegen_compile_conformance.py +0 -0
  252. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_constants_config.py +0 -0
  253. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_entity_model.py +0 -0
  254. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_enum_conformance.py +0 -0
  255. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_extends_abstract_field_inheritance.py +0 -0
  256. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_extract_tier_collision.py +0 -0
  257. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_extractor_generator.py +0 -0
  258. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_filter_allowlist_generator.py +0 -0
  259. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_format.py +0 -0
  260. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_fr010_nested_object_prompt.py +0 -0
  261. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_fr010_output_codegen.py +0 -0
  262. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_fr019_shared_provided_conformance.py +0 -0
  263. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_generator.py +0 -0
  264. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_generator_extension_seams.py +0 -0
  265. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_golden.py +0 -0
  266. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_inherit_without_restate_gate.py +0 -0
  267. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_inheritance_conformance.py +0 -0
  268. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_instance_artifacts.py +0 -0
  269. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_m2m_codegen.py +0 -0
  270. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_names_extends_chain.py +0 -0
  271. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_names_generator.py +0 -0
  272. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_no_magic_physical_names.py +0 -0
  273. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_origin_nullability.py +0 -0
  274. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_output_parser_generator.py +0 -0
  275. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_overwrite_policy.py +0 -0
  276. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_overwrite_policy_hash.py +0 -0
  277. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_project_config.py +0 -0
  278. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_projection_compile.py +0 -0
  279. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_render_helper_conformance.py +0 -0
  280. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_render_helper_generator.py +0 -0
  281. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_reverse_finders.py +0 -0
  282. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_route_path_naming.py +0 -0
  283. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_router_autoset.py +0 -0
  284. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_router_generator.py +0 -0
  285. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_router_generator_m2m_target_tph.py +0 -0
  286. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_router_generator_tph_m2m.py +0 -0
  287. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_router_generator_tph_m2m_shadowed.py +0 -0
  288. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_runner.py +0 -0
  289. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_source_resolution.py +0 -0
  290. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_sourceless_projection.py +0 -0
  291. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_template_data.py +0 -0
  292. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_template_generator.py +0 -0
  293. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_template_output_pattern.py +0 -0
  294. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_template_scope_helpers.py +0 -0
  295. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_template_scope_walk.py +0 -0
  296. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_template_spec.py +0 -0
  297. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_tph_codegen.py +0 -0
  298. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_trace_helper_generator.py +0 -0
  299. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_type_map.py +0 -0
  300. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_validation_conformance.py +0 -0
  301. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_value_objects.py +0 -0
  302. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/codegen/test_write_through.py +0 -0
  303. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/config/__init__.py +0 -0
  304. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/config/test_dependencies.py +0 -0
  305. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/config/test_library_package_guard.py +0 -0
  306. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/config/test_neutral_config.py +0 -0
  307. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/config/test_source_resolver.py +0 -0
  308. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/__init__.py +0 -0
  309. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/capabilities.py +0 -0
  310. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/conformance-expected-failures.json +0 -0
  311. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/conformance_adapter.py +0 -0
  312. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/corpus.py +0 -0
  313. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/expected_failures.py +0 -0
  314. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/fixture_discovery.py +0 -0
  315. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/navigator.py +0 -0
  316. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/test_api_docs_cross_port_conformance.py +0 -0
  317. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/test_conformance.py +0 -0
  318. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/test_dependency_conformance.py +0 -0
  319. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/test_extract_object_verdict.py +0 -0
  320. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/test_fr010_loader_attrs.py +0 -0
  321. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/test_fr011_attrs.py +0 -0
  322. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/test_generator_registry_conformance.py +0 -0
  323. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/test_object_model_conformance.py +0 -0
  324. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/test_provider_composition_conformance.py +0 -0
  325. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/test_registry_conformance.py +0 -0
  326. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/test_runner_hardfail.py +0 -0
  327. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/test_scope_conformance.py +0 -0
  328. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/test_source_resolution_conformance.py +0 -0
  329. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/test_spec_metamodel_embed.py +0 -0
  330. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/test_strict_attr_load.py +0 -0
  331. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/test_template_codegen_conformance.py +0 -0
  332. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/test_template_generator_conformance.py +0 -0
  333. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/test_yaml_conformance.py +0 -0
  334. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/conformance/yaml-conformance-expected-failures.json +0 -0
  335. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/__init__.py +0 -0
  336. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/api_contract_assertions.py +0 -0
  337. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/api_contract_jsonb_server.py +0 -0
  338. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/api_contract_m2m_server.py +0 -0
  339. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/api_contract_server.py +0 -0
  340. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/generated_jsonb_app.py +0 -0
  341. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/generated_m2m_app.py +0 -0
  342. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/generated_projection_app.py +0 -0
  343. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/generated_router_app.py +0 -0
  344. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/generated_tph_app.py +0 -0
  345. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/meta_ai_trace.yaml +0 -0
  346. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/normalization.py +0 -0
  347. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/postgres_container.py +0 -0
  348. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/query_runner.py +0 -0
  349. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/scenarios.py +0 -0
  350. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/test_api_contract.py +0 -0
  351. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/test_api_contract_generated.py +0 -0
  352. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/test_api_contract_jsonb.py +0 -0
  353. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/test_api_contract_m2m.py +0 -0
  354. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/test_api_contract_m2m_generated.py +0 -0
  355. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/test_api_contract_projection.py +0 -0
  356. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/test_api_contract_tph_generated.py +0 -0
  357. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/test_generated_router_uuid_pk.py +0 -0
  358. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/test_llm_call_trace.py +0 -0
  359. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/test_m2m_target_tph_generated.py +0 -0
  360. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/test_normalization.py +0 -0
  361. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/test_query_scenarios.py +0 -0
  362. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/test_runtime_return_types.py +0 -0
  363. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/test_tph_m2m_generated.py +0 -0
  364. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/integration/test_tph_m2m_shadowed_generated.py +0 -0
  365. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/loader/__init__.py +0 -0
  366. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/loader/test_abstract_subtype_authored.py +0 -0
  367. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/loader/test_child_wrapper_body_shape.py +0 -0
  368. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/loader/test_enum_extends_values_conflict.py +0 -0
  369. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/loader/test_field_mutability_order.py +0 -0
  370. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/loader/test_shipped_library_ai.py +0 -0
  371. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/loader/test_template_payload_target_210.py +0 -0
  372. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/open_closed_proof_test.py +0 -0
  373. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/__init__.py +0 -0
  374. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/extract/__init__.py +0 -0
  375. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/extract/test_coerce.py +0 -0
  376. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/extract/test_extract.py +0 -0
  377. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/extract/test_extract_map.py +0 -0
  378. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/extract/test_json_forgiving_reader.py +0 -0
  379. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/extract/test_locate.py +0 -0
  380. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/extract/test_model.py +0 -0
  381. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/extract/test_normalize.py +0 -0
  382. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/extract/test_strip.py +0 -0
  383. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/extract/test_xml_forgiving_reader.py +0 -0
  384. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/prompt/__init__.py +0 -0
  385. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/prompt/test_output_format_renderer.py +0 -0
  386. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/test_email_document.py +0 -0
  387. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/test_filesystem_provider.py +0 -0
  388. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/test_output_format_renderer_nested.py +0 -0
  389. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/test_output_prompt_conformance.py +0 -0
  390. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/test_render_conformance.py +0 -0
  391. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/test_render_max_chars.py +0 -0
  392. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/test_render_model_payload.py +0 -0
  393. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/test_verify.py +0 -0
  394. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/render/test_verify_conformance.py +0 -0
  395. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/runtime/test_constraint_errors.py +0 -0
  396. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/runtime/test_object_manager_currency_read.py +0 -0
  397. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/runtime/test_object_manager_enum_intvaluemap.py +0 -0
  398. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/runtime/test_object_manager_table_name.py +0 -0
  399. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/source/__init__.py +0 -0
  400. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/source/test_fr5c_merge_attribution.py +0 -0
  401. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/source/test_fr5d_reference_resolution.py +0 -0
  402. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/source/test_fr5e_database_source_shape.py +0 -0
  403. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/source/test_json_path.py +0 -0
  404. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/source/test_semantic_diff.py +0 -0
  405. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/source/test_source_on_node.py +0 -0
  406. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/source/test_yaml_positions.py +0 -0
  407. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/test_api_docs_accuracy.py +0 -0
  408. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/test_meta_endpoint.py +0 -0
  409. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/__init__.py +0 -0
  410. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_agent_context_staleness.py +0 -0
  411. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_capabilities.py +0 -0
  412. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_column_naming_strategy.py +0 -0
  413. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_common_attrs.py +0 -0
  414. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_core_types.py +0 -0
  415. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_derive_m2m_declaring_entity.py +0 -0
  416. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_effective_children_sibling_shadowing.py +0 -0
  417. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_effective_package.py +0 -0
  418. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_errors.py +0 -0
  419. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_field_enum.py +0 -0
  420. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_field_enum_intvaluemap.py +0 -0
  421. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_field_map_validation.py +0 -0
  422. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_field_uuid_dbcolumntype.py +0 -0
  423. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_file_source_id.py +0 -0
  424. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_fr016_source_name_and_kind_aliases.py +0 -0
  425. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_index_lookup.py +0 -0
  426. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_llm_recorder.py +0 -0
  427. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_loader.py +0 -0
  428. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_loader_bom.py +0 -0
  429. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_loader_class.py +0 -0
  430. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_merge.py +0 -0
  431. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_meta_attr.py +0 -0
  432. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_meta_data.py +0 -0
  433. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_meta_source.py +0 -0
  434. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_module_shortcuts.py +0 -0
  435. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_n2m_resolver.py +0 -0
  436. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_n2m_resolver_inherited.py +0 -0
  437. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_no_dead_config_fields.py +0 -0
  438. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_object_manager_autoset_stamping.py +0 -0
  439. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_object_manager_uuid_coercion.py +0 -0
  440. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_object_manager_write_through.py +0 -0
  441. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_one_primary_source.py +0 -0
  442. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_parser.py +0 -0
  443. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_parser_yaml.py +0 -0
  444. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_provider.py +0 -0
  445. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_provider_extension.py +0 -0
  446. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_registry.py +0 -0
  447. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_registry_completeness.py +0 -0
  448. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_registry_extend.py +0 -0
  449. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_registry_sealed.py +0 -0
  450. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_relationship_m2m_validation.py +0 -0
  451. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_relationship_references.py +0 -0
  452. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_relationship_referential_actions.py +0 -0
  453. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_resolution_key.py +0 -0
  454. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_runtime_resolution_key_binding.py +0 -0
  455. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_serializer.py +0 -0
  456. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_serializer_shared_document.py +0 -0
  457. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_shared_constants.py +0 -0
  458. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_smoke.py +0 -0
  459. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_source_escapes.py +0 -0
  460. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_sources.py +0 -0
  461. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_strict_child_placement.py +0 -0
  462. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_super_resolve.py +0 -0
  463. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_template_toolcall.py +0 -0
  464. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_template_wrong_subtype_attrs.py +0 -0
  465. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_validation_attr_schema.py +0 -0
  466. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_validation_filter_values.py +0 -0
  467. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_validation_origin_195.py +0 -0
  468. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_validation_origin_paths.py +0 -0
  469. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_validation_sort_field.py +0 -0
  470. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_validation_warnings.py +0 -0
  471. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_write_coercion_arrays.py +0 -0
  472. {metaobjects-1.0.5rc10 → metaobjects-1.0.7}/tests/unit/test_yaml_desugar.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: metaobjects
3
- Version: 1.0.5rc10
3
+ Version: 1.0.7
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
@@ -78,7 +78,8 @@ else:
78
78
  The primary public API is the **loader** (`load_directory` / `load_uris` /
79
79
  `load_string`, `MetaDataLoader`, `LoadResult`, `ErrorCode`, `MetaError`). The
80
80
  distribution also ships the Python implementations of the other pillars used by the CLI
81
- and tooling: `codegen` (Pydantic + FastAPI emit), `render` (Mustache + payload-VO +
81
+ and tooling: `codegen` (Pydantic + FastAPI emit — reference generators you own:
82
+ `metaobjects eject <name>` copies one into your repo), `render` (Mustache + payload-VO +
82
83
  verify), and `runtime` (a DB-API 2 `ObjectManager` — pg8000 / psycopg — no SQLAlchemy).
83
84
  Schema migrations are owned by the TypeScript `meta` CLI (ADR-0015); there is
84
85
  **no `migrate` module** in this distribution.
@@ -43,7 +43,8 @@ else:
43
43
  The primary public API is the **loader** (`load_directory` / `load_uris` /
44
44
  `load_string`, `MetaDataLoader`, `LoadResult`, `ErrorCode`, `MetaError`). The
45
45
  distribution also ships the Python implementations of the other pillars used by the CLI
46
- and tooling: `codegen` (Pydantic + FastAPI emit), `render` (Mustache + payload-VO +
46
+ and tooling: `codegen` (Pydantic + FastAPI emit — reference generators you own:
47
+ `metaobjects eject <name>` copies one into your repo), `render` (Mustache + payload-VO +
47
48
  verify), and `runtime` (a DB-API 2 `ObjectManager` — pg8000 / psycopg — no SQLAlchemy).
48
49
  Schema migrations are owned by the TypeScript `meta` CLI (ADR-0015); there is
49
50
  **no `migrate` module** in this distribution.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "metaobjects"
3
- version = "1.0.5rc10"
3
+ version = "1.0.7"
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"
@@ -105,6 +105,7 @@ from metaobjects.codegen.generator_registry import (
105
105
  unsatisfied_requires,
106
106
  )
107
107
  from metaobjects.codegen.runner import run_gen
108
+ from metaobjects.codegen import eject as owned
108
109
  from metaobjects.codegen.generators.render_helper_generator import (
109
110
  _derive_payload_field_tree,
110
111
  )
@@ -501,10 +502,14 @@ def _template_root_for(args: argparse.Namespace) -> str:
501
502
 
502
503
 
503
504
  def _resolve_generators(
504
- names: str, ctx: GeneratorBuildContext | None = None,
505
+ names: str, ctx: GeneratorBuildContext | None = None, owned_root: Path | None = None,
505
506
  ) -> tuple[list[Generator], list[str]]:
506
507
  """Resolve a comma-separated list of STABLE generator names via the registry.
507
508
 
509
+ An entry of the form ``module:symbol`` is an adopter-owned copy (``metaobjects
510
+ eject``), imported with *owned_root* (default: the working directory) on ``sys.path``
511
+ — the config directory in config mode, so a copy beside the config resolves.
512
+
508
513
  Returns ``(generators, errors)``. An unknown name produces a clear error and
509
514
  no generators (so the caller can fail with exit code != 0).
510
515
 
@@ -519,17 +524,27 @@ def _resolve_generators(
519
524
  requested = [n.strip() for n in names.split(",") if n.strip()]
520
525
  gens: list[Generator] = []
521
526
  errors: list[str] = []
527
+ selected: list[str] = []
522
528
  for n in requested:
523
529
  entry = get_generator(n)
530
+ if entry is None and (":" in n or "." in n):
531
+ gen, err = owned.build_owned(n, owned_root or Path.cwd(), ctx)
532
+ if err is not None:
533
+ errors.append(err)
534
+ continue
535
+ gens.append(gen)
536
+ selected.append(gen.name)
537
+ continue
524
538
  if entry is None:
525
539
  known = ", ".join(sorted(GENERATOR_REGISTRY))
526
540
  errors.append(f"unknown generator {n!r}; known: {known}")
527
541
  continue
528
542
  gens.append(entry.factory(ctx))
543
+ selected.append(n)
529
544
  if not errors and not gens:
530
545
  errors.append("no generators selected (empty --generators list)")
531
546
  if not errors:
532
- for warning in unsatisfied_requires(requested):
547
+ for warning in unsatisfied_requires(selected):
533
548
  print(f"warning: {warning}", file=sys.stderr)
534
549
  return gens, errors
535
550
 
@@ -968,17 +983,42 @@ def _cmd_docs(args: argparse.Namespace) -> int:
968
983
  return 0
969
984
 
970
985
 
986
+ #: ADR-0034 Amendment 3: generators are reference helpers you own with ``metaobjects
987
+ #: eject``. Printed above the ``--list`` entries.
988
+ LIST_HEADER = (
989
+ "Reference generators — each is a helper, not a guarantee: `metaobjects eject <name>`\n"
990
+ "copies it into codegen/generators/ and the copy is yours to change. What MetaObjects\n"
991
+ "guarantees (verify, render) is not a generator and is not listed.\n"
992
+ "Select with --generators <name,...>:"
993
+ )
994
+
995
+
971
996
  def _cmd_list(_args: argparse.Namespace) -> int:
972
997
  """Print each registered generator ``<stable-name> — <description>`` and exit 0.
973
998
 
974
999
  Does NOT run codegen — pure discoverability (ADR-0021 D3).
975
1000
  """
1001
+ print(LIST_HEADER)
1002
+ root = Path.cwd()
976
1003
  for entry in list_generators():
977
1004
  requires = f" (requires: {', '.join(entry.requires)})" if entry.requires else ""
978
- print(f"{entry.name} — {entry.description}{requires}")
1005
+ status = owned.owned_status(root, entry)
1006
+ mark = f" [owned — {status}]" if status is not None else ""
1007
+ print(f"{entry.name} — {entry.description}{requires}{mark}")
979
1008
  return 0
980
1009
 
981
1010
 
1011
+ def _cmd_eject(args: argparse.Namespace) -> int:
1012
+ """Copy reference generators into ``codegen/generators/`` to own (ADR-0034 Am. 3)."""
1013
+ root = Path(args.root) if args.root else Path.cwd()
1014
+ result = owned.eject(args.names, root, force=args.force)
1015
+ for line in result.out:
1016
+ print(line)
1017
+ for line in result.err:
1018
+ print(f"error: {line}", file=sys.stderr)
1019
+ return result.code
1020
+
1021
+
982
1022
  def _warn_if_agent_context_stale() -> None:
983
1023
  """Print ONE advisory line to stderr if the scaffolded agent context is stale.
984
1024
 
@@ -1161,7 +1201,8 @@ def _run_gen_targets(
1161
1201
  gens: list[Generator] | None = None
1162
1202
  if t.generators is not None:
1163
1203
  gens, gen_errors = _resolve_generators(
1164
- ",".join(t.generators), build_ctx or GeneratorBuildContext())
1204
+ ",".join(t.generators), build_ctx or GeneratorBuildContext(),
1205
+ owned_root=config.config_dir)
1165
1206
  if gen_errors:
1166
1207
  errors.extend(f"target '{t.name}': {m}" for m in gen_errors)
1167
1208
  continue
@@ -2365,6 +2406,16 @@ def _build_parser() -> argparse.ArgumentParser:
2365
2406
  )
2366
2407
  verify.set_defaults(func=_cmd_verify)
2367
2408
 
2409
+ eject_p = sub.add_parser(
2410
+ "eject",
2411
+ help="copy reference generators into codegen/generators/ to own and edit",
2412
+ )
2413
+ eject_p.add_argument("names", nargs="+", metavar="NAME", help="stable generator names")
2414
+ eject_p.add_argument("--force", action="store_true",
2415
+ help="replace an existing owned copy with the reference")
2416
+ eject_p.add_argument("--root", default=None, help="project root (default: cwd)")
2417
+ eject_p.set_defaults(func=_cmd_eject)
2418
+
2368
2419
  agent_docs = sub.add_parser(
2369
2420
  "agent-docs",
2370
2421
  help=(
@@ -0,0 +1,168 @@
1
+ """`metaobjects eject` — copy a reference generator into the adopter's repo to own.
2
+
3
+ ADR-0034 Amendment 3: a generator is a reference helper, not a guarantee. The adopter
4
+ copies it with ``eject``, wires the copy into ``generators`` as ``module:symbol`` (the
5
+ syntax ``providers`` already accepts), and ``gen`` / ``verify --codegen`` run the copy.
6
+ Mirrors the TypeScript ``meta eject``: the copy is verbatim, an existing copy is never
7
+ overwritten without ``--force``, and the config is never edited — eject prints the entry
8
+ to wire instead.
9
+
10
+ A copy imports the same ``metaobjects.codegen.*`` module paths the packaged generator
11
+ does. Those module paths are the documented surface an owned generator builds on.
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import importlib
16
+ import inspect
17
+ import sys
18
+ import tempfile
19
+ from collections import Counter
20
+ from dataclasses import dataclass
21
+ from pathlib import Path
22
+
23
+ from metaobjects.codegen.generator import Generator
24
+ from metaobjects.codegen.generator_registry import (
25
+ GENERATOR_REGISTRY,
26
+ GeneratorBuildContext,
27
+ GeneratorEntry,
28
+ )
29
+
30
+ #: Where an owned copy lands, relative to the project root. Mirrors the TS layout.
31
+ OWNED_DIR = Path("codegen") / "generators"
32
+
33
+
34
+ def owned_stem(name: str) -> str:
35
+ """The module name of an owned copy: the stable name with ``-`` as ``_``."""
36
+ return name.replace("-", "_")
37
+
38
+
39
+ def owned_path(root: Path, name: str) -> Path:
40
+ return root / OWNED_DIR / f"{owned_stem(name)}.py"
41
+
42
+
43
+ def owned_token(entry: GeneratorEntry) -> str:
44
+ """The ``module:symbol`` entry that wires an owned copy of *entry*."""
45
+ return f"codegen.generators.{owned_stem(entry.name)}:{entry.symbol}"
46
+
47
+
48
+ def packaged_source(entry: GeneratorEntry) -> str:
49
+ assert entry.source_module is not None
50
+ module = importlib.import_module(entry.source_module)
51
+ assert module.__file__ is not None
52
+ return Path(module.__file__).read_text(encoding="utf-8")
53
+
54
+
55
+ def ejectable() -> list[GeneratorEntry]:
56
+ return [e for e in GENERATOR_REGISTRY.values() if e.source is not None]
57
+
58
+
59
+ @dataclass
60
+ class EjectResult:
61
+ code: int
62
+ out: list[str]
63
+ err: list[str]
64
+
65
+
66
+ def eject(names: list[str], root: Path, *, force: bool = False) -> EjectResult:
67
+ """Copy each named generator. Every name is checked before any file is written."""
68
+ known = {e.name: e for e in ejectable()}
69
+ unknown = [n for n in names if n not in known]
70
+ if unknown:
71
+ return EjectResult(2, [], [
72
+ f"unknown or non-ejectable generator(s): {', '.join(unknown)}; "
73
+ f"ejectable: {', '.join(sorted(known))}",
74
+ ])
75
+ existing = [n for n in names if owned_path(root, n).exists()]
76
+ if existing and not force:
77
+ return EjectResult(1, [], [
78
+ f"already owned: {', '.join(str(owned_path(root, n).relative_to(root)) for n in existing)}. "
79
+ "Eject never overwrites your copy; pass --force to replace it with the reference.",
80
+ ])
81
+
82
+ (root / OWNED_DIR).mkdir(parents=True, exist_ok=True)
83
+ for init in (root / "codegen" / "__init__.py", root / OWNED_DIR / "__init__.py"):
84
+ if not init.exists():
85
+ init.write_text("", encoding="utf-8")
86
+
87
+ out: list[str] = []
88
+ for n in names:
89
+ entry = known[n]
90
+ target = owned_path(root, n)
91
+ target.write_text(packaged_source(entry), encoding="utf-8")
92
+ out.append(f"ejected {n} -> {target.relative_to(root)}")
93
+ out.append(f" wire it: replace \"{n}\" in `generators` with {owned_token(entry)}")
94
+ out.append("")
95
+ out.append(
96
+ "The copies are yours: edit them freely. Keep only one of the packaged name and your "
97
+ "copy in `generators` — wiring both runs both, and they write the same files."
98
+ )
99
+ return EjectResult(0, out, [])
100
+
101
+
102
+ def _normalised(text: str) -> Counter[str]:
103
+ return Counter(line.rstrip() for line in text.splitlines() if line.strip())
104
+
105
+
106
+ def owned_status(root: Path, entry: GeneratorEntry) -> str | None:
107
+ """``identical`` / ``DIFFERS: N behind, M of your own``, or ``None`` if not owned.
108
+
109
+ Line-multiset comparison, the same shape as TS ``owned-copy.ts``: *behind* counts
110
+ reference lines the copy lacks, *of your own* counts copy lines the reference lacks.
111
+ """
112
+ path = owned_path(root, entry.name)
113
+ if entry.source is None or not path.exists():
114
+ return None
115
+ mine = _normalised(path.read_text(encoding="utf-8"))
116
+ ref = _normalised(packaged_source(entry))
117
+ behind = sum((ref - mine).values())
118
+ own = sum((mine - ref).values())
119
+ if behind == 0 and own == 0:
120
+ return "identical"
121
+ return f"DIFFERS: {behind} behind, {own} of your own"
122
+
123
+
124
+ def build_owned(spec: str, root: Path, ctx: GeneratorBuildContext) -> tuple[Generator | None, str | None]:
125
+ """Resolve a ``module:symbol`` generator entry against the project at *root*.
126
+
127
+ The symbol may be a Generator, or a factory: one taking ``template_root`` (the
128
+ render-helper shape) gets the build context's template root; one taking a single
129
+ positional argument gets the build context; otherwise it is called with none.
130
+ """
131
+ module_name, sep, symbol = spec.partition(":")
132
+ if not sep or not module_name or not symbol:
133
+ return None, (f"generator {spec!r} is neither a registered name nor a "
134
+ "'module:symbol' reference to an owned copy")
135
+ root_str = str(root.resolve())
136
+ if root_str not in sys.path:
137
+ sys.path.insert(0, root_str)
138
+ # A module of the same name imported from another project (or an earlier copy) would
139
+ # be reused from the cache; drop any entry that does not live under this root.
140
+ top = module_name.split(".")[0]
141
+ for key in [k for k in sys.modules if k == top or k.startswith(top + ".")]:
142
+ file = getattr(sys.modules[key], "__file__", None)
143
+ if file is None or not str(Path(file).resolve()).startswith(root_str):
144
+ del sys.modules[key]
145
+ try:
146
+ module = importlib.import_module(module_name)
147
+ except Exception as exc: # ImportError and anything raised at import time
148
+ return None, f"generator {spec!r}: cannot import {module_name!r}: {exc}"
149
+ obj = getattr(module, symbol, None)
150
+ if obj is None:
151
+ return None, f"generator {spec!r}: {module_name!r} has no attribute {symbol!r}"
152
+ if not hasattr(obj, "generate") and callable(obj):
153
+ params = inspect.signature(obj).parameters
154
+ required = [p for p in params.values()
155
+ if p.default is inspect.Parameter.empty
156
+ and p.kind in (p.POSITIONAL_ONLY, p.POSITIONAL_OR_KEYWORD)]
157
+ try:
158
+ if "template_root" in params:
159
+ obj = obj(template_root=ctx.template_root or tempfile.gettempdir())
160
+ elif len(required) == 1:
161
+ obj = obj(ctx)
162
+ else:
163
+ obj = obj()
164
+ except Exception as exc:
165
+ return None, f"generator {spec!r}: factory {symbol}() raised: {exc}"
166
+ if not hasattr(obj, "generate") or not hasattr(obj, "name"):
167
+ return None, f"generator {spec!r}: {symbol!r} is not a generator (needs name and generate)"
168
+ return obj, None
@@ -108,6 +108,21 @@ class GeneratorEntry:
108
108
  #: Not gated cross-port (the manifest carries no such column); surfaced by ``--list``
109
109
  #: and warned about by :func:`unsatisfied_requires`.
110
110
  requires: tuple[str, ...] = ()
111
+ #: The packaged factory an adopter copies with ``metaobjects eject`` (ADR-0034
112
+ #: Amendment 3). Its module is the file copied; its name is the ``module:symbol``
113
+ #: symbol the copy is wired by. ``None`` = not ejectable (the ``template`` primitive
114
+ #: has no emit logic of its own to own).
115
+ source: Callable[..., Generator] | None = None
116
+
117
+ @property
118
+ def source_module(self) -> str | None:
119
+ """Dotted module path of the file ``eject`` copies, or ``None``."""
120
+ return self.source.__module__ if self.source is not None else None
121
+
122
+ @property
123
+ def symbol(self) -> str | None:
124
+ """The factory name an owned copy exports, or ``None``."""
125
+ return self.source.__name__ if self.source is not None else None
111
126
 
112
127
 
113
128
  def _template_primitive(_ctx: GeneratorBuildContext) -> Generator:
@@ -149,10 +164,16 @@ def _render_helper_default(ctx: GeneratorBuildContext) -> Generator:
149
164
  GENERATOR_REGISTRY: dict[str, GeneratorEntry] = {
150
165
  "entity": GeneratorEntry(
151
166
  name="entity",
152
- description="Per-entity model/class — the entity module (table-backed or value object).",
167
+ description=(
168
+ "Per-entity model/class — the entity module (table-backed or value object). "
169
+ "[A field with @stringFormat email is typed pydantic EmailStr, which imports "
170
+ "email-validator when the class is defined, so the consuming project needs "
171
+ "`pydantic[email]` — without it the generated module fails at import.]"
172
+ ),
153
173
  tier="native",
154
174
  layer="model",
155
175
  factory=lambda _ctx: entity_model(),
176
+ source=entity_model,
156
177
  ),
157
178
  "routes": GeneratorEntry(
158
179
  name="routes",
@@ -160,6 +181,7 @@ GENERATOR_REGISTRY: dict[str, GeneratorEntry] = {
160
181
  tier="native",
161
182
  layer="api",
162
183
  factory=lambda _ctx: router_generator(),
184
+ source=router_generator,
163
185
  ),
164
186
  "output-parser": GeneratorEntry(
165
187
  name="output-parser",
@@ -168,6 +190,7 @@ GENERATOR_REGISTRY: dict[str, GeneratorEntry] = {
168
190
  layer="capability",
169
191
  factory=lambda _ctx: output_parser_generator(),
170
192
  requires=("entity",),
193
+ source=output_parser_generator,
171
194
  ),
172
195
  "output-prompt": GeneratorEntry(
173
196
  name="output-prompt",
@@ -175,6 +198,7 @@ GENERATOR_REGISTRY: dict[str, GeneratorEntry] = {
175
198
  tier="native",
176
199
  layer="capability",
177
200
  factory=lambda _ctx: output_prompt_generator(),
201
+ source=output_prompt_generator,
178
202
  ),
179
203
  "render-helper": GeneratorEntry(
180
204
  name="render-helper",
@@ -183,6 +207,7 @@ GENERATOR_REGISTRY: dict[str, GeneratorEntry] = {
183
207
  layer="capability",
184
208
  factory=_render_helper_default,
185
209
  requires=("entity",),
210
+ source=render_helper_generator,
186
211
  ),
187
212
  "extractor": GeneratorEntry(
188
213
  name="extractor",
@@ -191,6 +216,7 @@ GENERATOR_REGISTRY: dict[str, GeneratorEntry] = {
191
216
  layer="capability",
192
217
  factory=lambda _ctx: extractor_generator(),
193
218
  requires=("entity",),
219
+ source=extractor_generator,
194
220
  ),
195
221
  "template": GeneratorEntry(
196
222
  name="template",
@@ -205,6 +231,7 @@ GENERATOR_REGISTRY: dict[str, GeneratorEntry] = {
205
231
  tier="native",
206
232
  layer="api",
207
233
  factory=lambda _ctx: filter_allowlist_generator(),
234
+ source=filter_allowlist_generator,
208
235
  ),
209
236
  "names": GeneratorEntry(
210
237
  name="names",
@@ -212,6 +239,7 @@ GENERATOR_REGISTRY: dict[str, GeneratorEntry] = {
212
239
  tier="native",
213
240
  layer="model",
214
241
  factory=lambda _ctx: names_generator(),
242
+ source=names_generator,
215
243
  ),
216
244
  "trace-helper": GeneratorEntry(
217
245
  name="trace-helper",
@@ -219,6 +247,7 @@ GENERATOR_REGISTRY: dict[str, GeneratorEntry] = {
219
247
  tier="native",
220
248
  layer="capability",
221
249
  factory=lambda _ctx: trace_helper_generator(),
250
+ source=trace_helper_generator,
222
251
  ),
223
252
  }
224
253
 
@@ -431,6 +431,32 @@ def _sort_parse_fn_lines() -> list[str]:
431
431
  ]
432
432
 
433
433
 
434
+ def _auth_docstring_paragraph(*, read_only: bool) -> str:
435
+ """The auth-seam paragraph appended to every generated router's module docstring
436
+ (#367). A generated router is unauthenticated by construction — the consumer wires
437
+ a dependency onto `app.include_router` — and until this, nothing in the emitted
438
+ module said so, mirroring the gap the TS route generators closed for #367 with a
439
+ doc-comment above the register function. Python has no `expose` option to narrow a
440
+ generated router down to a safe subset (non-TS REST templates are frozen for
441
+ features), so the escape hatch for anything a dependency cannot express — a
442
+ row-ownership rule — is `metaobjects eject`, not a narrowing flag.
443
+
444
+ *read_only* only swaps "these endpoints" for "these read endpoints" on a
445
+ projection's GET-only surface; the guidance is otherwise identical. Returned text
446
+ starts and ends with a newline so a caller can splice it directly between the
447
+ docstring's summary line and the closing `\"\"\"`."""
448
+ verbs = "read endpoints" if read_only else "endpoints"
449
+ return (
450
+ "\n"
451
+ f"Auth: these {verbs} are unauthenticated. To guard them, include the router with a\n"
452
+ "dependency, e.g. `app.include_router(router, dependencies=[Depends(require_auth)])`.\n"
453
+ "\n"
454
+ 'A row-ownership rule ("only the owner may read this row") cannot be expressed as a\n'
455
+ "router dependency: eject this generator with `metaobjects eject` and hand-write\n"
456
+ "those endpoints.\n"
457
+ )
458
+
459
+
434
460
  class RouterGenerator:
435
461
  """One ``<entity_snake>_router.py`` per routed object (FastAPI ``APIRouter``):
436
462
  full CRUD for a writable source, read-only for a view-backed one.
@@ -882,7 +908,9 @@ class RouterGenerator:
882
908
  parts.append(
883
909
  h + "\n"
884
910
  + f'"""GENERATED — TPH polymorphic REST router for the {short_name} hierarchy '
885
- + '(single-table inheritance: polymorphic base + per-subtype CRUD)."""\n'
911
+ + '(single-table inheritance: polymorphic base + per-subtype CRUD).\n'
912
+ + _auth_docstring_paragraph(read_only=False)
913
+ + '"""\n'
886
914
  )
887
915
  parts.append("from __future__ import annotations")
888
916
  parts.append("")
@@ -1232,7 +1260,9 @@ class RouterGenerator:
1232
1260
  parts: list[str] = []
1233
1261
  parts.append(
1234
1262
  generated_header(short_name, _effective_fqn(entity)).rstrip() + "\n"
1235
- + f'"""GENERATED — REST router for {short_name} entity. Implements the cross-port API contract."""\n'
1263
+ + f'"""GENERATED — REST router for {short_name} entity. Implements the cross-port API contract.\n'
1264
+ + _auth_docstring_paragraph(read_only=False)
1265
+ + '"""\n'
1236
1266
  )
1237
1267
  parts.append("from __future__ import annotations")
1238
1268
  parts.append("")
@@ -1401,7 +1431,9 @@ class RouterGenerator:
1401
1431
  generated_header(short_name, _effective_fqn(entity)).rstrip() + "\n"
1402
1432
  + f'"""GENERATED — read-only REST router for the {short_name} projection.\n\n'
1403
1433
  + "Implements the cross-port API contract: GET list + GET by id; every write\n"
1404
- + 'verb answers 405 {"error": "method_not_allowed"}."""\n'
1434
+ + 'verb answers 405 {"error": "method_not_allowed"}.\n'
1435
+ + _auth_docstring_paragraph(read_only=True)
1436
+ + '"""\n'
1405
1437
  )
1406
1438
  parts.append("from __future__ import annotations")
1407
1439
  parts.append("")
@@ -151,6 +151,7 @@ def run_gen(
151
151
 
152
152
  refused: list[str] = []
153
153
  adopted: list[str] = []
154
+ untracked = 0
154
155
  for full, (content, _by) in emitted.items():
155
156
  # The out-dir-relative name: what the manifest used to be keyed by, and still
156
157
  # what a refusal is REPORTED as (it is the name the reader sees in `--out`).
@@ -173,11 +174,17 @@ def run_gen(
173
174
  if config.project_root
174
175
  else rel
175
176
  )
177
+ # A file written OUTSIDE the project has no place in the project's manifest: its
178
+ # key would be `../`-relative and committed into `.hashes.json`. It gets the
179
+ # manifest-less rule a run with no project gets — written, never recorded.
180
+ outside = bool(config.project_root) and (key.startswith("..") or os.path.isabs(key))
181
+ if outside:
182
+ untracked += 1
176
183
  status = decide_and_write(
177
184
  full,
178
185
  content,
179
186
  merge_strategy,
180
- gen_state_dir=config.gen_state_dir,
187
+ gen_state_dir=None if outside else config.gen_state_dir,
181
188
  rel_path=key,
182
189
  legacy_rel_path=rel if key != rel else None,
183
190
  baseline=config.baseline,
@@ -188,6 +195,13 @@ def run_gen(
188
195
  elif status == "adopted":
189
196
  adopted.append(rel)
190
197
 
198
+ if untracked:
199
+ result.warnings.append(
200
+ f"{untracked} generated file(s) were written outside the project root and are "
201
+ f"not recorded in .metaobjects/.gen-state/.hashes.json, so hand-edit protection "
202
+ f"does not apply to them beyond the @generated header rule."
203
+ )
204
+
191
205
  if refused:
192
206
  if not tracking_hashes:
193
207
  # No state to reason from, so decide_and_write can only have refused for
@@ -45,7 +45,7 @@ def extract(
45
45
  span: str | None
46
46
  raw: dict[str, object]
47
47
  if schema.format == Format.JSON:
48
- span = _locate.json(stripped)
48
+ span = _select_json(text, stripped, schema.fields, ci)
49
49
  raw = {} if span is None else JsonForgivingReader().read(span)
50
50
  elif o.rootless:
51
51
  span = None if stripped == "" else stripped
@@ -199,12 +199,39 @@ def _extract_value(
199
199
  # A text element that also carried XML attributes is represented by XmlForgivingReader
200
200
  # as a dict with the body under TEXT_KEY. A scalar field reads that text (attributes
201
201
  # ignored for scalars — preserving pre-attribute-support behaviour).
202
- if isinstance(present, dict) and TEXT_KEY in present:
202
+ if isinstance(present, dict):
203
+ # An element with no text of its own (only child elements) is not a scalar value.
204
+ # Never stringify the dict: that delivered "{'child': ...}" as the field's text.
205
+ if TEXT_KEY not in present:
206
+ return MALFORMED
203
207
  present = present[TEXT_KEY]
204
208
  raw_str = present if isinstance(present, str) else str(present)
205
209
  return _coerce.value(raw_str, f, o, path, report)
206
210
 
207
211
 
212
+ def _select_json(
213
+ text: str | None, stripped: str, fields: list[FieldSpec], ci: bool
214
+ ) -> str | None:
215
+ """Pick the JSON object that answers the schema. Fenced blocks are searched first, then
216
+ the whole reply, and the first object carrying at least one declared field wins, so a
217
+ draft object, an echoed format example or a brace in prose no longer shadows the real
218
+ answer (#363). A fenced object with none of the declared fields falls through the same
219
+ way. When nothing carries a declared field, the first-object rule (``locate.json``)
220
+ decides."""
221
+ for region in [*_strip.fenced_bodies(text), stripped]:
222
+ for candidate in _locate.json_candidates(region):
223
+ parsed = JsonForgivingReader().read(candidate)
224
+ if any(_carries(parsed, f.name, ci) for f in fields):
225
+ return candidate
226
+ return _locate.json(stripped)
227
+
228
+
229
+ def _carries(raw: dict[str, object], name: str, ci: bool) -> bool:
230
+ if name in raw:
231
+ return True
232
+ return ci and any(k.lower() == name.lower() for k in raw)
233
+
234
+
208
235
  def _lookup(raw: dict[str, object], name: str, ci: bool) -> object | None:
209
236
  """Case-folding lookup honoring tolerance."""
210
237
  if name in raw:
@@ -1,6 +1,7 @@
1
1
  """Stages 2-3: isolate and select the payload root span.
2
2
 
3
- Selection rule: first-closed-else-first-open.
3
+ JSON: extract picks among json_candidates by the schema (fenced first, first object carrying a
4
+ declared field); json() (first-closed-else-first-open) is its fallback.
4
5
  """
5
6
  from __future__ import annotations
6
7
 
@@ -22,6 +23,28 @@ def json(text: str | None) -> str | None:
22
23
  return None if first_open < 0 else text[first_open:]
23
24
 
24
25
 
26
+ def json_candidates(text: str | None) -> list[str]:
27
+ """Every top-level object span in ``text``, in order: each balanced {...} (nested objects
28
+ are part of their parent, not separate spans), and, for a '{' that never closes, the text
29
+ from it to the end."""
30
+ out: list[str] = []
31
+ if text is None:
32
+ return out
33
+ tail_added = False
34
+ i = 0
35
+ while i < len(text):
36
+ if text[i] == "{":
37
+ end = _scan_balanced(text, i)
38
+ if end >= 0:
39
+ out.append(text[i : end + 1])
40
+ i = end
41
+ elif not tail_added:
42
+ out.append(text[i:])
43
+ tail_added = True
44
+ i += 1
45
+ return out
46
+
47
+
25
48
  def _scan_balanced(s: str, open_idx: int) -> int:
26
49
  """Return index of the matching ``}``, or -1 if unterminated. String-aware."""
27
50
  depth = 0
@@ -18,3 +18,11 @@ def strip(raw: str | None) -> str:
18
18
  if m:
19
19
  return (raw[: m.start()] + m.group(1) + raw[m.end():]).strip()
20
20
  return raw.strip()
21
+
22
+
23
+ def fenced_bodies(raw: str | None) -> list[str]:
24
+ """The body of every fenced block, in order. Locate searches these before the whole
25
+ text, because a model told to fence its answer puts the answer there."""
26
+ if raw is None:
27
+ return []
28
+ return [m.group(1) for m in _FENCE.finditer(raw)]