metaobjects 0.18.0__tar.gz → 0.19.1__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.18.0 → metaobjects-0.19.1}/PKG-INFO +1 -1
- {metaobjects-0.18.0 → metaobjects-0.19.1}/pyproject.toml +1 -1
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generators/entity_model.py +78 -30
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/spec_metamodel/__init__.py +1 -0
- metaobjects-0.19.1/src/metaobjects/spec_metamodel/ui-web.json +21 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/spec_metamodel/view.json +2 -1
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/golden/extends/expected/Program.py +1 -1
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/golden/nested-array/expected/AuthorBrief.py +9 -2
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/golden/nested-array/expected/PostBrief.py +6 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/golden/scalars/expected/Metric.py +6 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/golden/scalars/expected/Report.py +10 -1
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/golden/vanilla/expected/Subscriber.py +1 -1
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_entity_model.py +54 -2
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_validation_conformance.py +15 -5
- {metaobjects-0.18.0 → metaobjects-0.19.1}/uv.lock +1 -1
- {metaobjects-0.18.0 → metaobjects-0.19.1}/.gitignore +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/LICENSE +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/README.md +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/hatch_build.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/agent_context/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/agent_context/scaffold.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/apidocs/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/apidocs/api_model.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/apidocs/builder.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/apidocs/naming.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/apidocs/paths.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/apidocs/renderer.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/attr_class_map.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/cli.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/KNOWN_GAPS.md +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/config.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/constants.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/extract_delegate_emitter.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/extract_schema_emitter.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/format.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/fr010_field_mapping.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generator_registry.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generators/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generators/extractor_generator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generators/filter_allowlist_generator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generators/fr019_shared_enum.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generators/m2m_codegen.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generators/output_parser_generator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generators/output_prompt_generator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generators/payload_vo_generator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generators/render_helper_generator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generators/router_generator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generators/template_generator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generators/tph_plan.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generators/trace_helper_generator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/instance_artifacts.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/output_format_spec_emitter.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/overwrite_policy.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/runner.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/runtime/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/runtime/filter_parser.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/template_codegen/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/template_codegen/output_pattern.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/template_codegen/template_data.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/template_codegen/template_spec.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/type_map.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/core_types.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/datatype.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/documentation/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/documentation/doc_constants.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/documentation/doc_provider.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/documentation/doc_schema.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/errors.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/loader/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/loader/merge.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/loader/meta_data_loader.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/loader/registered_validation.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/loader/sources/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/loader/sources/directory_source.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/loader/sources/file_source.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/loader/sources/meta_data_source.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/loader/sources/uri_source.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/loader/validate_discriminator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/loader/validate_field_readonly.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/loader/validate_source_escapes.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/loader/validate_source_parameter_ref.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/loader/validate_source_physical_names.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/loader/validation_passes.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/attr/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/attr/attr_constants.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/attr/meta_attr.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/field/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/field/field_constants.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/field/meta_field.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/identity/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/identity/identity_constants.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/identity/meta_identity.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/index/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/index/index_constants.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/index/meta_index.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/object/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/object/meta_object.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/object/meta_object_aware.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/object/object_class_registry.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/object/object_constants.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/object/object_extract.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/object/value_object.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/relationship/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/relationship/derive_m2m_fields.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/relationship/meta_relationship.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/relationship/relationship_constants.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/validator/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/core/validator/validator_constants.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/meta_data.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/meta_root.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/persistence/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/persistence/db/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/persistence/db/db_constants.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/persistence/db/db_provider.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/persistence/origin/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/persistence/origin/meta_origin.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/persistence/origin/origin_constants.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/persistence/source/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/persistence/source/meta_source.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/persistence/source/source_constants.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/presentation/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/presentation/layout/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/presentation/layout/layout_constants.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/presentation/layout/meta_layout.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/presentation/ui/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/presentation/ui/ui_provider.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/presentation/view/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/presentation/view/meta_view.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/presentation/view/view_constants.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/provider_extends.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/template/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/template/meta_template.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/template/prompt_provider.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/meta/template/template_constants.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/naming_refs.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/parser.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/parser_yaml.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/provider.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/py.typed +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/registry.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/registry_manifest.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/email_document.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/escapers.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/extract/KNOWN_GAPS.md +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/extract/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/extract/coerce.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/extract/extract.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/extract/extract_map.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/extract/json_forgiving_reader.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/extract/locate.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/extract/normalize.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/extract/strip.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/extract/types.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/extract/xml_forgiving_reader.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/filesystem_provider.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/prompt/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/prompt/output_format_renderer.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/prompt/output_format_spec.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/prompt/prompt_field.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/prompt/prompt_overrides.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/prompt/prompt_style.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/renderer.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/render/verify.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/runtime/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/runtime/llm_recorder.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/runtime/n2m_resolver.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/runtime/object_manager.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/runtime/tph.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/serializer_json.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/shared/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/shared/base_types.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/shared/separators.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/shared/structural.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/source/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/source/error_source.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/source/json_path.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/source/semantic_diff.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/source/yaml_positions.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/spec_metamodel/attr.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/spec_metamodel/db.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/spec_metamodel/documentation.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/spec_metamodel/field.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/spec_metamodel/identity.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/spec_metamodel/index.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/spec_metamodel/layout.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/spec_metamodel/object.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/spec_metamodel/origin.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/spec_metamodel/prompt.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/spec_metamodel/relationship.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/spec_metamodel/source.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/spec_metamodel/template.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/spec_metamodel/ui.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/spec_metamodel/validator.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/super_resolve.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/validation_types.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/yaml_desugar.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/golden/extends/expected/BaseEntity.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/golden/extends/meta.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/golden/nested-array/meta.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/golden/scalars/meta.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/golden/vanilla/meta.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_abstract_conformance.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_api_docs_builder.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_api_docs_paths.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_cli.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_cli_providers.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_cli_registry.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_cli_staleness_nudge.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_cli_verify_strict.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_cli_verify_subverbs.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_constants_config.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_enum_conformance.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_extends_abstract_field_inheritance.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_extractor_generator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_filter_allowlist_generator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_format.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_fr010_nested_object_prompt.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_fr010_output_codegen.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_fr019_shared_provided_conformance.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_generator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_generator_extension_seams.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_golden.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_inherit_without_restate_gate.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_inheritance_conformance.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_instance_artifacts.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_m2m_codegen.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_origin_nullability.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_output_parser_generator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_overwrite_policy.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_payload_vo_generator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_projection_compile.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_render_helper_conformance.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_render_helper_generator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_reverse_finders.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_router_generator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_runner.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_template_data.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_template_generator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_template_output_pattern.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_template_scope_helpers.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_template_scope_walk.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_template_spec.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_tph_codegen.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_trace_helper_generator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_type_map.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/codegen/test_write_through.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/capabilities.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/conformance-expected-failures.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/conformance_adapter.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/corpus.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/expected_failures.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/fixture_discovery.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/navigator.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/test_api_docs_cross_port_conformance.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/test_conformance.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/test_extract_conformance.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/test_extract_object_verdict.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/test_fr010_loader_attrs.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/test_fr011_attrs.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/test_generator_registry_conformance.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/test_object_model_conformance.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/test_provider_composition_conformance.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/test_registry_conformance.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/test_runner_hardfail.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/test_spec_metamodel_embed.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/test_strict_attr_load.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/test_template_codegen_conformance.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/test_template_generator_conformance.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/test_yaml_conformance.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/conformance/yaml-conformance-expected-failures.json +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/api_contract_assertions.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/api_contract_jsonb_server.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/api_contract_m2m_server.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/api_contract_server.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/generated_jsonb_app.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/generated_m2m_app.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/generated_router_app.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/generated_tph_app.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/meta_ai_trace.yaml +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/normalization.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/postgres_container.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/query_runner.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/scenarios.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/test_api_contract.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/test_api_contract_generated.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/test_api_contract_jsonb.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/test_api_contract_m2m.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/test_api_contract_m2m_generated.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/test_api_contract_tph_generated.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/test_generated_router_uuid_pk.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/test_llm_call_trace.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/test_normalization.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/test_query_scenarios.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/integration/test_runtime_return_types.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/open_closed_proof_test.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/extract/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/extract/test_coerce.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/extract/test_extract.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/extract/test_extract_map.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/extract/test_json_forgiving_reader.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/extract/test_locate.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/extract/test_model.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/extract/test_normalize.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/extract/test_strip.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/extract/test_xml_forgiving_reader.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/prompt/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/prompt/test_output_format_renderer.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/test_email_document.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/test_filesystem_provider.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/test_output_format_renderer_nested.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/test_output_prompt_conformance.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/test_render_conformance.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/test_render_max_chars.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/test_verify.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/render/test_verify_conformance.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/source/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/source/test_fr5c_merge_attribution.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/source/test_fr5d_reference_resolution.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/source/test_fr5e_database_source_shape.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/source/test_json_path.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/source/test_semantic_diff.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/source/test_source_on_node.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/source/test_yaml_positions.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/test_api_docs_accuracy.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/__init__.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_agent_context_staleness.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_capabilities.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_common_attrs.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_core_types.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_effective_package.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_errors.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_field_enum.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_field_map_validation.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_field_uuid_dbcolumntype.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_fr016_source_name_and_kind_aliases.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_index_lookup.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_llm_recorder.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_loader.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_loader_bom.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_loader_class.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_merge.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_meta_attr.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_meta_data.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_meta_source.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_module_shortcuts.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_n2m_resolver.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_n2m_resolver_inherited.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_object_manager_autoset_stamping.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_object_manager_uuid_coercion.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_object_manager_write_through.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_one_primary_source.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_parser.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_parser_yaml.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_provider.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_provider_extension.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_registry.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_registry_completeness.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_registry_extend.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_registry_sealed.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_relationship_referential_actions.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_resolution_key.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_runtime_resolution_key_binding.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_serializer.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_shared_constants.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_smoke.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_source_escapes.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_sources.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_strict_child_placement.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_super_resolve.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_template_toolcall.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_template_wrong_subtype_attrs.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_validation_attr_schema.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_validation_filter_values.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_validation_origin_195.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_validation_origin_paths.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_validation_sort_field.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_validation_warnings.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/tests/unit/test_write_coercion_arrays.py +0 -0
- {metaobjects-0.18.0 → metaobjects-0.19.1}/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.19.1
|
|
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.19.1"
|
|
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.18.0 → metaobjects-0.19.1}/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 = False) -> 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,15 @@ 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 the default ``False``; callers building a wire
|
|
118
|
+
model (``_create_field_line``/``_patch_field_line``) pass ``True``.
|
|
107
119
|
"""
|
|
108
120
|
kwargs: dict[str, object] = {}
|
|
109
121
|
|
|
@@ -158,11 +170,13 @@ def _validator_constraints(field: MetaField) -> dict[str, object]:
|
|
|
158
170
|
if field.attrs().get(fc.FIELD_ATTR_STRING_FORMAT) == fc.STRING_FORMAT_HOSTNAME:
|
|
159
171
|
kwargs["pattern"] = _HOSTNAME_REGEX
|
|
160
172
|
|
|
161
|
-
# FR-036 Pin 1 — a @required non-array string is
|
|
162
|
-
# ACCEPT whitespace-only. Emit an implicit
|
|
163
|
-
# floor if a validator.length @min
|
|
173
|
+
# FR-036 Pin 1 (#224 — WIRE TIER ONLY) — a @required non-array string is
|
|
174
|
+
# non-empty: reject null / "" but ACCEPT whitespace-only. Emit an implicit
|
|
175
|
+
# min_length of 1, keeping the stricter floor if a validator.length @min
|
|
176
|
+
# already set one. Never applied to the in-process read model (wire=False).
|
|
164
177
|
if (
|
|
165
|
-
|
|
178
|
+
wire
|
|
179
|
+
and field.sub_type == fc.FIELD_SUBTYPE_STRING
|
|
166
180
|
and not field_is_array(field)
|
|
167
181
|
and field.attrs().get(fc.FIELD_ATTR_REQUIRED) is True
|
|
168
182
|
):
|
|
@@ -182,7 +196,7 @@ def _constraint_parts(constraints: dict[str, object]) -> list[str]:
|
|
|
182
196
|
|
|
183
197
|
|
|
184
198
|
def _type_expr_for_field(
|
|
185
|
-
field: MetaField, imports: set[str], config: GenConfig
|
|
199
|
+
field: MetaField, imports: set[str], config: GenConfig, wire: bool = False
|
|
186
200
|
) -> tuple[str, str | None]:
|
|
187
201
|
"""The Python annotation text for *field* (arrays wrapped in ``list[...]``) plus the
|
|
188
202
|
shared-enum class name when the field resolves to one (used to render an enum
|
|
@@ -191,7 +205,13 @@ def _type_expr_for_field(
|
|
|
191
205
|
|
|
192
206
|
FR-019: a field resolving to a package-level shared enum is typed by the materialized
|
|
193
207
|
standalone class (imported from the shared ``enums`` module) or — when @provided — an
|
|
194
|
-
external module; inline enums keep their ``Literal[...]`` (py_type_for).
|
|
208
|
+
external module; inline enums keep their ``Literal[...]`` (py_type_for).
|
|
209
|
+
|
|
210
|
+
*wire* (#224): in a wire context (create/patch), a ``field.object``/``field.map``
|
|
211
|
+
``@objectRef`` annotates with the referenced VO's own WIRE model (``<Ref>Create``)
|
|
212
|
+
rather than its read model, so a required-string Pin 1 violation nested inside the
|
|
213
|
+
VO still validates on the wire (api-contract jsonb r10). A VO's own Create lines
|
|
214
|
+
are emitted through this same wire path, so nested-VO-in-VO recurses naturally."""
|
|
195
215
|
shared = (
|
|
196
216
|
fr019.shared_enum_for_field(field)
|
|
197
217
|
if field.sub_type == fc.FIELD_SUBTYPE_ENUM
|
|
@@ -220,11 +240,20 @@ def _type_expr_for_field(
|
|
|
220
240
|
# A field.object (-> VO) and a field.map with @objectRef (-> dict[str, VO]) both
|
|
221
241
|
# reference a value-object by name; import it so the emitted annotation resolves.
|
|
222
242
|
# @objectRef is FQN-expanded at load; the generated VOs live flat in one package,
|
|
223
|
-
# so import by the bare class name.
|
|
243
|
+
# so import by the bare class name. #224 — a WIRE context binds the referenced
|
|
244
|
+
# VO's <Ref>Create instead (see docstring above).
|
|
224
245
|
ref = field.attrs().get(fc.FIELD_ATTR_OBJECT_REF)
|
|
225
246
|
if ref:
|
|
226
247
|
ref_name = str(ref).split("::")[-1]
|
|
227
|
-
|
|
248
|
+
bound_name = f"{ref_name}Create" if wire else ref_name
|
|
249
|
+
imports.add(f"from .{ref_name} import {bound_name}")
|
|
250
|
+
if wire:
|
|
251
|
+
if field.sub_type == fc.FIELD_SUBTYPE_MAP:
|
|
252
|
+
type_expr = f"dict[str, {bound_name}]"
|
|
253
|
+
elif field_is_array(field):
|
|
254
|
+
type_expr = f"list[{bound_name}]"
|
|
255
|
+
else:
|
|
256
|
+
type_expr = bound_name
|
|
228
257
|
return type_expr, enum_type_name
|
|
229
258
|
|
|
230
259
|
|
|
@@ -330,14 +359,18 @@ def _create_field_line(
|
|
|
330
359
|
field: MetaField, imports: set[str], config: GenConfig
|
|
331
360
|
) -> tuple[str, bool]:
|
|
332
361
|
"""A CREATE-model field line (FR-036): keyed by the WIRE name (``field.name``) and
|
|
333
|
-
carrying the
|
|
362
|
+
carrying the WIRE-TIER per-field constraints (#224 — includes FR-036 Pin 1
|
|
363
|
+
non-empty-string; the read model does NOT carry Pin 1). A ``@required`` field
|
|
334
364
|
that is SERVER-FILLED — it has ANY ``@default`` (a literal OR a SQL expression such
|
|
335
365
|
as ``now()`` / ``gen_random_uuid()`` / ``CURRENT_TIMESTAMP``) or an ``@autoSet`` — is
|
|
336
366
|
emitted OPTIONAL, because the DB / trigger provides it and a POST that omits it must
|
|
337
367
|
not 400 (mirrors the TS InsertSchema ``fieldWillBeOptional``). A literal ``@default``
|
|
338
368
|
is preserved as the Python default; a SQL-expression default / ``@autoSet`` carries
|
|
339
|
-
no Python default (the server fills it).
|
|
340
|
-
|
|
369
|
+
no Python default (the server fills it). Also used, unchanged, to emit an
|
|
370
|
+
``object.value``'s own ``<Name>Create`` wire model (#224) — the PK/TPH/derived-field
|
|
371
|
+
guards in the caller no-op for a VO carrying none of those. Returns (source line,
|
|
372
|
+
uses_field)."""
|
|
373
|
+
type_expr, enum_type_name = _type_expr_for_field(field, imports, config, wire=True)
|
|
341
374
|
required = field.attrs().get(fc.FIELD_ATTR_REQUIRED) is True
|
|
342
375
|
default_raw = field.attrs().get(fc.FIELD_ATTR_DEFAULT)
|
|
343
376
|
literal_default = default_raw is not None and not _is_sql_expr_default(default_raw)
|
|
@@ -349,7 +382,7 @@ def _create_field_line(
|
|
|
349
382
|
server_filled = default_raw is not None or is_auto_set
|
|
350
383
|
create_required = required and not server_filled
|
|
351
384
|
|
|
352
|
-
parts = _constraint_parts(_validator_constraints(field))
|
|
385
|
+
parts = _constraint_parts(_validator_constraints(field, wire=True))
|
|
353
386
|
uses_field = bool(parts)
|
|
354
387
|
|
|
355
388
|
py_name = field.name # FR-036 #3 — validation models key by the WIRE name (field.name)
|
|
@@ -383,12 +416,12 @@ def _patch_field_line(
|
|
|
383
416
|
field: MetaField, imports: set[str], config: GenConfig
|
|
384
417
|
) -> tuple[str, bool]:
|
|
385
418
|
"""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))
|
|
419
|
+
carries the SAME wire-tier per-field constraints as the create model (#224), so a
|
|
420
|
+
present, non-null value is validated with the create rules (FR-036) while an
|
|
421
|
+
absent field is left untouched. A ``@default`` is never emitted (a patch does not
|
|
422
|
+
default a column). Returns (source line, uses_field)."""
|
|
423
|
+
type_expr, _enum = _type_expr_for_field(field, imports, config, wire=True)
|
|
424
|
+
parts = _constraint_parts(_validator_constraints(field, wire=True))
|
|
392
425
|
py_name = field.name # FR-036 #3 — validation models key by the WIRE name (field.name)
|
|
393
426
|
if parts:
|
|
394
427
|
return f" {py_name}: {type_expr} | None = Field(default=None, {', '.join(parts)})", True
|
|
@@ -478,8 +511,10 @@ class EntityModelGenerator:
|
|
|
478
511
|
``@autoSet``; FR-036 #1) is made optional. Keyed by the wire name; a TPH
|
|
479
512
|
subtype's discriminator is pinned to its ``Literal`` value (the route injects it
|
|
480
513
|
from the URL, so it stays optional with a default). M:N navigations are omitted
|
|
481
|
-
(a create body targets columns, not relations).
|
|
482
|
-
|
|
514
|
+
(a create body targets columns, not relations). Also used, unchanged, to emit an
|
|
515
|
+
``object.value``'s own wire model (#224) — a VO has no PK/TPH/derived fields, so
|
|
516
|
+
those guards simply no-op. Returns ``(lines, uses_field)``. Override to
|
|
517
|
+
add/transform create-model lines."""
|
|
483
518
|
cfg = config if config is not None else GenConfig(out_dir="")
|
|
484
519
|
auto_gen_pk = _auto_gen_pk_field_names(entity)
|
|
485
520
|
binding = tph_subtype_binding(entity)
|
|
@@ -576,27 +611,37 @@ class EntityModelGenerator:
|
|
|
576
611
|
imports.add("from typing import Literal")
|
|
577
612
|
body = lines if lines else [" pass"]
|
|
578
613
|
|
|
579
|
-
# FR-036 — an object.entity
|
|
614
|
+
# FR-036 — an object.entity emits two flat WIRE-validation models the generated
|
|
580
615
|
# router binds: a ``<Name>Create`` (POST-body shape: auto-gen PK / @readOnly
|
|
581
616
|
# omitted, @default/@autoSet optional, other @required required) and an
|
|
582
617
|
# all-optional ``<Name>Patch`` (PATCH-body shape: PK excluded). Both key by the
|
|
583
|
-
# WIRE name and carry the field constraints
|
|
584
|
-
#
|
|
585
|
-
#
|
|
586
|
-
|
|
618
|
+
# WIRE name and carry the wire-tier field constraints (#224 — includes FR-036
|
|
619
|
+
# Pin 1), so present values are validated with the create rules.
|
|
620
|
+
#
|
|
621
|
+
# #224 — an object.value is reached OVER THE WIRE too: it nests into an entity's
|
|
622
|
+
# Create/Patch body via a field.object/field.map ``@objectRef`` (see
|
|
623
|
+
# ``_type_expr_for_field``'s wire mode), so it also emits its own ``<Name>Create``
|
|
624
|
+
# wire model — Create only, since a nested VO is whole-value replace on both POST
|
|
625
|
+
# and PATCH (the same reason TS embeds one ``<Ref>InsertSchema`` in both Insert
|
|
626
|
+
# and Update schemas; no separate VO ``Patch`` shape exists). A ``<Name>Patch`` is
|
|
627
|
+
# entity-only (PK exclusion + partial-update semantics are entity-specific).
|
|
628
|
+
# object.projection is read-only and never routed — it emits neither.
|
|
629
|
+
emit_create = entity.sub_type in (OBJECT_SUBTYPE_ENTITY, OBJECT_SUBTYPE_VALUE)
|
|
630
|
+
emit_patch = entity.sub_type == OBJECT_SUBTYPE_ENTITY
|
|
587
631
|
create_lines: list[str] = []
|
|
588
632
|
create_uses_field = False
|
|
589
633
|
patch_lines: list[str] = []
|
|
590
634
|
patch_uses_field = False
|
|
591
|
-
if
|
|
635
|
+
if emit_create:
|
|
592
636
|
create_lines, create_uses_field = self._emit_create_lines(entity, imports, config)
|
|
637
|
+
if emit_patch:
|
|
593
638
|
patch_lines, patch_uses_field = self._emit_patch_lines(entity, imports, config)
|
|
594
639
|
|
|
595
640
|
# Import only the pydantic names actually referenced. The main model imports
|
|
596
641
|
# BaseModel only when it has no super, but the flat Create/Patch models always
|
|
597
642
|
# subclass BaseModel, so their presence forces the import regardless.
|
|
598
643
|
pyd_names: list[str] = []
|
|
599
|
-
if entity.super_data is None or
|
|
644
|
+
if entity.super_data is None or emit_create or emit_patch:
|
|
600
645
|
pyd_names.append("BaseModel")
|
|
601
646
|
if uses_field or create_uses_field or patch_uses_field:
|
|
602
647
|
pyd_names.append("Field")
|
|
@@ -612,7 +657,7 @@ class EntityModelGenerator:
|
|
|
612
657
|
if pyd_names:
|
|
613
658
|
parts += [f"from pydantic import {', '.join(pyd_names)}", ""]
|
|
614
659
|
parts += ["", self._emit_class_header(entity, base_class), *body]
|
|
615
|
-
if
|
|
660
|
+
if emit_create:
|
|
616
661
|
parts += [
|
|
617
662
|
"",
|
|
618
663
|
"",
|
|
@@ -620,6 +665,9 @@ class EntityModelGenerator:
|
|
|
620
665
|
' """GENERATED — CREATE input: auto-gen PK / @readOnly omitted; '
|
|
621
666
|
'@default/@autoSet optional; present values validated (FR-036)."""',
|
|
622
667
|
*create_lines,
|
|
668
|
+
]
|
|
669
|
+
if emit_patch:
|
|
670
|
+
parts += [
|
|
623
671
|
"",
|
|
624
672
|
"",
|
|
625
673
|
f"class {entity.name}Patch(BaseModel):",
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"provider": "metaobjects-ui-web",
|
|
3
|
+
"extends": [
|
|
4
|
+
{
|
|
5
|
+
"type": "view", "subType": "textarea",
|
|
6
|
+
"children": [
|
|
7
|
+
{ "type": "attr", "subType": "int", "name": "rows", "min": 0, "max": 1, "description": "Visible row count for the generated <textarea>; the form generator defaults to 4 when absent." }
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"type": "view", "subType": "image",
|
|
12
|
+
"children": [
|
|
13
|
+
{ "type": "attr", "subType": "double", "name": "aspectRatio", "min": 0, "max": 1, "description": "Crop aspect ratio (width / height). Omit for freeform." },
|
|
14
|
+
{ "type": "attr", "subType": "int", "name": "maxEdge", "min": 0, "max": 1, "description": "Longest-edge bound in px for the re-encoded output." },
|
|
15
|
+
{ "type": "attr", "subType": "string", "name": "store", "min": 0, "max": 1, "description": "Opaque storage-namespace hint passed to the upload adapter (not infrastructure)." },
|
|
16
|
+
{ "type": "attr", "subType": "string", "name": "accept", "isArray": true, "min": 0, "max": 1, "description": "Accepted MIME types (client guard; the server re-enforces)." },
|
|
17
|
+
{ "type": "attr", "subType": "int", "name": "maxBytes", "min": 0, "max": 1, "description": "Client-side size ceiling in bytes." }
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -70,6 +70,7 @@
|
|
|
70
70
|
"type": "view",
|
|
71
71
|
"subType": "currency",
|
|
72
72
|
"description": "Currency display formatting (locale-aware via @locale)."
|
|
73
|
-
}
|
|
73
|
+
},
|
|
74
|
+
{ "type": "view", "subType": "image", "description": "Image upload/display control; the field stores an opaque storage key (field.string)." }
|
|
74
75
|
]
|
|
75
76
|
}
|
{metaobjects-0.18.0 → metaobjects-0.19.1}/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.18.0 → metaobjects-0.19.1}/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
|
|
@@ -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.18.0 → metaobjects-0.19.1}/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.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generators/extractor_generator.py
RENAMED
|
File without changes
|
|
File without changes
|
{metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generators/fr019_shared_enum.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generators/payload_vo_generator.py
RENAMED
|
File without changes
|
|
File without changes
|
{metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generators/router_generator.py
RENAMED
|
File without changes
|
{metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/generators/template_generator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/output_format_spec_emitter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/template_codegen/__init__.py
RENAMED
|
File without changes
|
{metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/template_codegen/output_pattern.py
RENAMED
|
File without changes
|
{metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/template_codegen/template_data.py
RENAMED
|
File without changes
|
{metaobjects-0.18.0 → metaobjects-0.19.1}/src/metaobjects/codegen/template_codegen/template_spec.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|