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