metaobjects 0.19.9__tar.gz → 0.20.13__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.
- {metaobjects-0.19.9 → metaobjects-0.20.13}/PKG-INFO +1 -1
- {metaobjects-0.19.9 → metaobjects-0.20.13}/pyproject.toml +1 -1
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/cli.py +334 -3
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/KNOWN_GAPS.md +6 -4
- metaobjects-0.20.13/src/metaobjects/codegen/metaobjects-config.schema.json +47 -0
- metaobjects-0.20.13/src/metaobjects/codegen/project_config.py +160 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/core_types.py +6 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/errors.py +5 -0
- metaobjects-0.20.13/src/metaobjects/loader/validate_enum_normalize_ambiguity.py +163 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/loader/validation_passes.py +32 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/provider.py +11 -1
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/registry.py +34 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/spec_metamodel/__init__.py +19 -2
- metaobjects-0.20.13/tests/codegen/test_cli_config_gen.py +224 -0
- metaobjects-0.20.13/tests/codegen/test_cli_config_verify.py +154 -0
- metaobjects-0.20.13/tests/codegen/test_project_config.py +136 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/test_provider_composition_conformance.py +79 -2
- metaobjects-0.20.13/tests/loader/test_enum_extends_values_conflict.py +167 -0
- metaobjects-0.20.13/tests/unit/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/uv.lock +1 -1
- {metaobjects-0.19.9 → metaobjects-0.20.13}/.gitignore +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/LICENSE +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/README.md +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/hatch_build.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/agent_context/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/agent_context/scaffold.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/apidocs/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/apidocs/api_model.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/apidocs/builder.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/apidocs/naming.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/apidocs/paths.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/apidocs/renderer.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/attr_class_map.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/collision_names.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/config.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/constants.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/extract_delegate_emitter.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/extract_schema_emitter.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/format.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/fr010_field_mapping.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/generator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/generator_registry.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/generators/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/generators/entity_model.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/generators/extractor_generator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/generators/filter_allowlist_generator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/generators/fr019_shared_enum.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/generators/m2m_codegen.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/generators/output_parser_generator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/generators/output_prompt_generator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/generators/payload_vo_generator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/generators/render_helper_generator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/generators/router_generator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/generators/template_generator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/generators/tph_plan.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/generators/trace_helper_generator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/instance_artifacts.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/output_format_spec_emitter.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/overwrite_policy.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/runner.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/runtime/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/runtime/filter_parser.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/template_codegen/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/template_codegen/output_pattern.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/template_codegen/template_data.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/template_codegen/template_spec.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/codegen/type_map.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/datatype.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/documentation/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/documentation/doc_constants.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/documentation/doc_provider.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/documentation/doc_schema.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/loader/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/loader/merge.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/loader/meta_data_loader.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/loader/registered_validation.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/loader/sources/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/loader/sources/directory_source.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/loader/sources/file_source.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/loader/sources/meta_data_source.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/loader/sources/uri_source.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/loader/validate_discriminator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/loader/validate_field_readonly.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/loader/validate_source_escapes.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/loader/validate_source_parameter_ref.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/loader/validate_source_physical_names.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/attr/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/attr/attr_constants.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/attr/meta_attr.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/field/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/field/field_constants.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/field/meta_field.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/identity/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/identity/identity_constants.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/identity/meta_identity.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/index/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/index/index_constants.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/index/meta_index.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/object/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/object/meta_object.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/object/meta_object_aware.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/object/object_class_registry.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/object/object_constants.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/object/object_extract.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/object/value_object.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/relationship/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/relationship/derive_m2m_fields.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/relationship/meta_relationship.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/relationship/relationship_constants.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/validator/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/core/validator/validator_constants.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/meta_data.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/meta_root.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/persistence/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/persistence/db/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/persistence/db/db_constants.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/persistence/db/db_provider.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/persistence/origin/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/persistence/origin/meta_origin.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/persistence/origin/origin_constants.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/persistence/source/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/persistence/source/meta_source.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/persistence/source/source_constants.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/presentation/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/presentation/layout/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/presentation/layout/layout_constants.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/presentation/layout/meta_layout.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/presentation/ui/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/presentation/ui/ui_provider.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/presentation/view/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/presentation/view/meta_view.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/presentation/view/view_constants.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/provider_extends.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/template/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/template/meta_template.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/template/prompt_provider.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/meta/template/template_constants.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/naming_refs.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/parser.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/parser_yaml.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/py.typed +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/registry_manifest.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/email_document.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/escapers.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/extract/KNOWN_GAPS.md +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/extract/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/extract/coerce.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/extract/extract.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/extract/extract_map.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/extract/json_forgiving_reader.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/extract/locate.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/extract/normalize.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/extract/strip.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/extract/types.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/extract/xml_forgiving_reader.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/filesystem_provider.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/prompt/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/prompt/output_format_renderer.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/prompt/output_format_spec.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/prompt/prompt_field.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/prompt/prompt_overrides.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/prompt/prompt_style.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/renderer.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/render/verify.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/runtime/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/runtime/llm_recorder.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/runtime/n2m_resolver.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/runtime/object_manager.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/runtime/tph.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/serializer_json.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/shared/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/shared/base_types.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/shared/separators.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/shared/structural.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/source/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/source/error_source.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/source/json_path.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/source/semantic_diff.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/source/yaml_positions.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/spec_metamodel/attr.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/spec_metamodel/db.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/spec_metamodel/documentation.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/spec_metamodel/field.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/spec_metamodel/identity.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/spec_metamodel/index.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/spec_metamodel/layout.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/spec_metamodel/object.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/spec_metamodel/origin.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/spec_metamodel/prompt.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/spec_metamodel/relationship.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/spec_metamodel/source.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/spec_metamodel/template.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/spec_metamodel/ui-web.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/spec_metamodel/ui.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/spec_metamodel/validator.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/spec_metamodel/view.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/super_resolve.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/validation_types.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/src/metaobjects/yaml_desugar.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/golden/extends/expected/BaseEntity.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/golden/extends/expected/Program.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/golden/extends/meta.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/golden/nested-array/expected/AuthorBrief.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/golden/nested-array/expected/PostBrief.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/golden/nested-array/meta.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/golden/scalars/expected/Metric.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/golden/scalars/expected/Report.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/golden/scalars/meta.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/golden/vanilla/expected/Subscriber.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/golden/vanilla/meta.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_abstract_conformance.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_api_docs_builder.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_api_docs_paths.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_cli.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_cli_providers.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_cli_registry.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_cli_staleness_nudge.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_cli_verify_strict.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_cli_verify_subverbs.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_constants_config.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_entity_model.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_enum_conformance.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_extends_abstract_field_inheritance.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_extract_tier_collision.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_extractor_generator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_filter_allowlist_generator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_format.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_fr010_nested_object_prompt.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_fr010_output_codegen.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_fr019_shared_provided_conformance.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_generator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_generator_extension_seams.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_golden.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_inherit_without_restate_gate.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_inheritance_conformance.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_instance_artifacts.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_m2m_codegen.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_origin_nullability.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_output_parser_generator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_overwrite_policy.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_payload_vo_generator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_projection_compile.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_render_helper_conformance.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_render_helper_generator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_reverse_finders.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_router_autoset.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_router_generator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_runner.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_template_data.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_template_generator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_template_output_pattern.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_template_scope_helpers.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_template_scope_walk.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_template_spec.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_tph_codegen.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_trace_helper_generator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_type_map.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_validation_conformance.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/codegen/test_write_through.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/capabilities.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/conformance-expected-failures.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/conformance_adapter.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/corpus.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/expected_failures.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/fixture_discovery.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/navigator.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/test_api_docs_cross_port_conformance.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/test_conformance.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/test_extract_conformance.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/test_extract_object_verdict.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/test_fr010_loader_attrs.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/test_fr011_attrs.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/test_generator_registry_conformance.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/test_object_model_conformance.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/test_registry_conformance.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/test_runner_hardfail.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/test_spec_metamodel_embed.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/test_strict_attr_load.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/test_template_codegen_conformance.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/test_template_generator_conformance.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/test_yaml_conformance.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/conformance/yaml-conformance-expected-failures.json +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/api_contract_assertions.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/api_contract_jsonb_server.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/api_contract_m2m_server.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/api_contract_server.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/generated_jsonb_app.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/generated_m2m_app.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/generated_router_app.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/generated_tph_app.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/meta_ai_trace.yaml +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/normalization.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/postgres_container.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/query_runner.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/scenarios.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/test_api_contract.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/test_api_contract_generated.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/test_api_contract_jsonb.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/test_api_contract_m2m.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/test_api_contract_m2m_generated.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/test_api_contract_tph_generated.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/test_generated_router_uuid_pk.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/test_llm_call_trace.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/test_normalization.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/test_query_scenarios.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/integration/test_runtime_return_types.py +0 -0
- {metaobjects-0.19.9/tests/render → metaobjects-0.20.13/tests/loader}/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/open_closed_proof_test.py +0 -0
- {metaobjects-0.19.9/tests/render/extract → metaobjects-0.20.13/tests/render}/__init__.py +0 -0
- {metaobjects-0.19.9/tests/render/prompt → metaobjects-0.20.13/tests/render/extract}/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/render/extract/test_coerce.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/render/extract/test_extract.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/render/extract/test_extract_map.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/render/extract/test_json_forgiving_reader.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/render/extract/test_locate.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/render/extract/test_model.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/render/extract/test_normalize.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/render/extract/test_strip.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/render/extract/test_xml_forgiving_reader.py +0 -0
- {metaobjects-0.19.9/tests/source → metaobjects-0.20.13/tests/render/prompt}/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/render/prompt/test_output_format_renderer.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/render/test_email_document.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/render/test_filesystem_provider.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/render/test_output_format_renderer_nested.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/render/test_output_prompt_conformance.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/render/test_render_conformance.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/render/test_render_max_chars.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/render/test_verify.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/render/test_verify_conformance.py +0 -0
- {metaobjects-0.19.9/tests/unit → metaobjects-0.20.13/tests/source}/__init__.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/source/test_fr5c_merge_attribution.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/source/test_fr5d_reference_resolution.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/source/test_fr5e_database_source_shape.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/source/test_json_path.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/source/test_semantic_diff.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/source/test_source_on_node.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/source/test_yaml_positions.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/test_api_docs_accuracy.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_agent_context_staleness.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_capabilities.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_common_attrs.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_core_types.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_effective_package.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_errors.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_field_enum.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_field_map_validation.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_field_uuid_dbcolumntype.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_fr016_source_name_and_kind_aliases.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_index_lookup.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_llm_recorder.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_loader.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_loader_bom.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_loader_class.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_merge.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_meta_attr.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_meta_data.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_meta_source.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_module_shortcuts.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_n2m_resolver.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_n2m_resolver_inherited.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_object_manager_autoset_stamping.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_object_manager_uuid_coercion.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_object_manager_write_through.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_one_primary_source.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_parser.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_parser_yaml.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_provider.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_provider_extension.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_registry.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_registry_completeness.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_registry_extend.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_registry_sealed.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_relationship_referential_actions.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_resolution_key.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_runtime_resolution_key_binding.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_serializer.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_shared_constants.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_smoke.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_source_escapes.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_sources.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_strict_child_placement.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_super_resolve.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_template_toolcall.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_template_wrong_subtype_attrs.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_validation_attr_schema.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_validation_filter_values.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_validation_origin_195.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_validation_origin_paths.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_validation_sort_field.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_validation_warnings.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/tests/unit/test_write_coercion_arrays.py +0 -0
- {metaobjects-0.19.9 → metaobjects-0.20.13}/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.
|
|
3
|
+
Version: 0.20.13
|
|
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.
|
|
3
|
+
version = "0.20.13"
|
|
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"
|
|
@@ -39,7 +39,9 @@ generator-wiring divergence between the two commands.
|
|
|
39
39
|
from __future__ import annotations
|
|
40
40
|
|
|
41
41
|
import argparse
|
|
42
|
+
import dataclasses
|
|
42
43
|
import json
|
|
44
|
+
import re
|
|
43
45
|
import sys
|
|
44
46
|
import tempfile
|
|
45
47
|
from pathlib import Path
|
|
@@ -52,6 +54,13 @@ from metaobjects.agent_context import (
|
|
|
52
54
|
)
|
|
53
55
|
from metaobjects.meta.meta_data import MetaData
|
|
54
56
|
from metaobjects.codegen.config import GenConfig
|
|
57
|
+
from metaobjects.codegen.project_config import (
|
|
58
|
+
CONFIG_FILENAME,
|
|
59
|
+
ConfigError,
|
|
60
|
+
ProjectConfig,
|
|
61
|
+
TargetConfig,
|
|
62
|
+
load_project_config,
|
|
63
|
+
)
|
|
55
64
|
from metaobjects.codegen.generator import Generator
|
|
56
65
|
from metaobjects.codegen.generators.entity_model import entity_model
|
|
57
66
|
from metaobjects.codegen.generators.extractor_generator import extractor_generator
|
|
@@ -180,6 +189,48 @@ def _providers_from_args(args: argparse.Namespace) -> tuple[list[object], bool]:
|
|
|
180
189
|
return providers, True
|
|
181
190
|
|
|
182
191
|
|
|
192
|
+
def _find_config(args: argparse.Namespace) -> Path | None:
|
|
193
|
+
"""The config path: ``--config`` if given (even if missing → clear load error),
|
|
194
|
+
else ``./metaobjects.config.yaml`` in cwd when it exists, else ``None``."""
|
|
195
|
+
explicit = getattr(args, "config", None)
|
|
196
|
+
if explicit:
|
|
197
|
+
return Path(explicit)
|
|
198
|
+
default = Path.cwd() / CONFIG_FILENAME
|
|
199
|
+
return default if default.is_file() else None
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def _config_providers(config: ProjectConfig) -> tuple[list[object], bool]:
|
|
203
|
+
"""Resolve ``config.providers`` with the config file's directory on ``sys.path``.
|
|
204
|
+
|
|
205
|
+
#267: prepend the config directory so a ``module:symbol`` provider living beside
|
|
206
|
+
the config imports with no ``PYTHONPATH=``. Idempotent; the entry is left in
|
|
207
|
+
place (a short-lived CLI process). Prints resolution errors; returns (providers, ok).
|
|
208
|
+
"""
|
|
209
|
+
config_dir = str(config.config_dir)
|
|
210
|
+
if config_dir not in sys.path:
|
|
211
|
+
sys.path.insert(0, config_dir)
|
|
212
|
+
providers, errors = _resolve_providers(config.providers)
|
|
213
|
+
if errors:
|
|
214
|
+
print("error: invalid provider in config:", file=sys.stderr)
|
|
215
|
+
for msg in errors:
|
|
216
|
+
print(f" {msg}", file=sys.stderr)
|
|
217
|
+
return providers, False
|
|
218
|
+
return providers, True
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def _select_targets(
|
|
222
|
+
config: ProjectConfig, target_name: str | None
|
|
223
|
+
) -> tuple[list[TargetConfig], str | None]:
|
|
224
|
+
"""All targets, or the single ``--target`` (error string when the name is unknown)."""
|
|
225
|
+
if target_name is None:
|
|
226
|
+
return config.targets, None
|
|
227
|
+
t = config.target(target_name)
|
|
228
|
+
if t is None:
|
|
229
|
+
known = ", ".join(sorted(x.name for x in config.targets))
|
|
230
|
+
return [], f"unknown --target {target_name!r}; known targets: {known}"
|
|
231
|
+
return [t], None
|
|
232
|
+
|
|
233
|
+
|
|
183
234
|
def _load_root(
|
|
184
235
|
metadata_dir: str,
|
|
185
236
|
strict: bool = False,
|
|
@@ -422,9 +473,14 @@ def _cmd_gen(args: argparse.Namespace) -> int:
|
|
|
422
473
|
|
|
423
474
|
_warn_if_agent_context_stale()
|
|
424
475
|
|
|
425
|
-
|
|
476
|
+
# #267: config mode ⇔ no positional <metadata_dir>. The explicit
|
|
477
|
+
# <metadata_dir> + --out flag path below is untouched (byte-identical).
|
|
478
|
+
if args.metadata_dir is None:
|
|
479
|
+
return _cmd_gen_config(args)
|
|
480
|
+
if args.out is None:
|
|
426
481
|
print(
|
|
427
|
-
"error: gen requires <metadata_dir> and --out
|
|
482
|
+
"error: gen requires <metadata_dir> and --out "
|
|
483
|
+
"(or a metaobjects.config.yaml / --list).",
|
|
428
484
|
file=sys.stderr,
|
|
429
485
|
)
|
|
430
486
|
return 2
|
|
@@ -495,6 +551,100 @@ def _cmd_gen(args: argparse.Namespace) -> int:
|
|
|
495
551
|
return 0
|
|
496
552
|
|
|
497
553
|
|
|
554
|
+
def _run_gen_targets(
|
|
555
|
+
config: ProjectConfig, targets: list[TargetConfig], root: MetaData
|
|
556
|
+
) -> tuple[list[str], list[str]]:
|
|
557
|
+
"""Run each target's suite into its ``outDir``. Returns (all_written, errors).
|
|
558
|
+
|
|
559
|
+
Cross-target duplicate-output-path guard (#267): ``run_gen``'s collision guard
|
|
560
|
+
is per-pass, so two targets writing the same full path would silently clobber
|
|
561
|
+
(generated files carry the @generated header). We accumulate every written full
|
|
562
|
+
path across targets and record an error when two targets emit the same one.
|
|
563
|
+
(Detection is post-write — the colliding file may already be on disk — but the
|
|
564
|
+
command still fails, so a misconfigured gate is caught in CI.)
|
|
565
|
+
"""
|
|
566
|
+
all_written: list[str] = []
|
|
567
|
+
seen: dict[str, str] = {} # full path -> target name
|
|
568
|
+
errors: list[str] = []
|
|
569
|
+
for t in targets:
|
|
570
|
+
gens: list[Generator] | None = None
|
|
571
|
+
if t.generators is not None:
|
|
572
|
+
gens, gen_errors = _resolve_generators(",".join(t.generators))
|
|
573
|
+
if gen_errors:
|
|
574
|
+
errors.extend(f"target '{t.name}': {m}" for m in gen_errors)
|
|
575
|
+
continue
|
|
576
|
+
out_dir = config.out_dir_for(t)
|
|
577
|
+
try:
|
|
578
|
+
written = _run_suite(root, out_dir, gens, t.entities)
|
|
579
|
+
except ValueError as exc: # intra-target run_gen collision → clean error
|
|
580
|
+
errors.append(f"target '{t.name}': {exc}")
|
|
581
|
+
continue
|
|
582
|
+
for full in written:
|
|
583
|
+
if Path(full).name == "__init__.py":
|
|
584
|
+
continue # auto-emitted package marker — byte-identical across targets sharing an outDir; not a real collision
|
|
585
|
+
prior = seen.get(full)
|
|
586
|
+
if prior is not None and prior != t.name:
|
|
587
|
+
errors.append(
|
|
588
|
+
f"duplicate output path across targets: {full!r} written by "
|
|
589
|
+
f"both '{prior}' and '{t.name}'."
|
|
590
|
+
)
|
|
591
|
+
else:
|
|
592
|
+
seen[full] = t.name
|
|
593
|
+
all_written.extend(written)
|
|
594
|
+
return all_written, errors
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
def _cmd_gen_config(args: argparse.Namespace) -> int:
|
|
598
|
+
"""``gen`` with no positional ``metadata_dir`` → declarative-config mode (#267).
|
|
599
|
+
|
|
600
|
+
Load ``metaobjects.config.yaml``, load metadata ONCE, and run every target
|
|
601
|
+
(or ``--target``) into its own ``outDir`` with a cross-target duplicate-path
|
|
602
|
+
guard. Providers resolve relative to the config file (no ``PYTHONPATH=``).
|
|
603
|
+
"""
|
|
604
|
+
config_path = _find_config(args)
|
|
605
|
+
if config_path is None:
|
|
606
|
+
print(
|
|
607
|
+
"error: no <metadata_dir> given and no metaobjects.config.yaml found. "
|
|
608
|
+
"Either pass <metadata_dir> --out (flag mode) or create a "
|
|
609
|
+
"metaobjects.config.yaml (or pass --config <path>).",
|
|
610
|
+
file=sys.stderr,
|
|
611
|
+
)
|
|
612
|
+
return 2
|
|
613
|
+
try:
|
|
614
|
+
config = load_project_config(config_path)
|
|
615
|
+
except ConfigError as exc:
|
|
616
|
+
print(f"error: {exc}", file=sys.stderr)
|
|
617
|
+
return 1
|
|
618
|
+
|
|
619
|
+
targets, target_err = _select_targets(config, getattr(args, "target", None))
|
|
620
|
+
if target_err:
|
|
621
|
+
print(f"error: {target_err}", file=sys.stderr)
|
|
622
|
+
return 1
|
|
623
|
+
|
|
624
|
+
providers, providers_ok = _config_providers(config)
|
|
625
|
+
if not providers_ok:
|
|
626
|
+
return 1
|
|
627
|
+
|
|
628
|
+
root, load_errors = _load_root(config.metadata_dir(), providers=providers)
|
|
629
|
+
if root is None:
|
|
630
|
+
print("error: failed to load metadata:", file=sys.stderr)
|
|
631
|
+
for msg in load_errors:
|
|
632
|
+
print(f" {msg}", file=sys.stderr)
|
|
633
|
+
return 1
|
|
634
|
+
|
|
635
|
+
written, errors = _run_gen_targets(config, targets, root)
|
|
636
|
+
if errors:
|
|
637
|
+
for msg in errors:
|
|
638
|
+
print(f"error: {msg}", file=sys.stderr)
|
|
639
|
+
return 1
|
|
640
|
+
for path in written:
|
|
641
|
+
print(path)
|
|
642
|
+
print(
|
|
643
|
+
f"metaobjects gen: wrote {len(written)} file(s) across {len(targets)} target(s)."
|
|
644
|
+
)
|
|
645
|
+
return 0
|
|
646
|
+
|
|
647
|
+
|
|
498
648
|
def _relative_set(root: Path) -> dict[str, str]:
|
|
499
649
|
"""Map every ``*.py`` file under ``root`` to its content, keyed by rel path.
|
|
500
650
|
|
|
@@ -516,6 +666,10 @@ def _verify_codegen(args: argparse.Namespace) -> int:
|
|
|
516
666
|
code path (gen-to-temp + diff), so drift can never be a generator-wiring
|
|
517
667
|
divergence between the two commands.
|
|
518
668
|
"""
|
|
669
|
+
# #267: config mode ⇔ no positional <metadata_dir>. The legacy
|
|
670
|
+
# <metadata_dir> + --out diff below is untouched.
|
|
671
|
+
if args.metadata_dir is None:
|
|
672
|
+
return _verify_codegen_config(args)
|
|
519
673
|
if args.out is None:
|
|
520
674
|
print(
|
|
521
675
|
"error: verify --codegen requires --out (the committed output dir).",
|
|
@@ -572,6 +726,139 @@ def _verify_codegen(args: argparse.Namespace) -> int:
|
|
|
572
726
|
return 1
|
|
573
727
|
|
|
574
728
|
|
|
729
|
+
def _temp_slot_for(temp_root: Path, real_outdir: str, config_dir: Path) -> str:
|
|
730
|
+
"""The temp mirror of a committed ``outDir``.
|
|
731
|
+
|
|
732
|
+
Keyed by the real outDir's path relative to ``config_dir`` when it lives under
|
|
733
|
+
it, else a sanitized flat name — mirroring the TS ``computeCodegenDrift``
|
|
734
|
+
``tempFor``. Two targets sharing a real outDir map to the SAME slot so their
|
|
735
|
+
co-resident regen accumulates into one tree: the diff is then union-of-
|
|
736
|
+
co-resident-regen vs the shared committed dir, so the other target's files are
|
|
737
|
+
never false ``extra`` drift.
|
|
738
|
+
"""
|
|
739
|
+
try:
|
|
740
|
+
rel = Path(real_outdir).relative_to(config_dir)
|
|
741
|
+
except ValueError:
|
|
742
|
+
rel = None
|
|
743
|
+
if rel is None:
|
|
744
|
+
safe = re.sub(r"[^A-Za-z0-9]+", "_", real_outdir)
|
|
745
|
+
return str(temp_root / safe)
|
|
746
|
+
return str(temp_root / rel)
|
|
747
|
+
|
|
748
|
+
|
|
749
|
+
def _verify_codegen_config(args: argparse.Namespace) -> int:
|
|
750
|
+
"""``verify --codegen`` with no positional ``metadata_dir`` → config mode (#267).
|
|
751
|
+
|
|
752
|
+
Symmetric with ``gen`` config mode: ONE whole-selection regen into a temp tree
|
|
753
|
+
(reusing :func:`_run_gen_targets` — the exact gen pipeline, so verify rejects
|
|
754
|
+
exactly what gen rejects, including the cross-target duplicate-output-path
|
|
755
|
+
guard), then a diff per UNIQUE real outDir. Targets that share an outDir are
|
|
756
|
+
verified TOGETHER — the diff is the union of their co-resident regen vs the
|
|
757
|
+
shared committed dir, so a shared outDir is never a false-positive ``extra``
|
|
758
|
+
drift (mirrors the TS ``computeCodegenDrift`` unit = unique outDir).
|
|
759
|
+
``--target`` widens to the outDir-sharing closure (an outDir is verified as a
|
|
760
|
+
unit). Strict-by-default (ADR-0023) unless ``--lax``.
|
|
761
|
+
"""
|
|
762
|
+
config_path = _find_config(args)
|
|
763
|
+
if config_path is None:
|
|
764
|
+
print(
|
|
765
|
+
"error: verify --codegen with no <metadata_dir> requires a "
|
|
766
|
+
"metaobjects.config.yaml (or --config <path>).",
|
|
767
|
+
file=sys.stderr,
|
|
768
|
+
)
|
|
769
|
+
return 2
|
|
770
|
+
try:
|
|
771
|
+
config = load_project_config(config_path)
|
|
772
|
+
except ConfigError as exc:
|
|
773
|
+
print(f"error: {exc}", file=sys.stderr)
|
|
774
|
+
return 1
|
|
775
|
+
|
|
776
|
+
selected, target_err = _select_targets(config, getattr(args, "target", None))
|
|
777
|
+
if target_err:
|
|
778
|
+
print(f"error: {target_err}", file=sys.stderr)
|
|
779
|
+
return 1
|
|
780
|
+
|
|
781
|
+
# Widen to the outDir-sharing closure: a shared outDir is verified as a unit,
|
|
782
|
+
# so --target a (whose outDir b also writes) pulls b in.
|
|
783
|
+
selected_outdirs = {config.out_dir_for(t) for t in selected}
|
|
784
|
+
closure = [t for t in config.targets if config.out_dir_for(t) in selected_outdirs]
|
|
785
|
+
added = [t.name for t in closure if t not in selected]
|
|
786
|
+
if added:
|
|
787
|
+
target_arg = getattr(args, "target", None)
|
|
788
|
+
print(
|
|
789
|
+
f"note: --target {target_arg!r} shares an outDir with "
|
|
790
|
+
f"{', '.join(added)}; verifying the shared outDir as a unit.",
|
|
791
|
+
file=sys.stderr,
|
|
792
|
+
)
|
|
793
|
+
|
|
794
|
+
strict = not getattr(args, "lax", False)
|
|
795
|
+
providers, providers_ok = _config_providers(config)
|
|
796
|
+
if not providers_ok:
|
|
797
|
+
return 1
|
|
798
|
+
|
|
799
|
+
root, load_errors = _load_root(config.metadata_dir(), strict=strict, providers=providers)
|
|
800
|
+
if root is None:
|
|
801
|
+
print("error: failed to load metadata:", file=sys.stderr)
|
|
802
|
+
for msg in load_errors:
|
|
803
|
+
print(f" {msg}", file=sys.stderr)
|
|
804
|
+
if strict and any("ERR_UNKNOWN_ATTR" in m for m in load_errors):
|
|
805
|
+
print(_strict_load_hint(), file=sys.stderr)
|
|
806
|
+
return 1
|
|
807
|
+
|
|
808
|
+
with tempfile.TemporaryDirectory() as temp_root:
|
|
809
|
+
# Map each unique real outDir to ONE temp slot (shared real dir => shared slot).
|
|
810
|
+
temp_for: dict[str, str] = {}
|
|
811
|
+
for t in closure:
|
|
812
|
+
real = config.out_dir_for(t)
|
|
813
|
+
if real not in temp_for:
|
|
814
|
+
temp_for[real] = _temp_slot_for(Path(temp_root), real, config.config_dir)
|
|
815
|
+
remapped = [
|
|
816
|
+
dataclasses.replace(t, out_dir=temp_for[config.out_dir_for(t)]) for t in closure
|
|
817
|
+
]
|
|
818
|
+
|
|
819
|
+
# The exact gen pipeline into the temp tree — verify now rejects exactly
|
|
820
|
+
# what gen rejects (incl. the cross-target duplicate-output-path guard).
|
|
821
|
+
_written, errors = _run_gen_targets(config, remapped, root)
|
|
822
|
+
if errors:
|
|
823
|
+
for msg in errors:
|
|
824
|
+
print(f"error: {msg}", file=sys.stderr)
|
|
825
|
+
return 1
|
|
826
|
+
|
|
827
|
+
exit_code = 0
|
|
828
|
+
for real_outdir in sorted(temp_for):
|
|
829
|
+
tmp_slot = temp_for[real_outdir]
|
|
830
|
+
expected = _relative_set(Path(tmp_slot))
|
|
831
|
+
committed = _relative_set(Path(real_outdir))
|
|
832
|
+
|
|
833
|
+
changed = sorted(
|
|
834
|
+
k for k in expected if k in committed and expected[k] != committed[k]
|
|
835
|
+
)
|
|
836
|
+
missing = sorted(k for k in expected if k not in committed)
|
|
837
|
+
extra = sorted(k for k in committed if k not in expected)
|
|
838
|
+
|
|
839
|
+
names = "+".join(
|
|
840
|
+
t.name for t in closure if config.out_dir_for(t) == real_outdir
|
|
841
|
+
)
|
|
842
|
+
if not changed and not missing and not extra:
|
|
843
|
+
print(
|
|
844
|
+
f"metaobjects verify [{names}]: in sync ({len(expected)} file(s))."
|
|
845
|
+
)
|
|
846
|
+
continue
|
|
847
|
+
exit_code = max(exit_code, 1)
|
|
848
|
+
print(
|
|
849
|
+
f"error: [{names}] generated code is out of sync with metadata.",
|
|
850
|
+
file=sys.stderr,
|
|
851
|
+
)
|
|
852
|
+
for k in changed:
|
|
853
|
+
print(f" drifted: {k}", file=sys.stderr)
|
|
854
|
+
for k in missing:
|
|
855
|
+
print(f" missing: {k}", file=sys.stderr)
|
|
856
|
+
for k in extra:
|
|
857
|
+
print(f" extra: {k}", file=sys.stderr)
|
|
858
|
+
print("regenerate (metaobjects gen) and commit the result.", file=sys.stderr)
|
|
859
|
+
return exit_code
|
|
860
|
+
|
|
861
|
+
|
|
575
862
|
#: The text-ref attrs a ``template.*`` node may carry. Each is resolved through
|
|
576
863
|
#: the filesystem provider and run through the render ``verify()`` gate. A prompt
|
|
577
864
|
#: / document uses ``@textRef``; an email uses subject / html / (optional) text
|
|
@@ -607,6 +894,14 @@ def _verify_templates(args: argparse.Namespace) -> int:
|
|
|
607
894
|
(exit 1). Clean → 0. Reuses the render engine + field-tree walk; nothing is
|
|
608
895
|
reimplemented here.
|
|
609
896
|
"""
|
|
897
|
+
if args.metadata_dir is None:
|
|
898
|
+
print(
|
|
899
|
+
"error: verify --templates requires <metadata_dir> (it is not "
|
|
900
|
+
"config-driven; the config's targets registry drives --codegen only).",
|
|
901
|
+
file=sys.stderr,
|
|
902
|
+
)
|
|
903
|
+
return 2
|
|
904
|
+
|
|
610
905
|
template_root = getattr(args, "templates_root", None)
|
|
611
906
|
if not template_root:
|
|
612
907
|
print(
|
|
@@ -855,6 +1150,20 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
855
1150
|
"resolves through the standalone CLI (#158)"
|
|
856
1151
|
),
|
|
857
1152
|
)
|
|
1153
|
+
gen.add_argument(
|
|
1154
|
+
"--config",
|
|
1155
|
+
default=None,
|
|
1156
|
+
help=(
|
|
1157
|
+
"path to a metaobjects.config.yaml (declarative targets registry). "
|
|
1158
|
+
"Config mode runs when no <metadata_dir> is given; default lookup is "
|
|
1159
|
+
"./metaobjects.config.yaml in cwd."
|
|
1160
|
+
),
|
|
1161
|
+
)
|
|
1162
|
+
gen.add_argument(
|
|
1163
|
+
"--target",
|
|
1164
|
+
default=None,
|
|
1165
|
+
help="run only this named target from the config (default: every target)",
|
|
1166
|
+
)
|
|
858
1167
|
gen.set_defaults(func=_cmd_gen)
|
|
859
1168
|
|
|
860
1169
|
docs = sub.add_parser(
|
|
@@ -902,7 +1211,15 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
902
1211
|
"(ADR-0021 D2); bare verify defaults to --codegen"
|
|
903
1212
|
),
|
|
904
1213
|
)
|
|
905
|
-
verify.add_argument(
|
|
1214
|
+
verify.add_argument(
|
|
1215
|
+
"metadata_dir",
|
|
1216
|
+
nargs="?",
|
|
1217
|
+
default=None,
|
|
1218
|
+
help=(
|
|
1219
|
+
"directory of metadata JSON/YAML files. Omit to use a "
|
|
1220
|
+
"metaobjects.config.yaml (--codegen config mode, #267)."
|
|
1221
|
+
),
|
|
1222
|
+
)
|
|
906
1223
|
verify.add_argument(
|
|
907
1224
|
"--codegen",
|
|
908
1225
|
action="store_true",
|
|
@@ -953,6 +1270,20 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
953
1270
|
metavar="module:symbol",
|
|
954
1271
|
help="load a consumer metadata Provider as 'module:symbol' (repeatable; #158)",
|
|
955
1272
|
)
|
|
1273
|
+
verify.add_argument(
|
|
1274
|
+
"--config",
|
|
1275
|
+
default=None,
|
|
1276
|
+
help=(
|
|
1277
|
+
"path to a metaobjects.config.yaml. Config mode runs when no "
|
|
1278
|
+
"<metadata_dir> is given; default ./metaobjects.config.yaml in cwd. "
|
|
1279
|
+
"Drives --codegen per-target regen+diff."
|
|
1280
|
+
),
|
|
1281
|
+
)
|
|
1282
|
+
verify.add_argument(
|
|
1283
|
+
"--target",
|
|
1284
|
+
default=None,
|
|
1285
|
+
help="verify only this named target from the config (default: every target)",
|
|
1286
|
+
)
|
|
956
1287
|
verify.set_defaults(func=_cmd_verify)
|
|
957
1288
|
|
|
958
1289
|
agent_docs = sub.add_parser(
|
|
@@ -47,7 +47,9 @@ the path-resolution and import-base machinery that is not yet on the
|
|
|
47
47
|
Python codegen surface). Consumers wanting strong typing can hand-edit
|
|
48
48
|
the generated router to import their preferred entity shape.
|
|
49
49
|
|
|
50
|
-
**When it ships:**
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
`from .<snake>_entity import <Entity>`
|
|
50
|
+
**When it ships:** the Python codegen now has a per-target output-directory
|
|
51
|
+
targets registry via the declarative `metaobjects.config.yaml` (#267 — mirrors
|
|
52
|
+
the TS `targets` registry). The remaining deferred piece is the router→entity-model
|
|
53
|
+
import wiring itself (`from .<snake>_entity import <Entity>`), which still needs the
|
|
54
|
+
path-resolution/import-base machinery; the config's per-target `outDir` is the
|
|
55
|
+
prerequisite that is now in place.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://metaobjects.dev/schemas/metaobjects-config.schema.json",
|
|
4
|
+
"title": "MetaObjects Python codegen config",
|
|
5
|
+
"description": "Declarative config for the `metaobjects` Python CLI (#267). Schema keys mirror the TS metaobjects.config.ts vocabulary (outDir/generators/entities/providers/metadata).",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["targets"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"metadata": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"description": "Metadata directory, relative to this config file. Default: metaobjects",
|
|
13
|
+
"default": "metaobjects"
|
|
14
|
+
},
|
|
15
|
+
"providers": {
|
|
16
|
+
"type": "array",
|
|
17
|
+
"items": { "type": "string", "pattern": "^[^:]+:[^:]+$" },
|
|
18
|
+
"description": "Consumer provider refs as 'module:symbol', resolved relative to this config file's directory (no PYTHONPATH needed)."
|
|
19
|
+
},
|
|
20
|
+
"targets": {
|
|
21
|
+
"type": "object",
|
|
22
|
+
"minProperties": 1,
|
|
23
|
+
"description": "Named run-specs; each key is a target name.",
|
|
24
|
+
"additionalProperties": {
|
|
25
|
+
"type": "object",
|
|
26
|
+
"additionalProperties": false,
|
|
27
|
+
"required": ["outDir"],
|
|
28
|
+
"properties": {
|
|
29
|
+
"outDir": {
|
|
30
|
+
"type": "string",
|
|
31
|
+
"description": "Output directory, relative to this config file."
|
|
32
|
+
},
|
|
33
|
+
"generators": {
|
|
34
|
+
"type": "array",
|
|
35
|
+
"items": { "type": "string" },
|
|
36
|
+
"description": "Stable generator names (see `metaobjects gen --list`). Omit to run the default suite."
|
|
37
|
+
},
|
|
38
|
+
"entities": {
|
|
39
|
+
"type": "array",
|
|
40
|
+
"items": { "type": "string" },
|
|
41
|
+
"description": "Entity-name allowlist. Omit to emit every entity."
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""Declarative project config for the Python codegen CLI (#267).
|
|
2
|
+
|
|
3
|
+
`metaobjects.config.yaml` describes a project's codegen surface once — a targets
|
|
4
|
+
registry (per-target ``outDir`` + generator selection + entity allowlist), the
|
|
5
|
+
metadata dir, and consumer providers — so ``metaobjects gen`` / ``verify --codegen``
|
|
6
|
+
run every target with no flags and provider modules resolve relative to the config
|
|
7
|
+
(no ``PYTHONPATH=``). YAML, not ``.py``: Python's config surface is pure data (the
|
|
8
|
+
provider CODE stays in its module, referenced by ``module:symbol`` per #158) —
|
|
9
|
+
unlike TS's executable ``metaobjects.config.ts`` (ADR-0034 owned generators / live
|
|
10
|
+
providers).
|
|
11
|
+
|
|
12
|
+
Schema keys are IDENTICAL to the TS ``metaobjects.config.ts`` vocabulary
|
|
13
|
+
(``targets.<name>.{outDir, generators, entities}``, ``providers``, ``metadata``) so
|
|
14
|
+
a polyglot adopter learns one vocabulary; the file SURFACE differs per port, the
|
|
15
|
+
SCHEMA does not (ADR-0021 D3 / FR-025). A JSON Schema ships beside this loader
|
|
16
|
+
(``metaobjects-config.schema.json``) for editor autocomplete + non-Python
|
|
17
|
+
validation.
|
|
18
|
+
|
|
19
|
+
Python-only, additive: no metamodel/vocabulary change; the existing positional
|
|
20
|
+
``metadata_dir`` + ``--out`` flag path is untouched and byte-identical.
|
|
21
|
+
"""
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
from dataclasses import dataclass
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
|
|
27
|
+
import yaml # type: ignore[import-untyped] # PyYAML ships no type stubs
|
|
28
|
+
|
|
29
|
+
#: Config filename looked up in the cwd when ``--config`` is not given.
|
|
30
|
+
CONFIG_FILENAME = "metaobjects.config.yaml"
|
|
31
|
+
|
|
32
|
+
#: Default metadata directory (relative to the config file) when ``metadata:`` is omitted.
|
|
33
|
+
DEFAULT_METADATA_DIR = "metaobjects"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ConfigError(ValueError):
|
|
37
|
+
"""A ``metaobjects.config.yaml`` that is missing, malformed, or invalid.
|
|
38
|
+
|
|
39
|
+
Carries a single user-facing message (no stack trace) — the CLI prints it and
|
|
40
|
+
exits non-zero.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass(frozen=True)
|
|
45
|
+
class TargetConfig:
|
|
46
|
+
"""One named run-spec: where to write + which generators/entities to run.
|
|
47
|
+
|
|
48
|
+
NOTE (cross-port reconciliation, design §Schema): TS ``targets`` are pure output
|
|
49
|
+
DESTINATIONS (a generator picks a target; ``TargetConfig`` carries no selection),
|
|
50
|
+
while a declarative-port target is a destination PLUS a selection (``generators``
|
|
51
|
+
+ ``entities``). The shared keys (``outDir``/``generators``/``entities``) stay
|
|
52
|
+
identical.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
#: The target's map key (``targets.<name>``).
|
|
56
|
+
name: str
|
|
57
|
+
#: Output directory, relative to the config file's directory (or absolute).
|
|
58
|
+
out_dir: str
|
|
59
|
+
#: Stable generator names (registry ids); ``None`` => the default suite.
|
|
60
|
+
generators: list[str] | None
|
|
61
|
+
#: Entity-name allowlist; ``None`` => every entity.
|
|
62
|
+
entities: list[str] | None
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@dataclass(frozen=True)
|
|
66
|
+
class ProjectConfig:
|
|
67
|
+
#: Directory containing the config file — the base for resolving ``metadata``,
|
|
68
|
+
#: ``providers`` (sys.path), and each target's ``outDir``.
|
|
69
|
+
config_dir: Path
|
|
70
|
+
#: Metadata directory (relative to ``config_dir`` or absolute).
|
|
71
|
+
metadata: str
|
|
72
|
+
#: Consumer provider refs (``module:symbol``), resolved config-relative.
|
|
73
|
+
providers: list[str]
|
|
74
|
+
#: Ordered run-specs (YAML map insertion order preserved).
|
|
75
|
+
targets: list[TargetConfig]
|
|
76
|
+
|
|
77
|
+
def metadata_dir(self) -> str:
|
|
78
|
+
"""The metadata dir resolved against ``config_dir`` (absolute path string)."""
|
|
79
|
+
return _resolve_under(self.config_dir, self.metadata)
|
|
80
|
+
|
|
81
|
+
def target(self, name: str) -> TargetConfig | None:
|
|
82
|
+
return next((t for t in self.targets if t.name == name), None)
|
|
83
|
+
|
|
84
|
+
def out_dir_for(self, target: TargetConfig) -> str:
|
|
85
|
+
"""``target.out_dir`` resolved against ``config_dir`` (absolute path string)."""
|
|
86
|
+
return _resolve_under(self.config_dir, target.out_dir)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _resolve_under(base: Path, p: str) -> str:
|
|
90
|
+
q = Path(p)
|
|
91
|
+
return str(q if q.is_absolute() else (base / q).resolve())
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _require_str_list(value: object, ctx: str) -> list[str]:
|
|
95
|
+
if not isinstance(value, list) or not all(isinstance(x, str) for x in value):
|
|
96
|
+
raise ConfigError(f"{ctx} must be a list of strings.")
|
|
97
|
+
return list(value)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def load_project_config(path: Path) -> ProjectConfig:
|
|
101
|
+
"""Parse + validate ``metaobjects.config.yaml`` at ``path``.
|
|
102
|
+
|
|
103
|
+
Raises :class:`ConfigError` (single user-facing message) on a missing file,
|
|
104
|
+
invalid YAML, or any shape violation. Defaults: ``metadata`` =>
|
|
105
|
+
``DEFAULT_METADATA_DIR``, ``providers`` => ``[]``, per-target ``generators`` /
|
|
106
|
+
``entities`` => ``None`` (default suite / all entities).
|
|
107
|
+
"""
|
|
108
|
+
if not path.is_file():
|
|
109
|
+
raise ConfigError(f"config file not found: {path}")
|
|
110
|
+
try:
|
|
111
|
+
text = path.read_text(encoding="utf-8")
|
|
112
|
+
except (OSError, UnicodeDecodeError) as exc:
|
|
113
|
+
raise ConfigError(f"{path}: cannot read config file: {exc}") from exc
|
|
114
|
+
try:
|
|
115
|
+
raw = yaml.safe_load(text)
|
|
116
|
+
except yaml.YAMLError as exc:
|
|
117
|
+
raise ConfigError(f"{path}: invalid YAML: {exc}") from exc
|
|
118
|
+
|
|
119
|
+
if raw is None:
|
|
120
|
+
raise ConfigError(f"{path}: config is empty.")
|
|
121
|
+
if not isinstance(raw, dict):
|
|
122
|
+
raise ConfigError(f"{path}: top level must be a mapping.")
|
|
123
|
+
|
|
124
|
+
metadata = raw.get("metadata", DEFAULT_METADATA_DIR)
|
|
125
|
+
if not isinstance(metadata, str):
|
|
126
|
+
raise ConfigError(f"{path}: 'metadata' must be a string (a directory path).")
|
|
127
|
+
|
|
128
|
+
providers = _require_str_list(raw.get("providers", []), f"{path}: 'providers'")
|
|
129
|
+
|
|
130
|
+
targets_raw = raw.get("targets")
|
|
131
|
+
if not isinstance(targets_raw, dict) or not targets_raw:
|
|
132
|
+
raise ConfigError(
|
|
133
|
+
f"{path}: 'targets' must be a non-empty mapping of "
|
|
134
|
+
"<name> -> {outDir, generators?, entities?}."
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
targets: list[TargetConfig] = []
|
|
138
|
+
for name, spec in targets_raw.items():
|
|
139
|
+
ctx = f"{path}: target '{name}'"
|
|
140
|
+
if not isinstance(spec, dict):
|
|
141
|
+
raise ConfigError(f"{ctx} must be a mapping.")
|
|
142
|
+
out_dir = spec.get("outDir")
|
|
143
|
+
if not isinstance(out_dir, str) or not out_dir:
|
|
144
|
+
raise ConfigError(f"{ctx} must declare a non-empty 'outDir' string.")
|
|
145
|
+
generators = spec.get("generators")
|
|
146
|
+
if generators is not None:
|
|
147
|
+
generators = _require_str_list(generators, f"{ctx} 'generators'")
|
|
148
|
+
entities = spec.get("entities")
|
|
149
|
+
if entities is not None:
|
|
150
|
+
entities = _require_str_list(entities, f"{ctx} 'entities'")
|
|
151
|
+
targets.append(
|
|
152
|
+
TargetConfig(name=str(name), out_dir=out_dir, generators=generators, entities=entities)
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
return ProjectConfig(
|
|
156
|
+
config_dir=path.parent.resolve(),
|
|
157
|
+
metadata=metadata,
|
|
158
|
+
providers=providers,
|
|
159
|
+
targets=targets,
|
|
160
|
+
)
|
|
@@ -874,3 +874,9 @@ core_providers: list[Provider] = [
|
|
|
874
874
|
prompt_provider,
|
|
875
875
|
ui_provider,
|
|
876
876
|
]
|
|
877
|
+
|
|
878
|
+
# #265 — the ids of the LIBRARY providers above, as a frozen set. Consulted by
|
|
879
|
+
# spec_metamodel._apply_strict_attr_scoping (via TypeRegistry.attr_origin) to
|
|
880
|
+
# decide whether an attr's provenance is "library" (still prunable against the
|
|
881
|
+
# strict per-subtype allow-list) or a consumer's own provider (never pruned).
|
|
882
|
+
LIBRARY_PROVIDER_IDS: frozenset[str] = frozenset(p.id for p in core_providers)
|
|
@@ -180,6 +180,11 @@ class ErrorCode(str, Enum):
|
|
|
180
180
|
ERR_SQL_BODY_WITH_UNMANAGED = "ERR_SQL_BODY_WITH_UNMANAGED"
|
|
181
181
|
ERR_SQL_BODY_ON_WRITABLE_KIND = "ERR_SQL_BODY_ON_WRITABLE_KIND"
|
|
182
182
|
ERR_ORIGIN_UNDER_SQL_BODY = "ERR_ORIGIN_UNDER_SQL_BODY"
|
|
183
|
+
# #246 — a field.enum both extends a shared package-level abstract enum and
|
|
184
|
+
# declares its own @values. One shared enum type has one member set — the
|
|
185
|
+
# own @values would be silently dropped in codegen. Remove the own @values
|
|
186
|
+
# to inherit the shared set, or extend a concrete (non-shared) enum instead.
|
|
187
|
+
ERR_ENUM_EXTENDS_VALUES_CONFLICT = "ERR_ENUM_EXTENDS_VALUES_CONFLICT"
|
|
183
188
|
ERR_UNKNOWN = "ERR_UNKNOWN"
|
|
184
189
|
|
|
185
190
|
|