metaobjects 0.16.0__tar.gz → 0.17.0__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.16.0 → metaobjects-0.17.0}/PKG-INFO +1 -1
- {metaobjects-0.16.0 → metaobjects-0.17.0}/pyproject.toml +1 -1
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/generators/entity_model.py +37 -5
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/generators/filter_allowlist_generator.py +6 -1
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/generators/router_generator.py +6 -1
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/core_types.py +72 -7
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/errors.py +21 -0
- metaobjects-0.17.0/src/metaobjects/loader/validate_source_escapes.py +205 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/loader/validation_passes.py +536 -9
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/attr/attr_constants.py +5 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/attr/meta_attr.py +12 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/field/meta_field.py +15 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/object/meta_object.py +22 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/object/object_constants.py +6 -0
- metaobjects-0.17.0/src/metaobjects/meta/persistence/origin/origin_constants.py +49 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/persistence/source/meta_source.py +20 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/persistence/source/source_constants.py +10 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/runtime/object_manager.py +176 -11
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/spec_metamodel/attr.json +6 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/spec_metamodel/db.json +2 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/spec_metamodel/object.json +4 -1
- metaobjects-0.17.0/src/metaobjects/spec_metamodel/origin.json +67 -0
- metaobjects-0.17.0/tests/codegen/test_write_through.py +112 -0
- metaobjects-0.17.0/tests/integration/api_contract_jsonb_server.py +317 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/generated_jsonb_app.py +22 -6
- metaobjects-0.17.0/tests/unit/test_object_manager_autoset_stamping.py +239 -0
- metaobjects-0.17.0/tests/unit/test_object_manager_write_through.py +167 -0
- metaobjects-0.17.0/tests/unit/test_source_escapes.py +336 -0
- metaobjects-0.17.0/tests/unit/test_validation_origin_195.py +312 -0
- metaobjects-0.16.0/src/metaobjects/meta/persistence/origin/origin_constants.py +0 -28
- metaobjects-0.16.0/src/metaobjects/spec_metamodel/origin.json +0 -43
- metaobjects-0.16.0/tests/integration/api_contract_jsonb_server.py +0 -160
- {metaobjects-0.16.0 → metaobjects-0.17.0}/.gitignore +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/LICENSE +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/README.md +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/hatch_build.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/agent_context/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/agent_context/scaffold.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/apidocs/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/apidocs/api_model.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/apidocs/builder.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/apidocs/naming.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/apidocs/paths.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/apidocs/renderer.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/attr_class_map.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/cli.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/KNOWN_GAPS.md +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/config.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/constants.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/extract_delegate_emitter.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/extract_schema_emitter.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/format.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/fr010_field_mapping.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/generator.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/generator_registry.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/generators/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/generators/extractor_generator.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/generators/fr019_shared_enum.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/generators/m2m_codegen.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/generators/output_parser_generator.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/generators/output_prompt_generator.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/generators/payload_vo_generator.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/generators/render_helper_generator.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/generators/template_generator.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/generators/tph_plan.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/generators/trace_helper_generator.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/instance_artifacts.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/output_format_spec_emitter.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/overwrite_policy.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/runner.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/runtime/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/runtime/filter_parser.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/template_codegen/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/template_codegen/output_pattern.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/template_codegen/template_data.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/template_codegen/template_spec.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/type_map.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/datatype.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/documentation/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/documentation/doc_constants.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/documentation/doc_provider.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/documentation/doc_schema.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/loader/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/loader/merge.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/loader/meta_data_loader.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/loader/registered_validation.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/loader/sources/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/loader/sources/directory_source.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/loader/sources/file_source.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/loader/sources/meta_data_source.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/loader/sources/uri_source.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/loader/validate_discriminator.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/loader/validate_field_readonly.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/loader/validate_source_parameter_ref.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/loader/validate_source_physical_names.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/attr/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/field/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/field/field_constants.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/identity/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/identity/identity_constants.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/identity/meta_identity.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/index/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/index/index_constants.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/index/meta_index.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/object/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/object/meta_object_aware.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/object/object_class_registry.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/object/object_extract.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/object/value_object.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/relationship/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/relationship/derive_m2m_fields.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/relationship/meta_relationship.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/relationship/relationship_constants.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/validator/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/core/validator/validator_constants.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/meta_data.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/meta_root.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/persistence/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/persistence/db/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/persistence/db/db_constants.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/persistence/db/db_provider.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/persistence/origin/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/persistence/origin/meta_origin.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/persistence/source/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/presentation/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/presentation/layout/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/presentation/layout/layout_constants.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/presentation/layout/meta_layout.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/presentation/ui/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/presentation/ui/ui_provider.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/presentation/view/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/presentation/view/meta_view.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/presentation/view/view_constants.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/provider_extends.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/template/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/template/meta_template.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/template/prompt_provider.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/meta/template/template_constants.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/naming_refs.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/parser.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/parser_yaml.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/provider.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/py.typed +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/registry.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/registry_manifest.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/email_document.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/escapers.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/extract/KNOWN_GAPS.md +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/extract/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/extract/coerce.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/extract/extract.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/extract/extract_map.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/extract/json_forgiving_reader.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/extract/locate.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/extract/normalize.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/extract/strip.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/extract/types.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/extract/xml_forgiving_reader.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/filesystem_provider.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/prompt/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/prompt/output_format_renderer.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/prompt/output_format_spec.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/prompt/prompt_field.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/prompt/prompt_overrides.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/prompt/prompt_style.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/renderer.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/render/verify.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/runtime/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/runtime/llm_recorder.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/runtime/n2m_resolver.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/runtime/tph.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/serializer_json.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/shared/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/shared/base_types.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/shared/separators.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/shared/structural.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/source/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/source/error_source.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/source/json_path.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/source/semantic_diff.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/source/yaml_positions.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/spec_metamodel/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/spec_metamodel/documentation.json +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/spec_metamodel/field.json +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/spec_metamodel/identity.json +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/spec_metamodel/index.json +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/spec_metamodel/layout.json +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/spec_metamodel/prompt.json +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/spec_metamodel/relationship.json +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/spec_metamodel/source.json +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/spec_metamodel/template.json +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/spec_metamodel/ui.json +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/spec_metamodel/validator.json +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/spec_metamodel/view.json +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/super_resolve.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/validation_types.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/yaml_desugar.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/golden/extends/expected/BaseEntity.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/golden/extends/expected/Program.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/golden/extends/meta.json +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/golden/nested-array/expected/AuthorBrief.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/golden/nested-array/expected/PostBrief.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/golden/nested-array/meta.json +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/golden/scalars/expected/Metric.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/golden/scalars/expected/Report.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/golden/scalars/meta.json +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/golden/vanilla/expected/Subscriber.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/golden/vanilla/meta.json +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_abstract_conformance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_api_docs_builder.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_api_docs_paths.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_cli.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_cli_providers.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_cli_registry.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_cli_staleness_nudge.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_cli_verify_strict.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_cli_verify_subverbs.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_constants_config.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_entity_model.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_enum_conformance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_extends_abstract_field_inheritance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_extractor_generator.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_filter_allowlist_generator.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_format.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_fr010_nested_object_prompt.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_fr010_output_codegen.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_fr019_shared_provided_conformance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_generator.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_generator_extension_seams.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_golden.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_inherit_without_restate_gate.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_inheritance_conformance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_instance_artifacts.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_m2m_codegen.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_output_parser_generator.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_overwrite_policy.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_payload_vo_generator.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_projection_compile.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_render_helper_conformance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_render_helper_generator.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_reverse_finders.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_router_generator.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_runner.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_template_data.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_template_generator.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_template_output_pattern.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_template_scope_helpers.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_template_scope_walk.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_template_spec.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_tph_codegen.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_trace_helper_generator.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_type_map.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/codegen/test_validation_conformance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/capabilities.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/conformance-expected-failures.json +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/conformance_adapter.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/corpus.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/expected_failures.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/fixture_discovery.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/navigator.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/test_api_docs_cross_port_conformance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/test_conformance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/test_extract_conformance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/test_extract_object_verdict.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/test_fr010_loader_attrs.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/test_fr011_attrs.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/test_generator_registry_conformance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/test_object_model_conformance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/test_provider_composition_conformance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/test_registry_conformance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/test_runner_hardfail.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/test_spec_metamodel_embed.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/test_strict_attr_load.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/test_template_codegen_conformance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/test_template_generator_conformance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/test_yaml_conformance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/conformance/yaml-conformance-expected-failures.json +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/api_contract_assertions.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/api_contract_m2m_server.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/api_contract_server.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/generated_m2m_app.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/generated_router_app.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/generated_tph_app.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/meta_ai_trace.yaml +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/normalization.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/postgres_container.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/query_runner.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/scenarios.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/test_api_contract.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/test_api_contract_generated.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/test_api_contract_jsonb.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/test_api_contract_m2m.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/test_api_contract_m2m_generated.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/test_api_contract_tph_generated.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/test_generated_router_uuid_pk.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/test_llm_call_trace.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/test_normalization.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/test_query_scenarios.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/integration/test_runtime_return_types.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/open_closed_proof_test.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/extract/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/extract/test_coerce.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/extract/test_extract.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/extract/test_extract_map.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/extract/test_json_forgiving_reader.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/extract/test_locate.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/extract/test_model.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/extract/test_normalize.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/extract/test_strip.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/extract/test_xml_forgiving_reader.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/prompt/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/prompt/test_output_format_renderer.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/test_email_document.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/test_filesystem_provider.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/test_output_format_renderer_nested.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/test_output_prompt_conformance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/test_render_conformance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/test_render_max_chars.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/test_verify.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/render/test_verify_conformance.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/source/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/source/test_fr5c_merge_attribution.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/source/test_fr5d_reference_resolution.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/source/test_fr5e_database_source_shape.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/source/test_json_path.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/source/test_semantic_diff.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/source/test_source_on_node.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/source/test_yaml_positions.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/test_api_docs_accuracy.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/__init__.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_agent_context_staleness.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_capabilities.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_common_attrs.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_core_types.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_effective_package.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_errors.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_field_enum.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_field_map_validation.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_field_uuid_dbcolumntype.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_fr016_source_name_and_kind_aliases.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_index_lookup.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_llm_recorder.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_loader.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_loader_bom.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_loader_class.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_merge.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_meta_attr.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_meta_data.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_meta_source.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_module_shortcuts.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_n2m_resolver.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_n2m_resolver_inherited.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_object_manager_uuid_coercion.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_one_primary_source.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_parser.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_parser_yaml.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_provider.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_provider_extension.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_registry.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_registry_completeness.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_registry_extend.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_registry_sealed.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_relationship_referential_actions.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_resolution_key.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_runtime_resolution_key_binding.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_serializer.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_shared_constants.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_smoke.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_sources.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_strict_child_placement.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_super_resolve.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_template_toolcall.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_template_wrong_subtype_attrs.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_validation_attr_schema.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_validation_filter_values.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_validation_origin_paths.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_validation_sort_field.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_validation_warnings.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_write_coercion_arrays.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/tests/unit/test_yaml_desugar.py +0 -0
- {metaobjects-0.16.0 → metaobjects-0.17.0}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: metaobjects
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.17.0
|
|
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.17.0"
|
|
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.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/generators/entity_model.py
RENAMED
|
@@ -14,7 +14,14 @@ from metaobjects.meta.core.identity.identity_constants import (
|
|
|
14
14
|
IDENTITY_ATTR_GENERATION,
|
|
15
15
|
)
|
|
16
16
|
from metaobjects.meta.core.validator import validator_constants as vc
|
|
17
|
-
from metaobjects.
|
|
17
|
+
from metaobjects.meta.persistence.origin.origin_constants import (
|
|
18
|
+
AGG_ALL,
|
|
19
|
+
AGG_ANY,
|
|
20
|
+
AGG_COLLECT,
|
|
21
|
+
ORIGIN_ATTR_AGG,
|
|
22
|
+
ORIGIN_SUBTYPE_AGGREGATE,
|
|
23
|
+
)
|
|
24
|
+
from metaobjects.shared.base_types import TYPE_ORIGIN, TYPE_VALIDATOR
|
|
18
25
|
from metaobjects.shared.separators import PACKAGE_SEP
|
|
19
26
|
from metaobjects.codegen.config import GenConfig
|
|
20
27
|
from metaobjects.codegen.constants import generated_header
|
|
@@ -221,6 +228,22 @@ def _type_expr_for_field(
|
|
|
221
228
|
return type_expr, enum_type_name
|
|
222
229
|
|
|
223
230
|
|
|
231
|
+
def origin_guaranteed_non_null(field: MetaField) -> bool:
|
|
232
|
+
"""#195 — a field derived by an origin.aggregate ``@agg:any|all|collect`` is
|
|
233
|
+
COALESCE-guaranteed non-null in the synthesized view (any→false, all→true,
|
|
234
|
+
collect→[]), so its read type is non-null even when the field is not ``@required``.
|
|
235
|
+
origin.first is deliberately NOT here — an empty related set selects no row (→ null);
|
|
236
|
+
origin.computed nullability is expression-dependent, so it stays the conservative
|
|
237
|
+
nullable default. Mirrors the TS originGuaranteedNonNull."""
|
|
238
|
+
# ADR-0039 sanctioned own — origin.* never inherits (ADR-0029), so own is correct.
|
|
239
|
+
for child in field.own_children():
|
|
240
|
+
if child.type == TYPE_ORIGIN and child.sub_type == ORIGIN_SUBTYPE_AGGREGATE:
|
|
241
|
+
agg = child.attr(ORIGIN_ATTR_AGG) # ADR-0039 own — origin attr
|
|
242
|
+
if agg in (AGG_ANY, AGG_ALL, AGG_COLLECT):
|
|
243
|
+
return True
|
|
244
|
+
return False
|
|
245
|
+
|
|
246
|
+
|
|
224
247
|
def _field_line(field: MetaField, imports: set[str], config: GenConfig) -> tuple[str, bool]:
|
|
225
248
|
"""Return (source line, uses_field). Collects required imports into *imports*."""
|
|
226
249
|
type_expr, enum_type_name = _type_expr_for_field(field, imports, config)
|
|
@@ -243,15 +266,20 @@ def _field_line(field: MetaField, imports: set[str], config: GenConfig) -> tuple
|
|
|
243
266
|
else:
|
|
244
267
|
default_expr = None
|
|
245
268
|
|
|
246
|
-
#
|
|
247
|
-
|
|
269
|
+
# #195 — a field derived by an origin.aggregate any|all|collect always COALESCEs
|
|
270
|
+
# to a value (any→false, all→true, collect→[]), so its read type is mandatory
|
|
271
|
+
# non-null exactly like a @required field (no `| None`, no default). origin.first /
|
|
272
|
+
# origin.computed stay the conservative nullable default.
|
|
273
|
+
mandatory = required or origin_guaranteed_non_null(field)
|
|
274
|
+
# A field is Optional only when it is neither mandatory nor carries a @default.
|
|
275
|
+
annotation = type_expr if (mandatory or has_default) else f"{type_expr} | None"
|
|
248
276
|
if has_default and uses_field:
|
|
249
277
|
assignment = f" = Field(default={default_expr}, {', '.join(parts)})"
|
|
250
278
|
elif has_default:
|
|
251
279
|
assignment = f" = {default_expr}"
|
|
252
|
-
elif
|
|
280
|
+
elif mandatory and uses_field:
|
|
253
281
|
assignment = f" = Field({', '.join(parts)})"
|
|
254
|
-
elif
|
|
282
|
+
elif mandatory:
|
|
255
283
|
assignment = ""
|
|
256
284
|
elif uses_field:
|
|
257
285
|
assignment = f" = Field(default=None, {', '.join(parts)})"
|
|
@@ -468,6 +496,8 @@ class EntityModelGenerator:
|
|
|
468
496
|
continue # FR-036 #2 — a server-generated PK is never in the create body
|
|
469
497
|
if f.attrs().get(fc.FIELD_ATTR_READ_ONLY) is True:
|
|
470
498
|
continue # FR-013 — a read-only column is DB/owner-written, not create input
|
|
499
|
+
if f.is_derived():
|
|
500
|
+
continue # FR-024 §7 (#214) — a derived (origin.*) field is view-computed, not create input
|
|
471
501
|
line, used = _create_field_line(f, imports, cfg)
|
|
472
502
|
uses_field = uses_field or used
|
|
473
503
|
lines.append(line)
|
|
@@ -501,6 +531,8 @@ class EntityModelGenerator:
|
|
|
501
531
|
for f in entity.fields():
|
|
502
532
|
if f.name in pk_fields:
|
|
503
533
|
continue # FR-036 #4 — the PK is route-authoritative, never patched
|
|
534
|
+
if f.is_derived():
|
|
535
|
+
continue # FR-024 §7 (#214) — a derived (origin.*) field is view-computed, never patched
|
|
504
536
|
line, used = _patch_field_line(f, imports, cfg)
|
|
505
537
|
uses_field = uses_field or used
|
|
506
538
|
lines.append(line)
|
|
@@ -250,7 +250,12 @@ class FilterAllowlistGenerator:
|
|
|
250
250
|
src = _primary_source_rdb(entity)
|
|
251
251
|
if src is None:
|
|
252
252
|
return None
|
|
253
|
-
|
|
253
|
+
# FR-024 §7 (#214): a write-through entity read-view is writable and its generated
|
|
254
|
+
# router imports this allowlist — so it MUST be emitted for write-through regardless of
|
|
255
|
+
# source declaration order (matching the router gate; else a view-source-first
|
|
256
|
+
# write-through router imports a never-generated module and FastAPI startup crashes). A
|
|
257
|
+
# projection (read-only source only) is not write-through, so it still skips.
|
|
258
|
+
if not entity.is_write_through() and src.effective_kind() != SOURCE_KIND_TABLE:
|
|
254
259
|
return None
|
|
255
260
|
|
|
256
261
|
short_name = entity.name
|
{metaobjects-0.16.0 → metaobjects-0.17.0}/src/metaobjects/codegen/generators/router_generator.py
RENAMED
|
@@ -645,7 +645,12 @@ class RouterGenerator:
|
|
|
645
645
|
src = _primary_source_rdb(entity)
|
|
646
646
|
if src is None:
|
|
647
647
|
return None
|
|
648
|
-
|
|
648
|
+
# FR-024 §7 (#214): a write-through entity read-view is writable (owns a table
|
|
649
|
+
# source) and MUST emit its CRUD router regardless of source declaration order —
|
|
650
|
+
# the first-source gate below would wrongly skip a view-source-first write-through
|
|
651
|
+
# entity. Reads route to the replica view in the ObjectManager (not here). A
|
|
652
|
+
# projection (read-only source only) is not write-through, so it still skips.
|
|
653
|
+
if not entity.is_write_through() and src.effective_kind() != SOURCE_KIND_TABLE:
|
|
649
654
|
return None
|
|
650
655
|
|
|
651
656
|
# FR-017 TPH: a discriminator base emits a polymorphic collection at the base
|
|
@@ -6,6 +6,7 @@ from .attr_class_map import attr_class_for
|
|
|
6
6
|
from .meta.core.attr import meta_attr as _attr # noqa: F401
|
|
7
7
|
from .meta.core.attr.attr_constants import (
|
|
8
8
|
ATTR_SUBTYPE_BOOLEAN,
|
|
9
|
+
ATTR_SUBTYPE_EXPRESSION,
|
|
9
10
|
ATTR_SUBTYPE_FILTER,
|
|
10
11
|
ATTR_SUBTYPE_INT,
|
|
11
12
|
ATTR_SUBTYPE_STRING,
|
|
@@ -55,6 +56,7 @@ from .meta.core.object.meta_object import MetaObject
|
|
|
55
56
|
from .meta.core.object.object_constants import (
|
|
56
57
|
OBJECT_ATTR_DISCRIMINATOR,
|
|
57
58
|
OBJECT_ATTR_DISCRIMINATOR_VALUE,
|
|
59
|
+
OBJECT_PROJECTION_ATTR_FILTER,
|
|
58
60
|
OBJECT_SUBTYPE_ENTITY,
|
|
59
61
|
OBJECT_SUBTYPE_PROJECTION,
|
|
60
62
|
OBJECT_SUBTYPES,
|
|
@@ -77,12 +79,17 @@ from .meta.persistence.origin.meta_origin import MetaOrigin
|
|
|
77
79
|
from .meta.persistence.origin.origin_constants import (
|
|
78
80
|
ORIGIN_ATTR_AGG,
|
|
79
81
|
ORIGIN_ATTR_CONVERT,
|
|
82
|
+
ORIGIN_ATTR_DISTINCT,
|
|
83
|
+
ORIGIN_ATTR_EXPR,
|
|
80
84
|
ORIGIN_ATTR_FILTER,
|
|
81
85
|
ORIGIN_ATTR_FROM,
|
|
82
86
|
ORIGIN_ATTR_OF,
|
|
87
|
+
ORIGIN_ATTR_ORDER_BY,
|
|
83
88
|
ORIGIN_ATTR_VIA,
|
|
84
89
|
ORIGIN_SUBTYPE_AGGREGATE,
|
|
85
90
|
ORIGIN_SUBTYPE_COLLECTION,
|
|
91
|
+
ORIGIN_SUBTYPE_COMPUTED,
|
|
92
|
+
ORIGIN_SUBTYPE_FIRST,
|
|
86
93
|
ORIGIN_SUBTYPE_PASSTHROUGH,
|
|
87
94
|
)
|
|
88
95
|
from .meta.template.meta_template import MetaTemplate
|
|
@@ -96,7 +103,9 @@ from .meta.persistence.source.source_constants import (
|
|
|
96
103
|
SOURCE_ATTR_PROC,
|
|
97
104
|
SOURCE_ATTR_ROLE,
|
|
98
105
|
SOURCE_ATTR_SCHEMA,
|
|
106
|
+
SOURCE_ATTR_SQL,
|
|
99
107
|
SOURCE_ATTR_TABLE,
|
|
108
|
+
SOURCE_ATTR_UNMANAGED,
|
|
100
109
|
SOURCE_ATTR_VIEW,
|
|
101
110
|
SOURCE_RDB_KINDS,
|
|
102
111
|
SOURCE_ROLES,
|
|
@@ -253,6 +262,26 @@ for _obj_sub in OBJECT_SUBTYPES:
|
|
|
253
262
|
)
|
|
254
263
|
)
|
|
255
264
|
|
|
265
|
+
# #207 — object.projection carries an optional row-scope @filter (a portable
|
|
266
|
+
# attr.filter object — the SAME attr subtype as origin.aggregate's @filter) that
|
|
267
|
+
# lowers to a view-level SQL WHERE. The object loop above registered every subtype
|
|
268
|
+
# with the shared discriminator attrs; append @filter to the projection def
|
|
269
|
+
# (mirrors the field.currency enrichment below, and the TS object provider, where
|
|
270
|
+
# object.json's projection block declares the filter attr child). The strict
|
|
271
|
+
# per-subtype attr scoping (apply_spec_descriptions) then keeps @filter on
|
|
272
|
+
# projection and prunes the shared discriminator attrs — object.json's projection
|
|
273
|
+
# block declares ONLY @filter.
|
|
274
|
+
for _def in core_provider._defs: # noqa: SLF001 (provider build-time enrichment)
|
|
275
|
+
if _def.type == TYPE_OBJECT and _def.sub_type == OBJECT_SUBTYPE_PROJECTION:
|
|
276
|
+
_def.attrs.append(
|
|
277
|
+
AttrSchema(
|
|
278
|
+
name=OBJECT_PROJECTION_ATTR_FILTER,
|
|
279
|
+
value_type=ATTR_SUBTYPE_FILTER,
|
|
280
|
+
required=False,
|
|
281
|
+
)
|
|
282
|
+
)
|
|
283
|
+
break
|
|
284
|
+
|
|
256
285
|
# field.* (one factory, data_type by subtype)
|
|
257
286
|
# Note: FIELD_SUBTYPE_ENUM is excluded from FIELD_SUBTYPES; it is registered
|
|
258
287
|
# separately below with its required @values AttrSchema (sharing these child rules).
|
|
@@ -591,6 +620,9 @@ core_provider.add(
|
|
|
591
620
|
allowed_values=SOURCE_ROLES,
|
|
592
621
|
),
|
|
593
622
|
AttrSchema(name=SOURCE_ATTR_SCHEMA, value_type=ATTR_SUBTYPE_STRING, required=False),
|
|
623
|
+
# FR-024/#208 escape valves — registration only, no validation/lowering here.
|
|
624
|
+
AttrSchema(name=SOURCE_ATTR_SQL, value_type=ATTR_SUBTYPE_STRING, required=False),
|
|
625
|
+
AttrSchema(name=SOURCE_ATTR_UNMANAGED, value_type=ATTR_SUBTYPE_BOOLEAN, required=False),
|
|
594
626
|
# FR-015 — @parameterRef: input-shape object.value for proc/table-function sources.
|
|
595
627
|
AttrSchema(
|
|
596
628
|
name=SOURCE_ATTR_PARAMETER_REF,
|
|
@@ -628,13 +660,13 @@ core_provider.add(
|
|
|
628
660
|
)
|
|
629
661
|
)
|
|
630
662
|
|
|
631
|
-
# origin.aggregate — @agg
|
|
632
|
-
# FR-024 (ADR-0029): @via
|
|
633
|
-
#
|
|
634
|
-
#
|
|
635
|
-
#
|
|
636
|
-
#
|
|
637
|
-
_AGG_ALLOWED = ("count", "sum", "avg", "min", "max")
|
|
663
|
+
# origin.aggregate — @agg required; @of/@via/@distinct/@orderBy optional.
|
|
664
|
+
# FR-024 (ADR-0029): @via is inferable when exactly one single-hop relationship
|
|
665
|
+
# reaches the @of entity. #195: @of relaxed to optional (any/all forbid it, the
|
|
666
|
+
# rest require it) — presence is enforced per-@agg in the origin validation pass;
|
|
667
|
+
# @agg vocabulary extended with any/all (predicate quantifiers) + collect (array
|
|
668
|
+
# rollup); @distinct (collect set-semantics) + @orderBy (element/row ordering) added.
|
|
669
|
+
_AGG_ALLOWED = ("count", "sum", "avg", "min", "max", "any", "all", "collect")
|
|
638
670
|
core_provider.add(
|
|
639
671
|
TypeDefinition(
|
|
640
672
|
type=TYPE_ORIGIN,
|
|
@@ -647,8 +679,41 @@ core_provider.add(
|
|
|
647
679
|
required=True,
|
|
648
680
|
allowed_values=_AGG_ALLOWED,
|
|
649
681
|
),
|
|
682
|
+
AttrSchema(name=ORIGIN_ATTR_OF, value_type=ATTR_SUBTYPE_STRING, required=False),
|
|
683
|
+
AttrSchema(name=ORIGIN_ATTR_VIA, value_type=ATTR_SUBTYPE_STRING, required=False),
|
|
684
|
+
AttrSchema(name=ORIGIN_ATTR_FILTER, value_type=ATTR_SUBTYPE_FILTER, required=False),
|
|
685
|
+
AttrSchema(name=ORIGIN_ATTR_DISTINCT, value_type=ATTR_SUBTYPE_BOOLEAN, required=False),
|
|
686
|
+
AttrSchema(name=ORIGIN_ATTR_ORDER_BY, value_type=ATTR_SUBTYPE_STRING, required=False, is_array=True),
|
|
687
|
+
],
|
|
688
|
+
child_rules=[ChildRule(TYPE_ATTR, "*")],
|
|
689
|
+
)
|
|
690
|
+
)
|
|
691
|
+
|
|
692
|
+
# origin.computed (#195) — a row-level value from the base entity's own fields
|
|
693
|
+
# via a structured @expr tree (attr.expression). No related rows / @via.
|
|
694
|
+
core_provider.add(
|
|
695
|
+
TypeDefinition(
|
|
696
|
+
type=TYPE_ORIGIN,
|
|
697
|
+
sub_type=ORIGIN_SUBTYPE_COMPUTED,
|
|
698
|
+
factory=MetaOrigin,
|
|
699
|
+
attrs=[
|
|
700
|
+
AttrSchema(name=ORIGIN_ATTR_EXPR, value_type=ATTR_SUBTYPE_EXPRESSION, required=True),
|
|
701
|
+
],
|
|
702
|
+
child_rules=[ChildRule(TYPE_ATTR, "*")],
|
|
703
|
+
)
|
|
704
|
+
)
|
|
705
|
+
|
|
706
|
+
# origin.first (#195) — the single related row selected by @orderBy along @via,
|
|
707
|
+
# projecting @of. @of + @orderBy required; @via + @filter optional.
|
|
708
|
+
core_provider.add(
|
|
709
|
+
TypeDefinition(
|
|
710
|
+
type=TYPE_ORIGIN,
|
|
711
|
+
sub_type=ORIGIN_SUBTYPE_FIRST,
|
|
712
|
+
factory=MetaOrigin,
|
|
713
|
+
attrs=[
|
|
650
714
|
AttrSchema(name=ORIGIN_ATTR_OF, value_type=ATTR_SUBTYPE_STRING, required=True),
|
|
651
715
|
AttrSchema(name=ORIGIN_ATTR_VIA, value_type=ATTR_SUBTYPE_STRING, required=False),
|
|
716
|
+
AttrSchema(name=ORIGIN_ATTR_ORDER_BY, value_type=ATTR_SUBTYPE_STRING, required=True, is_array=True),
|
|
652
717
|
AttrSchema(name=ORIGIN_ATTR_FILTER, value_type=ATTR_SUBTYPE_FILTER, required=False),
|
|
653
718
|
],
|
|
654
719
|
child_rules=[ChildRule(TYPE_ATTR, "*")],
|
|
@@ -60,6 +60,13 @@ class ErrorCode(str, Enum):
|
|
|
60
60
|
# is to-one at every hop (you meant passthrough).
|
|
61
61
|
ERR_AMBIGUOUS_PATH = "ERR_AMBIGUOUS_PATH"
|
|
62
62
|
ERR_ORIGIN_CARDINALITY = "ERR_ORIGIN_CARDINALITY"
|
|
63
|
+
# #195 — origin.computed @expr validation. ERR_UNKNOWN_EXPR_NODE: the expression
|
|
64
|
+
# tree contains a node whose kind/op/fn is not in the closed grammar (fail-closed
|
|
65
|
+
# per ADR-0023). ERR_COMPUTED_TYPE_MISMATCH: the @expr tree's inferred root type
|
|
66
|
+
# does not equal the carrying field's declared field.<subType> (a computed column's
|
|
67
|
+
# type is DERIVED from its expression, never asserted — no @convert escape).
|
|
68
|
+
ERR_UNKNOWN_EXPR_NODE = "ERR_UNKNOWN_EXPR_NODE"
|
|
69
|
+
ERR_COMPUTED_TYPE_MISMATCH = "ERR_COMPUTED_TYPE_MISMATCH"
|
|
63
70
|
# FR-024 B6 — extends/origin agreement + derived-field providability. Vocabulary-
|
|
64
71
|
# only here until FR-024 Phase E (the Python loader does not run these checks yet):
|
|
65
72
|
# ERR_EXTENDS_ORIGIN_MISMATCH — a field's entity-nested extends (shape lineage)
|
|
@@ -156,6 +163,20 @@ class ErrorCode(str, Enum):
|
|
|
156
163
|
# the validate()-time structural enforcement is the next sub-step).
|
|
157
164
|
ERR_CHILD_NOT_ALLOWED = "ERR_CHILD_NOT_ALLOWED"
|
|
158
165
|
ERR_INVALID_METAMODEL_CONSTRAINT = "ERR_INVALID_METAMODEL_CONSTRAINT"
|
|
166
|
+
# #208 — DDL-ownership escape valves (source.rdb @sql / @unmanaged).
|
|
167
|
+
# ERR_SQL_BODY_WITH_UNMANAGED: @sql AND @unmanaged declared on the SAME
|
|
168
|
+
# source — the two mutually exclusive non-default DDL-ownership states.
|
|
169
|
+
# ERR_SQL_BODY_ON_WRITABLE_KIND: @sql set on a writable @kind ("table", the
|
|
170
|
+
# default) — @sql is legal only on a read-only kind; a writable table is
|
|
171
|
+
# either fully modeled or @unmanaged, never opaque-bodied.
|
|
172
|
+
# ERR_ORIGIN_UNDER_SQL_BODY: an origin.*-bearing (derived) own field, or an
|
|
173
|
+
# object.projection @filter (#207), under an @sql host — two sources of
|
|
174
|
+
# truth for the same body. (R6's WARN_ORIGIN_UNDER_UNMANAGED sibling — an
|
|
175
|
+
# origin.*-bearing field under an @unmanaged host — is a warning, not an
|
|
176
|
+
# error code; it lives in the envelope-warnings channel.)
|
|
177
|
+
ERR_SQL_BODY_WITH_UNMANAGED = "ERR_SQL_BODY_WITH_UNMANAGED"
|
|
178
|
+
ERR_SQL_BODY_ON_WRITABLE_KIND = "ERR_SQL_BODY_ON_WRITABLE_KIND"
|
|
179
|
+
ERR_ORIGIN_UNDER_SQL_BODY = "ERR_ORIGIN_UNDER_SQL_BODY"
|
|
159
180
|
ERR_UNKNOWN = "ERR_UNKNOWN"
|
|
160
181
|
|
|
161
182
|
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"""#208 — DDL-ownership escape valves loader validation (source.rdb @sql / @unmanaged).
|
|
2
|
+
|
|
3
|
+
Sibling of validate_source_parameter_ref.py / validate_source_physical_names.py.
|
|
4
|
+
|
|
5
|
+
#208 gives source.rdb two mutually exclusive, non-default DDL-ownership
|
|
6
|
+
markers: ``@sql`` (a hand-written body the tool registers/fingerprints/drift-
|
|
7
|
+
checks but never authors) and ``@unmanaged`` (this object's DDL is owned
|
|
8
|
+
elsewhere — the tool never touches it). This pass enforces the six
|
|
9
|
+
fail-closed rules from the design doc (§5):
|
|
10
|
+
|
|
11
|
+
R1 @sql AND @unmanaged on the SAME source -> ERR_SQL_BODY_WITH_UNMANAGED
|
|
12
|
+
R2 @sql on a writable @kind ("table", the default) -> ERR_SQL_BODY_ON_WRITABLE_KIND
|
|
13
|
+
R3 @sql present but empty / whitespace-only -> ERR_BAD_ATTR_VALUE
|
|
14
|
+
R4 origin.*-bearing field under an @sql host -> ERR_ORIGIN_UNDER_SQL_BODY
|
|
15
|
+
R5 object.projection @filter (#207) + @sql host -> ERR_ORIGIN_UNDER_SQL_BODY
|
|
16
|
+
R6 origin.*-bearing field under an @unmanaged host -> WARN_ORIGIN_UNDER_UNMANAGED
|
|
17
|
+
|
|
18
|
+
R1-R3 are per-source (declaration-layer). R4-R6 are per-host-object: a host
|
|
19
|
+
with ANY own source.rdb carrying @sql/@unmanaged is judged against its own
|
|
20
|
+
fields (and, for R5, its own @filter). The asymmetry between R4 (hard error)
|
|
21
|
+
and R6 (warn) is deliberate (design doc §5.6): @sql is a second body (two
|
|
22
|
+
sources of truth for the SAME data); @unmanaged acts on nothing, so a
|
|
23
|
+
documented-but-unacted-on lineage is benign.
|
|
24
|
+
|
|
25
|
+
Mirrors the TS reference
|
|
26
|
+
``packages/typescript/packages/metadata/src/persistence/source/validate-source-escapes.ts``.
|
|
27
|
+
"""
|
|
28
|
+
from __future__ import annotations
|
|
29
|
+
|
|
30
|
+
from ..errors import ErrorCode, MetaError
|
|
31
|
+
from ..meta.core.field.meta_field import MetaField
|
|
32
|
+
from ..meta.core.object.object_constants import (
|
|
33
|
+
OBJECT_PROJECTION_ATTR_FILTER,
|
|
34
|
+
OBJECT_SUBTYPE_PROJECTION,
|
|
35
|
+
)
|
|
36
|
+
from ..meta.meta_data import MetaData
|
|
37
|
+
from ..meta.persistence.source.meta_source import MetaSource
|
|
38
|
+
from ..meta.persistence.source.source_constants import (
|
|
39
|
+
SOURCE_ATTR_SQL,
|
|
40
|
+
SOURCE_SUBTYPE_RDB,
|
|
41
|
+
)
|
|
42
|
+
from ..shared.base_types import TYPE_FIELD, TYPE_OBJECT, TYPE_SOURCE
|
|
43
|
+
from ..source.error_source import LoaderWarning
|
|
44
|
+
|
|
45
|
+
WARN_ORIGIN_UNDER_UNMANAGED = "WARN_ORIGIN_UNDER_UNMANAGED"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def validate_source_escapes(
|
|
49
|
+
root: MetaData,
|
|
50
|
+
errors: list[MetaError],
|
|
51
|
+
envelope_warnings: list[LoaderWarning] | None = None,
|
|
52
|
+
legacy_warnings: list[str] | None = None,
|
|
53
|
+
) -> None:
|
|
54
|
+
"""Run the #208 R1-R6 @sql / @unmanaged DDL-ownership validation.
|
|
55
|
+
|
|
56
|
+
``envelope_warnings`` collects the FR5c-style envelope warning
|
|
57
|
+
(``WARN_ORIGIN_UNDER_UNMANAGED``, R6). ``legacy_warnings`` mirrors the
|
|
58
|
+
cross-port string warnings channel — populated with the same code string
|
|
59
|
+
so the legacy ``warnings: list[str]`` consumers see something too.
|
|
60
|
+
"""
|
|
61
|
+
# ADR-0039 sanctioned own: root has no super (children()==own_children()),
|
|
62
|
+
# and every object is declared at the root level (mirrors the TS
|
|
63
|
+
# reference's root.children() walk).
|
|
64
|
+
for obj in root.own_children():
|
|
65
|
+
if obj.type != TYPE_OBJECT:
|
|
66
|
+
continue
|
|
67
|
+
|
|
68
|
+
# ADR-0039 sanctioned own: declaration-layer source iteration (mirrors
|
|
69
|
+
# validate_source_parameter_ref / _validate_one_primary_source):
|
|
70
|
+
# R1-R3 judge markers DECLARED on this object's own sources.
|
|
71
|
+
sources = [
|
|
72
|
+
c
|
|
73
|
+
for c in obj.own_children()
|
|
74
|
+
if c.type == TYPE_SOURCE
|
|
75
|
+
and c.sub_type == SOURCE_SUBTYPE_RDB
|
|
76
|
+
and isinstance(c, MetaSource)
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
has_sql_host = False
|
|
80
|
+
has_unmanaged_host = False
|
|
81
|
+
|
|
82
|
+
for source in sources:
|
|
83
|
+
# ADR-0039: resolving — @sql/@unmanaged are inheritable (follow
|
|
84
|
+
# the @role/effective_kind precedent — sources are inheritable,
|
|
85
|
+
# NOT the @dbColumnType own-only exception).
|
|
86
|
+
sql_set = source.sql_body() is not None
|
|
87
|
+
unmanaged_set = source.is_unmanaged()
|
|
88
|
+
|
|
89
|
+
# R1 — contradictory DDL owners on the same source.
|
|
90
|
+
if sql_set and unmanaged_set:
|
|
91
|
+
errors.append(
|
|
92
|
+
MetaError(
|
|
93
|
+
f'source.rdb on object "{obj.name}" declares both @sql and '
|
|
94
|
+
"@unmanaged — these are the mutually exclusive non-default "
|
|
95
|
+
"states of one DDL-ownership axis (an author-supplied body "
|
|
96
|
+
'contradicts "someone else owns this DDL")',
|
|
97
|
+
ErrorCode.ERR_SQL_BODY_WITH_UNMANAGED,
|
|
98
|
+
envelope=source.source,
|
|
99
|
+
)
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# R2 — @sql on a writable kind would bypass the column-diff
|
|
103
|
+
# machinery; tables are fully modeled or @unmanaged, never
|
|
104
|
+
# opaque-bodied.
|
|
105
|
+
if sql_set and source.is_writable():
|
|
106
|
+
errors.append(
|
|
107
|
+
MetaError(
|
|
108
|
+
f'source.rdb on object "{obj.name}" declares @sql with a '
|
|
109
|
+
f'writable @kind ("{source.effective_kind()}") — @sql is '
|
|
110
|
+
"legal only on a read-only kind (view/materializedView/"
|
|
111
|
+
"storedProc/tableFunction); a writable table is either "
|
|
112
|
+
"fully modeled or marked @unmanaged, never opaque-bodied",
|
|
113
|
+
ErrorCode.ERR_SQL_BODY_ON_WRITABLE_KIND,
|
|
114
|
+
envelope=source.source,
|
|
115
|
+
)
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
# R3 — @sql present but empty/whitespace. MUST read the raw attr,
|
|
119
|
+
# not the sql_body() accessor: sql_body() already narrows an
|
|
120
|
+
# empty string to None, which would make a present-but-empty
|
|
121
|
+
# @sql indistinguishable from an absent one.
|
|
122
|
+
raw_sql = source.get_meta_attr(SOURCE_ATTR_SQL)
|
|
123
|
+
if raw_sql is not None and (
|
|
124
|
+
not isinstance(raw_sql, str) or raw_sql.strip() == ""
|
|
125
|
+
):
|
|
126
|
+
errors.append(
|
|
127
|
+
MetaError(
|
|
128
|
+
f'source.rdb on object "{obj.name}" sets @sql to an '
|
|
129
|
+
"empty/whitespace-only value; @sql requires a non-empty "
|
|
130
|
+
"SQL body",
|
|
131
|
+
ErrorCode.ERR_BAD_ATTR_VALUE,
|
|
132
|
+
envelope=source.source,
|
|
133
|
+
)
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
if sql_set:
|
|
137
|
+
has_sql_host = True
|
|
138
|
+
if unmanaged_set:
|
|
139
|
+
has_unmanaged_host = True
|
|
140
|
+
|
|
141
|
+
if not has_sql_host and not has_unmanaged_host:
|
|
142
|
+
continue
|
|
143
|
+
|
|
144
|
+
# R4 / R6 — origin.*-bearing (derived) own fields under an @sql /
|
|
145
|
+
# @unmanaged host. ADR-0039: own — origin.* never inherits
|
|
146
|
+
# (ADR-0029), so is_derived() is own-only by policy (mirrors
|
|
147
|
+
# _validate_derived_field_providability). @sql (hard error) takes
|
|
148
|
+
# priority over @unmanaged (warn) when a host happens to declare
|
|
149
|
+
# both markers across different sources.
|
|
150
|
+
for child in obj.own_children():
|
|
151
|
+
if child.type != TYPE_FIELD or not isinstance(child, MetaField):
|
|
152
|
+
continue
|
|
153
|
+
if not child.is_derived():
|
|
154
|
+
continue
|
|
155
|
+
if has_sql_host:
|
|
156
|
+
errors.append(
|
|
157
|
+
MetaError(
|
|
158
|
+
f'field "{obj.name}.{child.name}" carries an origin.* '
|
|
159
|
+
f'(derived) child, but "{obj.name}" has a read source '
|
|
160
|
+
"carrying @sql — the synthesized derivation and the "
|
|
161
|
+
"author's verbatim SQL are two sources of truth for the "
|
|
162
|
+
"same body",
|
|
163
|
+
ErrorCode.ERR_ORIGIN_UNDER_SQL_BODY,
|
|
164
|
+
envelope=child.source,
|
|
165
|
+
)
|
|
166
|
+
)
|
|
167
|
+
else:
|
|
168
|
+
msg = (
|
|
169
|
+
f'field "{obj.name}.{child.name}" carries an origin.* '
|
|
170
|
+
f'(derived) child, but "{obj.name}" has a source marked '
|
|
171
|
+
"@unmanaged — the tool never touches this object's DDL, so "
|
|
172
|
+
"the derivation is documented lineage only (not acted on); "
|
|
173
|
+
"this is informational, not an error"
|
|
174
|
+
)
|
|
175
|
+
if envelope_warnings is not None:
|
|
176
|
+
envelope_warnings.append(
|
|
177
|
+
LoaderWarning(
|
|
178
|
+
code=WARN_ORIGIN_UNDER_UNMANAGED,
|
|
179
|
+
message=msg,
|
|
180
|
+
source=child.source,
|
|
181
|
+
)
|
|
182
|
+
)
|
|
183
|
+
if legacy_warnings is not None:
|
|
184
|
+
legacy_warnings.append(WARN_ORIGIN_UNDER_UNMANAGED)
|
|
185
|
+
|
|
186
|
+
# R5 — a projection's row-scope @filter (#207) lowers to the outer
|
|
187
|
+
# WHERE of a TOOL-SYNTHESIZED body; with @sql the author owns the
|
|
188
|
+
# body (and its WHERE), so wrapping it is deferred cleverness
|
|
189
|
+
# (design doc D5) — reject.
|
|
190
|
+
if has_sql_host and obj.sub_type == OBJECT_SUBTYPE_PROJECTION:
|
|
191
|
+
# ADR-0039: own — the @filter is declared locally on this
|
|
192
|
+
# projection (mirrors _validate_projection_filter).
|
|
193
|
+
filter_value = obj.attr(OBJECT_PROJECTION_ATTR_FILTER)
|
|
194
|
+
if filter_value is not None:
|
|
195
|
+
errors.append(
|
|
196
|
+
MetaError(
|
|
197
|
+
f'projection "{obj.name}" declares both @filter and an '
|
|
198
|
+
"@sql read source — a view-level @filter lowers to the "
|
|
199
|
+
"outer WHERE of a synthesized body; with @sql the author "
|
|
200
|
+
"owns the body (and its WHERE), so the two cannot be "
|
|
201
|
+
"combined",
|
|
202
|
+
ErrorCode.ERR_ORIGIN_UNDER_SQL_BODY,
|
|
203
|
+
envelope=obj.source,
|
|
204
|
+
)
|
|
205
|
+
)
|