metaobjects 0.23.0__tar.gz → 0.23.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {metaobjects-0.23.0 → metaobjects-0.23.2}/PKG-INFO +1 -1
- {metaobjects-0.23.0 → metaobjects-0.23.2}/pyproject.toml +1 -1
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/generators/filter_allowlist_generator.py +39 -4
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/generators/fr019_shared_enum.py +15 -6
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/core_types.py +13 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/errors.py +6 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/loader/validation_passes.py +215 -14
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/attr/attr_constants.py +8 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/attr/meta_attr.py +17 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/field/field_constants.py +7 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/requirement/meta_requirement.py +2 -1
- metaobjects-0.23.2/src/metaobjects/render/payload_accessors.py +134 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/renderer.py +5 -1
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/verify.py +11 -1
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/runtime/object_manager.py +94 -6
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/spec_metamodel/attr.json +6 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/spec_metamodel/field.json +2 -1
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/spec_metamodel/requirement.json +2 -2
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/capabilities.py +7 -3
- metaobjects-0.23.2/tests/runtime/test_object_manager_enum_intvaluemap.py +192 -0
- metaobjects-0.23.2/tests/unit/test_field_enum_intvaluemap.py +185 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/uv.lock +1 -1
- {metaobjects-0.23.0 → metaobjects-0.23.2}/.gitignore +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/LICENSE +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/README.md +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/hatch_build.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/agent_context/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/agent_context/scaffold.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/apidocs/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/apidocs/api_model.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/apidocs/builder.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/apidocs/naming.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/apidocs/paths.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/apidocs/renderer.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/attr_class_map.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/cli.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/KNOWN_GAPS.md +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/collision_names.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/config.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/constants.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/extract_delegate_emitter.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/extract_schema_emitter.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/format.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/fr010_field_mapping.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/generator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/generator_registry.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/generators/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/generators/entity_model.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/generators/extractor_generator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/generators/m2m_codegen.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/generators/output_parser_generator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/generators/output_prompt_generator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/generators/payload_vo_generator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/generators/render_helper_generator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/generators/router_generator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/generators/template_generator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/generators/tph_plan.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/generators/trace_helper_generator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/instance_artifacts.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/metaobjects-config.schema.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/output_format_spec_emitter.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/overwrite_policy.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/project_config.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/runner.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/runtime/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/runtime/filter_parser.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/template_codegen/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/template_codegen/output_pattern.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/template_codegen/template_data.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/template_codegen/template_spec.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/type_map.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/datatype.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/documentation/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/documentation/doc_constants.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/documentation/doc_provider.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/documentation/doc_schema.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/loader/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/loader/merge.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/loader/meta_data_loader.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/loader/registered_validation.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/loader/sources/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/loader/sources/directory_source.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/loader/sources/file_source.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/loader/sources/meta_data_source.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/loader/sources/uri_source.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/loader/validate_discriminator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/loader/validate_enum_normalize_ambiguity.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/loader/validate_field_readonly.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/loader/validate_source_escapes.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/loader/validate_source_parameter_ref.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/loader/validate_source_physical_names.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/attr/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/field/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/field/meta_field.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/identity/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/identity/identity_constants.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/identity/meta_identity.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/index/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/index/index_constants.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/index/meta_index.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/object/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/object/meta_object.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/object/meta_object_aware.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/object/object_class_registry.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/object/object_constants.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/object/object_extract.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/object/value_object.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/relationship/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/relationship/derive_m2m_fields.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/relationship/meta_relationship.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/relationship/relationship_constants.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/requirement/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/requirement/requirement_constants.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/validator/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/validator/validator_constants.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/meta_data.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/meta_root.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/persistence/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/persistence/db/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/persistence/db/db_constants.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/persistence/db/db_provider.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/persistence/origin/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/persistence/origin/meta_origin.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/persistence/origin/origin_constants.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/persistence/source/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/persistence/source/meta_source.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/persistence/source/source_constants.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/presentation/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/presentation/layout/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/presentation/layout/layout_constants.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/presentation/layout/meta_layout.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/presentation/ui/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/presentation/ui/ui_provider.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/presentation/view/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/presentation/view/meta_view.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/presentation/view/view_constants.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/provider_extends.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/template/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/template/meta_template.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/template/prompt_provider.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/template/template_constants.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/naming_refs.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/parser.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/parser_yaml.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/provider.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/py.typed +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/registry.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/registry_manifest.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/email_document.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/escapers.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/extract/KNOWN_GAPS.md +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/extract/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/extract/coerce.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/extract/extract.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/extract/extract_map.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/extract/json_forgiving_reader.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/extract/locate.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/extract/normalize.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/extract/strip.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/extract/types.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/extract/xml_forgiving_reader.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/filesystem_provider.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/prompt/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/prompt/output_format_renderer.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/prompt/output_format_spec.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/prompt/prompt_field.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/prompt/prompt_overrides.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/render/prompt/prompt_style.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/runtime/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/runtime/llm_recorder.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/runtime/n2m_resolver.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/runtime/tph.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/serializer_json.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/shared/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/shared/base_types.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/shared/separators.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/shared/structural.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/source/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/source/error_source.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/source/json_path.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/source/semantic_diff.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/source/yaml_positions.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/spec_metamodel/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/spec_metamodel/db.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/spec_metamodel/documentation.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/spec_metamodel/identity.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/spec_metamodel/index.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/spec_metamodel/layout.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/spec_metamodel/object.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/spec_metamodel/origin.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/spec_metamodel/prompt.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/spec_metamodel/relationship.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/spec_metamodel/source.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/spec_metamodel/template.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/spec_metamodel/ui-web.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/spec_metamodel/ui.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/spec_metamodel/validator.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/spec_metamodel/view.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/super_resolve.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/validation_types.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/yaml_desugar.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/golden/extends/expected/BaseEntity.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/golden/extends/expected/Program.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/golden/extends/meta.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/golden/nested-array/expected/AuthorBrief.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/golden/nested-array/expected/PostBrief.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/golden/nested-array/meta.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/golden/scalars/expected/Metric.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/golden/scalars/expected/Report.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/golden/scalars/meta.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/golden/vanilla/expected/Subscriber.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/golden/vanilla/meta.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_abstract_conformance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_api_docs_builder.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_api_docs_paths.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_cli.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_cli_config_gen.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_cli_config_verify.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_cli_providers.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_cli_registry.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_cli_staleness_nudge.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_cli_verify_strict.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_cli_verify_subverbs.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_constants_config.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_entity_model.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_enum_conformance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_extends_abstract_field_inheritance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_extract_tier_collision.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_extractor_generator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_filter_allowlist_generator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_format.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_fr010_nested_object_prompt.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_fr010_output_codegen.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_fr019_shared_provided_conformance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_generator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_generator_extension_seams.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_golden.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_inherit_without_restate_gate.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_inheritance_conformance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_instance_artifacts.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_m2m_codegen.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_origin_nullability.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_output_parser_generator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_overwrite_policy.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_payload_vo_generator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_project_config.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_projection_compile.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_render_helper_conformance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_render_helper_generator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_reverse_finders.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_router_autoset.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_router_generator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_runner.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_sourceless_projection.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_template_data.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_template_generator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_template_output_pattern.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_template_scope_helpers.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_template_scope_walk.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_template_spec.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_tph_codegen.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_trace_helper_generator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_type_map.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_validation_conformance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/codegen/test_write_through.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/conformance-expected-failures.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/conformance_adapter.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/corpus.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/expected_failures.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/fixture_discovery.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/navigator.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/test_api_docs_cross_port_conformance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/test_conformance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/test_extract_conformance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/test_extract_object_verdict.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/test_fr010_loader_attrs.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/test_fr011_attrs.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/test_generator_registry_conformance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/test_object_model_conformance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/test_provider_composition_conformance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/test_registry_conformance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/test_runner_hardfail.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/test_spec_metamodel_embed.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/test_strict_attr_load.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/test_template_codegen_conformance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/test_template_generator_conformance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/test_yaml_conformance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/conformance/yaml-conformance-expected-failures.json +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/api_contract_assertions.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/api_contract_jsonb_server.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/api_contract_m2m_server.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/api_contract_server.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/generated_jsonb_app.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/generated_m2m_app.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/generated_router_app.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/generated_tph_app.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/meta_ai_trace.yaml +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/normalization.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/postgres_container.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/query_runner.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/scenarios.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/test_api_contract.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/test_api_contract_generated.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/test_api_contract_jsonb.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/test_api_contract_m2m.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/test_api_contract_m2m_generated.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/test_api_contract_tph_generated.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/test_generated_router_uuid_pk.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/test_llm_call_trace.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/test_normalization.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/test_query_scenarios.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/integration/test_runtime_return_types.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/loader/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/loader/test_enum_extends_values_conflict.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/loader/test_template_payload_target_210.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/open_closed_proof_test.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/extract/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/extract/test_coerce.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/extract/test_extract.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/extract/test_extract_map.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/extract/test_json_forgiving_reader.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/extract/test_locate.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/extract/test_model.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/extract/test_normalize.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/extract/test_strip.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/extract/test_xml_forgiving_reader.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/prompt/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/prompt/test_output_format_renderer.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/test_email_document.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/test_filesystem_provider.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/test_output_format_renderer_nested.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/test_output_prompt_conformance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/test_render_conformance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/test_render_max_chars.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/test_verify.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/render/test_verify_conformance.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/source/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/source/test_fr5c_merge_attribution.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/source/test_fr5d_reference_resolution.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/source/test_fr5e_database_source_shape.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/source/test_json_path.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/source/test_semantic_diff.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/source/test_source_on_node.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/source/test_yaml_positions.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/test_api_docs_accuracy.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/__init__.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_agent_context_staleness.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_capabilities.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_common_attrs.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_core_types.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_effective_package.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_errors.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_field_enum.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_field_map_validation.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_field_uuid_dbcolumntype.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_fr016_source_name_and_kind_aliases.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_index_lookup.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_llm_recorder.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_loader.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_loader_bom.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_loader_class.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_merge.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_meta_attr.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_meta_data.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_meta_source.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_module_shortcuts.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_n2m_resolver.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_n2m_resolver_inherited.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_object_manager_autoset_stamping.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_object_manager_uuid_coercion.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_object_manager_write_through.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_one_primary_source.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_parser.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_parser_yaml.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_provider.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_provider_extension.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_registry.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_registry_completeness.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_registry_extend.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_registry_sealed.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_relationship_referential_actions.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_resolution_key.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_runtime_resolution_key_binding.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_serializer.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_shared_constants.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_smoke.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_source_escapes.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_sources.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_strict_child_placement.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_super_resolve.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_template_toolcall.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_template_wrong_subtype_attrs.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_validation_attr_schema.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_validation_filter_values.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_validation_origin_195.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_validation_origin_paths.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_validation_sort_field.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_validation_warnings.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_write_coercion_arrays.py +0 -0
- {metaobjects-0.23.0 → metaobjects-0.23.2}/tests/unit/test_yaml_desugar.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: metaobjects
|
|
3
|
-
Version: 0.23.
|
|
3
|
+
Version: 0.23.2
|
|
4
4
|
Summary: Cross-language metadata standard: declare typed entities once, generate idiomatic drift-checked code across languages — Python port.
|
|
5
5
|
Project-URL: Homepage, https://metaobjects.dev
|
|
6
6
|
Project-URL: Repository, https://github.com/metaobjectsdev/metaobjects
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "metaobjects"
|
|
3
|
-
version = "0.23.
|
|
3
|
+
version = "0.23.2"
|
|
4
4
|
description = "Cross-language metadata standard: declare typed entities once, generate idiomatic drift-checked code across languages — Python port."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -53,6 +53,11 @@ _OPS_STRING: tuple[str, ...] = ("eq", "ne", "in", "like", "isNull")
|
|
|
53
53
|
# uuid: identity-comparison only — no `like` (not a substring type), no ordering.
|
|
54
54
|
_OPS_UUID: tuple[str, ...] = ("eq", "ne", "in", "isNull")
|
|
55
55
|
_OPS_NUMERIC: tuple[str, ...] = ("eq", "ne", "gt", "gte", "lt", "lte", "in", "isNull")
|
|
56
|
+
# int-backed enum (@intValueMap, design D5): the enum band minus `like` — the column
|
|
57
|
+
# is an integer, and a substring match against an integer is meaningless. Distinct
|
|
58
|
+
# constant from _OPS_UUID despite the identical members: they narrow for different
|
|
59
|
+
# reasons and would diverge independently.
|
|
60
|
+
_OPS_ENUM_INT_BACKED: tuple[str, ...] = ("eq", "ne", "in", "isNull")
|
|
56
61
|
_OPS_BOOLEAN: tuple[str, ...] = ("eq", "isNull")
|
|
57
62
|
|
|
58
63
|
|
|
@@ -118,6 +123,36 @@ def ops_for_subtype_ordered(sub_type: str | None) -> tuple[str, ...]:
|
|
|
118
123
|
return ()
|
|
119
124
|
|
|
120
125
|
|
|
126
|
+
def ops_for_field_ordered(field: MetaField) -> tuple[str, ...]:
|
|
127
|
+
"""The operator tuple for a FIELD, in canonical operator order.
|
|
128
|
+
|
|
129
|
+
The ordered counterpart of ``validation_passes.ops_for_field``, and the entry
|
|
130
|
+
point for every consumer that has a field in hand: the codegen allowlist emit
|
|
131
|
+
and the cross-port ``field.filter-ops`` conformance capability.
|
|
132
|
+
|
|
133
|
+
Identical to :func:`ops_for_subtype_ordered` except for ONE case: an int-backed
|
|
134
|
+
``field.enum`` (one declaring ``@intValueMap``, design D5) persists as an INTEGER
|
|
135
|
+
column, so ``like`` -- a substring match -- is dropped. ``eq``/``ne``/``in``
|
|
136
|
+
survive because the member symbol encodes to its integer before it reaches SQL;
|
|
137
|
+
``like`` has no such encoding, and an unencoded ``LIKE 'DRAFT'`` against an integer
|
|
138
|
+
column is a request-time type error.
|
|
139
|
+
|
|
140
|
+
ADR-0039: the ``@intValueMap`` read is RESOLVING (``attrs()``, NOT ``attr()`` --
|
|
141
|
+
Python inverts the TS naming, ``attr()`` here is own-only). Post-#246 the map lives
|
|
142
|
+
on a shared root-level abstract declaration and consuming fields INHERIT it, so an
|
|
143
|
+
own-only read would see it absent on exactly the shape adopters are steered toward
|
|
144
|
+
and wrongly keep ``like``.
|
|
145
|
+
|
|
146
|
+
Cross-port: ``fixtures/conformance/filter-ops-matrix`` pins ``fEnum`` vs
|
|
147
|
+
``fEnumInt`` in all five ports.
|
|
148
|
+
"""
|
|
149
|
+
if field.sub_type == fc.FIELD_SUBTYPE_ENUM and isinstance(
|
|
150
|
+
field.attrs().get(fc.FIELD_ATTR_INT_VALUE_MAP), dict
|
|
151
|
+
):
|
|
152
|
+
return _OPS_ENUM_INT_BACKED
|
|
153
|
+
return ops_for_subtype_ordered(field.sub_type)
|
|
154
|
+
|
|
155
|
+
|
|
121
156
|
def _is_filterable(field: MetaField) -> bool:
|
|
122
157
|
"""True iff ``field`` carries ``@filterable: true`` as a metadata attribute.
|
|
123
158
|
|
|
@@ -166,10 +201,10 @@ class FilterAllowlistGenerator:
|
|
|
166
201
|
name = "filter-allowlist-generator"
|
|
167
202
|
|
|
168
203
|
def _ops_for_field(self, field: MetaField) -> tuple[str, ...]:
|
|
169
|
-
"""The operator tuple allowed for ``field`` (FR-009 §5
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
return
|
|
204
|
+
"""The operator tuple allowed for ``field`` (FR-009 §5 matrix by default).
|
|
205
|
+
Override to customize the per-field operator vocabulary; returning an empty
|
|
206
|
+
tuple excludes the field from the allowlist."""
|
|
207
|
+
return ops_for_field_ordered(field)
|
|
173
208
|
|
|
174
209
|
def _compute_filterable_ops(
|
|
175
210
|
self, entity: MetaObject, object_index: dict[str, MetaObject] | None = None
|
{metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/codegen/generators/fr019_shared_enum.py
RENAMED
|
@@ -66,12 +66,21 @@ def resolve_shared_enum_decl(field: MetaField) -> MetaData | None:
|
|
|
66
66
|
|
|
67
67
|
|
|
68
68
|
def is_provided(decl: MetaData) -> bool:
|
|
69
|
-
"""
|
|
70
|
-
|
|
71
|
-
ADR-0039
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
"""``@provided`` truth of an enum DECLARATION.
|
|
70
|
+
|
|
71
|
+
ADR-0039 sanctioned own (Python naming inversion: ``attr()`` is the OWN read,
|
|
72
|
+
``get_meta_attr()`` resolves). ``@provided`` is a declaration-layer provenance
|
|
73
|
+
marker — "THIS type is supplied by hand-written/third-party code", like
|
|
74
|
+
``is_abstract`` — and does not flow down an ``extends`` chain.
|
|
75
|
+
|
|
76
|
+
This is only ever called on the resolved declaration (see
|
|
77
|
+
``shared_enum_for_field``), never on the consuming field, so own and resolving
|
|
78
|
+
agree for a plain ``field extends @provided decl``. They diverge on a CHAINED
|
|
79
|
+
declaration (root abstract ``B extends`` root abstract ``@provided A``): a
|
|
80
|
+
resolving read reports B provided and emits a reference to a hand-written ``B``
|
|
81
|
+
the adopter never declared, instead of materializing B. Matches the JVM ports.
|
|
82
|
+
"""
|
|
83
|
+
return decl.attr(fc.FIELD_ATTR_PROVIDED) is True
|
|
75
84
|
|
|
76
85
|
|
|
77
86
|
def _meta_package_of(decl: MetaData) -> str:
|
|
@@ -9,6 +9,7 @@ from .meta.core.attr.attr_constants import (
|
|
|
9
9
|
ATTR_SUBTYPE_EXPRESSION,
|
|
10
10
|
ATTR_SUBTYPE_FILTER,
|
|
11
11
|
ATTR_SUBTYPE_INT,
|
|
12
|
+
ATTR_SUBTYPE_INT_MAP,
|
|
12
13
|
ATTR_SUBTYPE_STRING,
|
|
13
14
|
ATTR_SUBTYPES,
|
|
14
15
|
)
|
|
@@ -19,6 +20,7 @@ from .meta.core.field.field_constants import (
|
|
|
19
20
|
FIELD_ATTR_AUTO_SET,
|
|
20
21
|
FIELD_ATTR_CURRENCY,
|
|
21
22
|
FIELD_ATTR_DEFAULT,
|
|
23
|
+
FIELD_ATTR_INT_VALUE_MAP,
|
|
22
24
|
FIELD_ATTR_PROVIDED,
|
|
23
25
|
FIELD_ATTR_MAX_LENGTH,
|
|
24
26
|
FIELD_ATTR_OBJECT_REF,
|
|
@@ -472,6 +474,17 @@ core_provider.add(
|
|
|
472
474
|
value_type=ATTR_SUBTYPE_BOOLEAN,
|
|
473
475
|
required=False,
|
|
474
476
|
),
|
|
477
|
+
# int-backed-enum-values plan — @intValueMap: optional per-member int
|
|
478
|
+
# values ({member: int}) switching this enum field's DB persistence
|
|
479
|
+
# from string+CHECK to integer+CHECK. Keys must exactly match @values;
|
|
480
|
+
# values must be unique integers (enforced in _validate_enum_values,
|
|
481
|
+
# Rule 4). Structural (core), like @values / @provided — not a
|
|
482
|
+
# TS-web-only / prompt-domain overlay.
|
|
483
|
+
AttrSchema(
|
|
484
|
+
name=FIELD_ATTR_INT_VALUE_MAP,
|
|
485
|
+
value_type=ATTR_SUBTYPE_INT_MAP,
|
|
486
|
+
required=False,
|
|
487
|
+
),
|
|
475
488
|
# FR-033 — the field.enum tolerant-extract overlays (@enumAlias / @enumDoc /
|
|
476
489
|
# @coerceDefault / @normalize) are NO LONGER declared here; they are re-homed
|
|
477
490
|
# to the prompt domain provider (`prompt_provider`, metaobjects-prompt) via
|
|
@@ -194,6 +194,12 @@ class ErrorCode(str, Enum):
|
|
|
194
194
|
# own @values would be silently dropped in codegen. Remove the own @values
|
|
195
195
|
# to inherit the shared set, or extend a concrete (non-shared) enum instead.
|
|
196
196
|
ERR_ENUM_EXTENDS_VALUES_CONFLICT = "ERR_ENUM_EXTENDS_VALUES_CONFLICT"
|
|
197
|
+
# A field.enum carries @intValueMap together with isArray=true. Int-backing is
|
|
198
|
+
# a persistence-layer codec and no port implements it element-wise over an
|
|
199
|
+
# array column, so the combination would silently persist member SYMBOLS into
|
|
200
|
+
# an integer array. An array-of-enum stays string-backed: drop @intValueMap,
|
|
201
|
+
# or make the field scalar.
|
|
202
|
+
ERR_ENUM_INT_VALUE_MAP_ARRAY = "ERR_ENUM_INT_VALUE_MAP_ARRAY"
|
|
197
203
|
ERR_UNKNOWN = "ERR_UNKNOWN"
|
|
198
204
|
|
|
199
205
|
|
|
@@ -23,6 +23,7 @@ from ..meta.core.field.field_constants import (
|
|
|
23
23
|
ENUM_MEMBER_PATTERN,
|
|
24
24
|
FIELD_ATTR_COERCE_DEFAULT,
|
|
25
25
|
FIELD_ATTR_DEFAULT,
|
|
26
|
+
FIELD_ATTR_INT_VALUE_MAP,
|
|
26
27
|
FIELD_ATTR_OBJECT_REF,
|
|
27
28
|
FIELD_ATTR_REQUIRED,
|
|
28
29
|
FIELD_ATTR_STORAGE,
|
|
@@ -60,6 +61,7 @@ from ..meta.persistence.source.source_constants import (
|
|
|
60
61
|
SOURCE_ROLE_PRIMARY,
|
|
61
62
|
)
|
|
62
63
|
from ..meta.core.attr.attr_constants import (
|
|
64
|
+
ATTR_SUBTYPE_INT_MAP,
|
|
63
65
|
ATTR_SUBTYPE_PROPERTIES,
|
|
64
66
|
ATTR_SUBTYPE_STRINGARRAY,
|
|
65
67
|
)
|
|
@@ -281,6 +283,26 @@ def _type_ok(value: object, value_type: str) -> bool:
|
|
|
281
283
|
# fails here → ERR_BAD_ATTR_VALUE, matching TS + Java (fail-closed); an object
|
|
282
284
|
# @expr then flows to the closed-grammar check in the origin pass.
|
|
283
285
|
return isinstance(value, dict)
|
|
286
|
+
if value_type == ATTR_SUBTYPE_INT_MAP:
|
|
287
|
+
# attr.intMap (int-backed-enum-values plan): an object whose every member
|
|
288
|
+
# value is an integer (e.g. field.enum's @intValueMap). This port has no
|
|
289
|
+
# per-attr-class validateValue dispatch (that's TS's architecture); the
|
|
290
|
+
# generic shape check lives here, mirroring C#'s ValueMatchesType
|
|
291
|
+
# ATTR_SUBTYPE_INT_MAP case. field.enum's own key-set/uniqueness content
|
|
292
|
+
# rules run separately in _validate_enum_values (Rule 4), which skips
|
|
293
|
+
# re-reporting a non-integer member already caught here.
|
|
294
|
+
#
|
|
295
|
+
# Final-review fix: also bound every value to the 32-bit signed int range
|
|
296
|
+
# (inclusive) — the eventual DB column for an int-backed enum is a 32-bit
|
|
297
|
+
# Postgres/SQLite `integer` (design doc D5), matching Java's
|
|
298
|
+
# IntMapAttribute#setValueAsString bound check exactly. Python ints have
|
|
299
|
+
# no fixed width, so this is the only place that boundary is enforced.
|
|
300
|
+
return isinstance(value, dict) and all(
|
|
301
|
+
isinstance(v, int)
|
|
302
|
+
and not isinstance(v, bool)
|
|
303
|
+
and -2147483648 <= v <= 2147483647
|
|
304
|
+
for v in value.values()
|
|
305
|
+
)
|
|
284
306
|
# Unknown value types (e.g. "class") — allow anything.
|
|
285
307
|
return True
|
|
286
308
|
|
|
@@ -544,6 +566,32 @@ def _validate_attr_schema(
|
|
|
544
566
|
_ENUM_MEMBER_RE = re.compile(ENUM_MEMBER_PATTERN)
|
|
545
567
|
|
|
546
568
|
|
|
569
|
+
def _shared_enum_super(node: MetaData) -> MetaData | None:
|
|
570
|
+
"""The shared-enum super of ``node``, or ``None`` when it has none.
|
|
571
|
+
|
|
572
|
+
"Shared" (FR-019 / #246) means the immediate super is abstract AND declared at
|
|
573
|
+
metadata-root — its parent is the ``metadata.root`` node, not an object. Such a
|
|
574
|
+
declaration is materialized ONCE per port as a single named type, so anything a
|
|
575
|
+
consuming field re-declares that belongs to the shared TYPE's contract (its
|
|
576
|
+
``@values`` member set, or the ``@intValueMap`` integer backing of that set) is a
|
|
577
|
+
conflict. A concrete super, or a non-root abstract super (e.g. one nested inside
|
|
578
|
+
an object), is legal and not flagged.
|
|
579
|
+
|
|
580
|
+
Immediate-super-only, matching codegen's ``resolve_shared_enum_decl``
|
|
581
|
+
(``codegen/generators/fr019_shared_enum.py``) so the validator and the
|
|
582
|
+
shared-enum collapse agree on what "shared" means.
|
|
583
|
+
"""
|
|
584
|
+
sup = node.super_data
|
|
585
|
+
if (
|
|
586
|
+
sup is not None
|
|
587
|
+
and sup.is_abstract
|
|
588
|
+
and sup.parent is not None
|
|
589
|
+
and sup.parent.type == TYPE_METADATA
|
|
590
|
+
):
|
|
591
|
+
return sup
|
|
592
|
+
return None
|
|
593
|
+
|
|
594
|
+
|
|
547
595
|
def _validate_enum_values(
|
|
548
596
|
root: MetaData,
|
|
549
597
|
errors: list[MetaError],
|
|
@@ -556,6 +604,21 @@ def _validate_enum_values(
|
|
|
556
604
|
# @coerceDefault / @default / @normalize while inheriting @values).
|
|
557
605
|
_validate_enum_fr011_attrs(node, errors)
|
|
558
606
|
|
|
607
|
+
# Rule 4 (@intValueMap content rules) is independent of whether @values is
|
|
608
|
+
# own or inherited on THIS node — it must run whenever this node owns
|
|
609
|
+
# @intValueMap, using the EFFECTIVE @values (own-or-inherited) as the
|
|
610
|
+
# membership set. Mirrors TS/C#/Java, which all check this unconditionally
|
|
611
|
+
# (Java's `validateEnumIntValueMap` is a standalone call at the top of
|
|
612
|
+
# `validateEnumNode`). Deliberately called BEFORE the `own_values is None:
|
|
613
|
+
# continue` gate below so a concrete field.enum that inherits @values via
|
|
614
|
+
# `extends` but declares its own @intValueMap is still validated.
|
|
615
|
+
_validate_enum_int_value_map(node, errors)
|
|
616
|
+
|
|
617
|
+
# Design D7, narrowed: int-backing is scalar-only. Separate from the content
|
|
618
|
+
# rules above because it must fire on the node that combines the two halves,
|
|
619
|
+
# which is NOT necessarily the node that declares the map.
|
|
620
|
+
_validate_enum_int_value_map_not_array(node, errors)
|
|
621
|
+
|
|
559
622
|
# ADR-0039 sanctioned own: validates the AUTHORED @values membership on THIS
|
|
560
623
|
# node (mirrors the TS attr-schema-validate `node.ownAttrs()`); an inherited
|
|
561
624
|
# @values yields None here and is validated on its declaring node.
|
|
@@ -607,19 +670,9 @@ def _validate_enum_values(
|
|
|
607
670
|
|
|
608
671
|
# #246: own @values AND extends a shared package-level abstract enum —
|
|
609
672
|
# one shared enum type has one member set, so the own @values would be
|
|
610
|
-
# silently dropped by the shared-enum codegen collapse.
|
|
611
|
-
#
|
|
612
|
-
|
|
613
|
-
# concrete super, or a non-root abstract super (e.g. nested inside an
|
|
614
|
-
# object), is legal and not flagged. Mirrors the TS reference
|
|
615
|
-
# (attr-schema-validate.ts).
|
|
616
|
-
sup = node.super_data
|
|
617
|
-
if (
|
|
618
|
-
sup is not None
|
|
619
|
-
and sup.is_abstract
|
|
620
|
-
and sup.parent is not None
|
|
621
|
-
and sup.parent.type == TYPE_METADATA
|
|
622
|
-
):
|
|
673
|
+
# silently dropped by the shared-enum codegen collapse. Mirrors the TS
|
|
674
|
+
# reference (attr-schema-validate.ts).
|
|
675
|
+
if _shared_enum_super(node) is not None:
|
|
623
676
|
errors.append(
|
|
624
677
|
MetaError(
|
|
625
678
|
f"{label} declares its own '@{FIELD_ATTR_VALUES}' but extends "
|
|
@@ -633,6 +686,113 @@ def _validate_enum_values(
|
|
|
633
686
|
)
|
|
634
687
|
|
|
635
688
|
|
|
689
|
+
def _validate_enum_int_value_map_not_array(node: MetaData, errors: list[MetaError]) -> None:
|
|
690
|
+
"""``@intValueMap`` is scalar-only (design D7, narrowed).
|
|
691
|
+
|
|
692
|
+
Int-backing is a persistence-layer CODEC, and no port implements it
|
|
693
|
+
element-wise over an array column: this port's ``ObjectManager`` would bind the
|
|
694
|
+
symbol LIST straight into an ``integer[]``, OMDB's ``EnumCodec`` and Kotlin's
|
|
695
|
+
``customEnumeration`` are scalar by construction, and TypeScript's sqlite branch
|
|
696
|
+
serializes an array as JSON text before the enum case is reached. Two ports that
|
|
697
|
+
happen to compose (TS/Postgres, C#) are not a feature — shipping a claim four
|
|
698
|
+
ports silently get wrong is the ``field.byte``/``short``/``class`` mistake.
|
|
699
|
+
|
|
700
|
+
BOTH halves are read RESOLVING, unlike the content rules: the illegal thing is
|
|
701
|
+
the EFFECTIVE combination. Post-#246 the map must live on the shared abstract
|
|
702
|
+
declaration, so the field that inherits it is exactly where ``isArray`` gets
|
|
703
|
+
declared — an own-only read would see the two halves on different nodes and
|
|
704
|
+
never fire.
|
|
705
|
+
"""
|
|
706
|
+
if not isinstance(node.get_meta_attr(FIELD_ATTR_INT_VALUE_MAP), dict):
|
|
707
|
+
return
|
|
708
|
+
if not node.resolved_is_array():
|
|
709
|
+
return
|
|
710
|
+
errors.append(
|
|
711
|
+
MetaError(
|
|
712
|
+
f"{_node_label(node)} declares '@{FIELD_ATTR_INT_VALUE_MAP}' with isArray=true; "
|
|
713
|
+
f"int-backing is scalar-only — an array-of-enum persists its member symbols. "
|
|
714
|
+
f"Remove '@{FIELD_ATTR_INT_VALUE_MAP}', or make the field scalar.",
|
|
715
|
+
ErrorCode.ERR_ENUM_INT_VALUE_MAP_ARRAY,
|
|
716
|
+
envelope=node.source,
|
|
717
|
+
)
|
|
718
|
+
)
|
|
719
|
+
|
|
720
|
+
|
|
721
|
+
def _validate_enum_int_value_map(node: MetaData, errors: list[MetaError]) -> None:
|
|
722
|
+
"""``@intValueMap`` content rules (optional), independent of whether ``@values``
|
|
723
|
+
is own or inherited on this node. Mirrors TS/C#/Java, which all run this check
|
|
724
|
+
unconditionally against the node's EFFECTIVE ``@values`` — a concrete
|
|
725
|
+
``field.enum`` that inherits ``@values`` via ``extends`` but declares its own
|
|
726
|
+
``@intValueMap`` locally must still have that map validated.
|
|
727
|
+
|
|
728
|
+
a. Key set must exactly match the EFFECTIVE ``@values`` (own or inherited).
|
|
729
|
+
b. No two members may share the same int (protobuf's stance — no alias
|
|
730
|
+
opt-in). Every-value-is-an-integer is already enforced by ``_type_ok``'s
|
|
731
|
+
ATTR_SUBTYPE_INT_MAP case at parse time.
|
|
732
|
+
"""
|
|
733
|
+
int_value_map = node.attr(FIELD_ATTR_INT_VALUE_MAP)
|
|
734
|
+
if not isinstance(int_value_map, dict):
|
|
735
|
+
return
|
|
736
|
+
|
|
737
|
+
label = _node_label(node)
|
|
738
|
+
|
|
739
|
+
# #246 (int-backed twin): the symbol->int mapping is a property of the enum
|
|
740
|
+
# VOCABULARY, not of one column that uses it -- it is @values' numeric half. A
|
|
741
|
+
# shared enum is materialized once as a single type, so a per-field map would
|
|
742
|
+
# give one logical type N storage encodings (and, where a port emits per-TYPE
|
|
743
|
+
# codec artifacts, two same-named declarations). Same remedy as the @values
|
|
744
|
+
# half: declare it on the shared declaration and inherit it.
|
|
745
|
+
shared_super = _shared_enum_super(node)
|
|
746
|
+
if shared_super is not None:
|
|
747
|
+
errors.append(
|
|
748
|
+
MetaError(
|
|
749
|
+
f"{label} declares its own '@{FIELD_ATTR_INT_VALUE_MAP}' but extends "
|
|
750
|
+
f"a shared package-level abstract enum — a shared enum's integer "
|
|
751
|
+
f"backing is owned by the shared declaration. Move "
|
|
752
|
+
f"'@{FIELD_ATTR_INT_VALUE_MAP}' onto the shared declaration to "
|
|
753
|
+
f"inherit it, or extend a concrete (non-shared) enum instead",
|
|
754
|
+
ErrorCode.ERR_ENUM_EXTENDS_VALUES_CONFLICT,
|
|
755
|
+
envelope=node.source,
|
|
756
|
+
)
|
|
757
|
+
)
|
|
758
|
+
effective_values = _effective_enum_values(node)
|
|
759
|
+
member_set = set(effective_values)
|
|
760
|
+
key_set = set(int_value_map.keys())
|
|
761
|
+
missing = [m for m in effective_values if m not in key_set]
|
|
762
|
+
extra = [k for k in int_value_map if k not in member_set]
|
|
763
|
+
if missing or extra:
|
|
764
|
+
parts = []
|
|
765
|
+
if missing:
|
|
766
|
+
parts.append(f"missing: {', '.join(missing)}")
|
|
767
|
+
if extra:
|
|
768
|
+
parts.append(f"unknown: {', '.join(extra)}")
|
|
769
|
+
errors.append(
|
|
770
|
+
MetaError(
|
|
771
|
+
f"{label} attribute '@{FIELD_ATTR_INT_VALUE_MAP}' keys must exactly match "
|
|
772
|
+
f"'@{FIELD_ATTR_VALUES}' members ({'; '.join(parts)}).",
|
|
773
|
+
ErrorCode.ERR_BAD_ATTR_VALUE,
|
|
774
|
+
envelope=node.source,
|
|
775
|
+
)
|
|
776
|
+
)
|
|
777
|
+
|
|
778
|
+
seen_values: dict[int, str] = {}
|
|
779
|
+
for member, value in int_value_map.items():
|
|
780
|
+
if not isinstance(value, int) or isinstance(value, bool):
|
|
781
|
+
continue # _type_ok already reported this
|
|
782
|
+
owner = seen_values.get(value)
|
|
783
|
+
if owner is not None:
|
|
784
|
+
errors.append(
|
|
785
|
+
MetaError(
|
|
786
|
+
f"{label} attribute '@{FIELD_ATTR_INT_VALUE_MAP}' members {owner!r} and {member!r} "
|
|
787
|
+
f"share the same value {value}; every member must have a unique int.",
|
|
788
|
+
ErrorCode.ERR_BAD_ATTR_VALUE,
|
|
789
|
+
envelope=node.source,
|
|
790
|
+
)
|
|
791
|
+
)
|
|
792
|
+
else:
|
|
793
|
+
seen_values[value] = member
|
|
794
|
+
|
|
795
|
+
|
|
636
796
|
def _effective_enum_values(node: MetaData) -> list[str]:
|
|
637
797
|
"""The effective ``@values`` members of an enum node (own or inherited via
|
|
638
798
|
``extends:``). Empty list when absent. Mirrors Java ``effectiveEnumValues``."""
|
|
@@ -913,6 +1073,45 @@ def ops_for_subtype(field_subtype: str) -> frozenset[str]:
|
|
|
913
1073
|
return frozenset()
|
|
914
1074
|
|
|
915
1075
|
|
|
1076
|
+
# The int-backed-enum band: the enum band minus `like`. Named so the narrowing is
|
|
1077
|
+
# one constant rather than a set rebuilt at every call.
|
|
1078
|
+
_OPS_ENUM_INT_BACKED: frozenset[str] = frozenset({"eq", "ne", "in", "isNull"})
|
|
1079
|
+
|
|
1080
|
+
|
|
1081
|
+
def ops_for_field(field: MetaData) -> frozenset[str]:
|
|
1082
|
+
"""The filter-operator band for a FIELD.
|
|
1083
|
+
|
|
1084
|
+
The entry point every consumer that has a field in hand must use (loader
|
|
1085
|
+
validation, the codegen filter-allowlist generator, the cross-port
|
|
1086
|
+
``field.filter-ops`` capability).
|
|
1087
|
+
|
|
1088
|
+
Identical to :func:`ops_for_subtype` except for ONE case: an int-backed
|
|
1089
|
+
``field.enum`` (one declaring ``@intValueMap``, design D5) persists as an
|
|
1090
|
+
INTEGER column, so ``like`` -- a substring match -- is dropped.
|
|
1091
|
+
``eq``/``ne``/``in`` survive because the member symbol encodes to its integer
|
|
1092
|
+
before it reaches SQL; ``like`` has no such encoding, and an unencoded
|
|
1093
|
+
``LIKE 'DRAFT'`` against an integer column is a request-time type error.
|
|
1094
|
+
|
|
1095
|
+
``ops_for_subtype`` cannot express this -- it only ever sees the subtype
|
|
1096
|
+
``"enum"`` -- and is deliberately left unchanged for the one caller that
|
|
1097
|
+
genuinely has no field: the expression grammar's declared operand type.
|
|
1098
|
+
|
|
1099
|
+
ADR-0039: the ``@intValueMap`` read is RESOLVING (``attrs()``, NOT ``attr()``
|
|
1100
|
+
-- Python inverts the TS naming, ``attr()`` here is own-only). Post-#246 the
|
|
1101
|
+
map lives on a shared root-level abstract declaration and consuming fields
|
|
1102
|
+
INHERIT it, so an own-only read would see it absent on exactly the shape
|
|
1103
|
+
adopters are steered toward and wrongly keep ``like``.
|
|
1104
|
+
|
|
1105
|
+
Cross-port: ``fixtures/conformance/filter-ops-matrix`` pins ``fEnum`` vs
|
|
1106
|
+
``fEnumInt`` in all five ports.
|
|
1107
|
+
"""
|
|
1108
|
+
if field.sub_type == FIELD_SUBTYPE_ENUM and isinstance(
|
|
1109
|
+
field.attrs().get(FIELD_ATTR_INT_VALUE_MAP), dict
|
|
1110
|
+
):
|
|
1111
|
+
return _OPS_ENUM_INT_BACKED
|
|
1112
|
+
return ops_for_subtype(field.sub_type)
|
|
1113
|
+
|
|
1114
|
+
|
|
916
1115
|
# ---------------------------------------------------------------------------
|
|
917
1116
|
# #195 — attr.expression closed grammar (validate + infer)
|
|
918
1117
|
# ---------------------------------------------------------------------------
|
|
@@ -1095,8 +1294,10 @@ def _validate_datagrid_filter_values(
|
|
|
1095
1294
|
continue
|
|
1096
1295
|
|
|
1097
1296
|
# Build filterable map: field_name → allowed ops set
|
|
1297
|
+
# ops_for_field, not ops_for_subtype — an int-backed field.enum
|
|
1298
|
+
# (@intValueMap) stores as an integer, so `like` is not in its band.
|
|
1098
1299
|
filterable: dict[str, frozenset[str]] = {
|
|
1099
|
-
f.name:
|
|
1300
|
+
f.name: ops_for_field(f)
|
|
1100
1301
|
for f in node.fields()
|
|
1101
1302
|
if f.attrs().get("filterable") is True
|
|
1102
1303
|
}
|
|
@@ -14,6 +14,13 @@ ATTR_SUBTYPE_CLASS = "class"
|
|
|
14
14
|
# ATTR_SUBTYPE_EXPRESSION / meta-attr-expression.ts.
|
|
15
15
|
ATTR_SUBTYPE_EXPRESSION = "expression"
|
|
16
16
|
|
|
17
|
+
# attr.intMap (int-backed-enum-values plan) — an object-shaped attribute whose
|
|
18
|
+
# values are all integers (e.g. field.enum's @intValueMap: {memberSymbol: int}).
|
|
19
|
+
# Generic shape check only; field.enum layers its own semantic rules (key-set
|
|
20
|
+
# membership, uniqueness) in its own content-rule validation pass. Mirrors TS
|
|
21
|
+
# ATTR_SUBTYPE_INT_MAP / C# AttrConstants.ATTR_SUBTYPE_INT_MAP.
|
|
22
|
+
ATTR_SUBTYPE_INT_MAP = "intMap"
|
|
23
|
+
|
|
17
24
|
# The retired "stringarray" array attr subtype. It is NO LONGER a registered
|
|
18
25
|
# (attr, sub_type) (not in ATTR_SUBTYPES) — array-ness is modeled as a "string"
|
|
19
26
|
# attr with the orthogonal AttrSchema.is_array flag (matching Java's
|
|
@@ -33,4 +40,5 @@ ATTR_SUBTYPES = (
|
|
|
33
40
|
ATTR_SUBTYPE_PROPERTIES,
|
|
34
41
|
ATTR_SUBTYPE_CLASS,
|
|
35
42
|
ATTR_SUBTYPE_EXPRESSION,
|
|
43
|
+
ATTR_SUBTYPE_INT_MAP,
|
|
36
44
|
)
|
|
@@ -12,6 +12,7 @@ from .attr_constants import (
|
|
|
12
12
|
ATTR_SUBTYPE_EXPRESSION,
|
|
13
13
|
ATTR_SUBTYPE_FILTER,
|
|
14
14
|
ATTR_SUBTYPE_INT,
|
|
15
|
+
ATTR_SUBTYPE_INT_MAP,
|
|
15
16
|
ATTR_SUBTYPE_LONG,
|
|
16
17
|
ATTR_SUBTYPE_PROPERTIES,
|
|
17
18
|
ATTR_SUBTYPE_STRING,
|
|
@@ -134,6 +135,21 @@ class PropertiesAttr(MetaAttr):
|
|
|
134
135
|
return DataType.OBJECT
|
|
135
136
|
|
|
136
137
|
|
|
138
|
+
class IntMapAttr(MetaAttr):
|
|
139
|
+
"""attr.intMap (int-backed-enum-values plan) — an object-shaped attribute
|
|
140
|
+
whose values are all integers (e.g. field.enum's @intValueMap). Generic
|
|
141
|
+
shape check only; the deeper "every value is an int" check is enforced by
|
|
142
|
+
`_type_ok`'s ATTR_SUBTYPE_INT_MAP case in validation_passes.py (this port
|
|
143
|
+
has no per-attr-class validate_value dispatch — TS's is the one port that
|
|
144
|
+
does; C# mirrors the same "static type-check function" architecture this
|
|
145
|
+
port uses). field.enum's own key-set/uniqueness content rules run in a
|
|
146
|
+
separate pass. Mirrors TS IntMapAttr / C# ATTR_SUBTYPE_INT_MAP shape."""
|
|
147
|
+
|
|
148
|
+
@property
|
|
149
|
+
def data_type(self) -> DataType:
|
|
150
|
+
return DataType.OBJECT
|
|
151
|
+
|
|
152
|
+
|
|
137
153
|
class ClassAttr(MetaAttr):
|
|
138
154
|
@property
|
|
139
155
|
def data_type(self) -> DataType:
|
|
@@ -145,4 +161,5 @@ register_attr_class(ATTR_SUBTYPE_STRINGARRAY, StringArrayAttr)
|
|
|
145
161
|
register_attr_class(ATTR_SUBTYPE_FILTER, FilterAttr)
|
|
146
162
|
register_attr_class(ATTR_SUBTYPE_PROPERTIES, PropertiesAttr)
|
|
147
163
|
register_attr_class(ATTR_SUBTYPE_EXPRESSION, ExpressionAttr)
|
|
164
|
+
register_attr_class(ATTR_SUBTYPE_INT_MAP, IntMapAttr)
|
|
148
165
|
register_attr_class(ATTR_SUBTYPE_CLASS, ClassAttr)
|
{metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/field/field_constants.py
RENAMED
|
@@ -150,3 +150,10 @@ SORT_ORDER_VALUES = (SORT_ORDER_ASC, SORT_ORDER_DESC)
|
|
|
150
150
|
# Regex pattern for enum member symbols — must be identifier-safe.
|
|
151
151
|
# Cross-language contract: every port enforces this pattern.
|
|
152
152
|
ENUM_MEMBER_PATTERN = r"^[A-Za-z_][A-Za-z0-9_]*$"
|
|
153
|
+
|
|
154
|
+
# int-backed-enum-values plan — @intValueMap (field.enum only): optional
|
|
155
|
+
# per-member int values ({member: int}) switching this enum field's DB
|
|
156
|
+
# persistence from string+CHECK to integer+CHECK. Keys must exactly match
|
|
157
|
+
# @values; values must be unique integers. The generated native type and wire
|
|
158
|
+
# format are unchanged in every language. Mirrors TS FIELD_ATTR_INT_VALUE_MAP.
|
|
159
|
+
FIELD_ATTR_INT_VALUE_MAP = "intValueMap"
|
{metaobjects-0.23.0 → metaobjects-0.23.2}/src/metaobjects/meta/core/requirement/meta_requirement.py
RENAMED
|
@@ -54,7 +54,8 @@ class MetaRequirement(MetaData):
|
|
|
54
54
|
return [str(x) for x in v] if isinstance(v, list) else []
|
|
55
55
|
|
|
56
56
|
def verified_by(self) -> list[str]:
|
|
57
|
-
"""ADR-0039: resolving. Names of
|
|
57
|
+
"""ADR-0039: resolving. Names of tests that ASSERT the behaviour — existence
|
|
58
|
+
evidence only; verify cannot tell whether a named test verifies this."""
|
|
58
59
|
v = self.get_meta_attr(REQUIREMENT_ATTR_VERIFIED_BY)
|
|
59
60
|
return [str(x) for x in v] if isinstance(v, list) else []
|
|
60
61
|
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""Derived boolean accessors — ``{{#hasFoo}}`` over a payload field ``foo``.
|
|
2
|
+
|
|
3
|
+
A prompt needs conditional sections ("include the abilities block only when there ARE
|
|
4
|
+
abilities"), and the payload contract answers that with a DERIVED accessor rather than an
|
|
5
|
+
authored boolean field: the author declares ``abilities`` and ``hasAbilities`` follows
|
|
6
|
+
from it. Declaring both would let them disagree.
|
|
7
|
+
|
|
8
|
+
THE RULE IS SHARED ACROSS PORTS ON PURPOSE. The JVM has carried it since 7.7.7
|
|
9
|
+
(``com.metaobjects.render.PayloadAccessors``, emitted onto every generated payload record
|
|
10
|
+
and accepted by its ``Verify``), and its comment says the emitter and the verifier share
|
|
11
|
+
one rule so they "can never drift apart". Python had neither half, so the same template
|
|
12
|
+
verified clean on the JVM and reported drift here — and rendered WRONG rather than
|
|
13
|
+
failing, silently dropping the section. Gated cross-port by the
|
|
14
|
+
``render-derived-has-accessor`` conformance case.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import numbers
|
|
20
|
+
from collections.abc import Mapping, Sequence
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"HAS_PREFIX",
|
|
25
|
+
"has_accessor_name",
|
|
26
|
+
"capitalize",
|
|
27
|
+
"accessor_value",
|
|
28
|
+
"with_derived_accessors",
|
|
29
|
+
"is_boolean_accessor",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
#: The ``has`` prefix every derived boolean accessor carries.
|
|
33
|
+
HAS_PREFIX = "has"
|
|
34
|
+
|
|
35
|
+
_MAX_DEPTH = 32
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def capitalize(s: str) -> str:
|
|
39
|
+
"""Capitalize the first character, leaving an already-uppercase one untouched.
|
|
40
|
+
|
|
41
|
+
Deliberately NOT ``str.capitalize()``, which also lowercases the remainder.
|
|
42
|
+
"""
|
|
43
|
+
if not s:
|
|
44
|
+
return s
|
|
45
|
+
if s[0].isupper():
|
|
46
|
+
return s
|
|
47
|
+
return s[0].upper() + s[1:]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def has_accessor_name(field_name: str) -> str:
|
|
51
|
+
"""``"has" + capitalize(name)`` (``abilities`` → ``hasAbilities``).
|
|
52
|
+
|
|
53
|
+
Byte-identical to the JVM's ``PayloadAccessors.hasAccessorName``.
|
|
54
|
+
"""
|
|
55
|
+
return HAS_PREFIX + capitalize(field_name)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def accessor_value(value: Any) -> bool | None:
|
|
59
|
+
"""Is ``value`` "present" for the purposes of ``has<Field>``?
|
|
60
|
+
|
|
61
|
+
Mirrors the JVM emitter's per-type bodies exactly: string → non-null and non-blank;
|
|
62
|
+
collection → non-null and non-empty; reference → non-null.
|
|
63
|
+
|
|
64
|
+
Returns ``None`` for numbers and booleans, which the JVM deliberately emits NO
|
|
65
|
+
accessor for — they are always-present scalars, and ``{{#hasCount}}`` over an int is
|
|
66
|
+
drift rather than a conditional. Returning ``None`` (rather than ``False``) keeps that
|
|
67
|
+
distinction: nothing is injected, so the name stays unresolved exactly as it is on a
|
|
68
|
+
generated record with no such method.
|
|
69
|
+
"""
|
|
70
|
+
if value is None:
|
|
71
|
+
return False
|
|
72
|
+
if isinstance(value, str):
|
|
73
|
+
return bool(value.strip())
|
|
74
|
+
# bool before int — bool IS an int in Python, and a boolean field gets no accessor.
|
|
75
|
+
if isinstance(value, numbers.Number):
|
|
76
|
+
return None
|
|
77
|
+
if isinstance(value, Mapping):
|
|
78
|
+
return True
|
|
79
|
+
if isinstance(value, (Sequence, set, frozenset)):
|
|
80
|
+
return len(value) > 0
|
|
81
|
+
return True
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def with_derived_accessors(payload: Any, depth: int = 0) -> Any:
|
|
85
|
+
"""A view over ``payload`` carrying its derived ``has<Field>`` accessors, recursively.
|
|
86
|
+
|
|
87
|
+
NON-MUTATING — the caller's payload is never touched, because a render must not be
|
|
88
|
+
able to change the object it was handed. An AUTHORED key always wins: if a payload
|
|
89
|
+
genuinely carries ``hasFoo``, that value is kept rather than shadowed.
|
|
90
|
+
|
|
91
|
+
Recursion follows Mustache's own scoping: every nested mapping and every sequence
|
|
92
|
+
ELEMENT becomes a context in its own right, so a section over ``abilities`` sees the
|
|
93
|
+
accessors of the ability it is currently iterating.
|
|
94
|
+
"""
|
|
95
|
+
if depth > _MAX_DEPTH:
|
|
96
|
+
return payload # pathological graph; render is not a validator
|
|
97
|
+
if isinstance(payload, Mapping):
|
|
98
|
+
out: dict[str, Any] = {
|
|
99
|
+
k: with_derived_accessors(v, depth + 1) for k, v in payload.items()
|
|
100
|
+
}
|
|
101
|
+
for k, v in payload.items():
|
|
102
|
+
if not isinstance(k, str):
|
|
103
|
+
continue
|
|
104
|
+
name = has_accessor_name(k)
|
|
105
|
+
if name in payload: # authored wins
|
|
106
|
+
continue
|
|
107
|
+
derived = accessor_value(v)
|
|
108
|
+
if derived is not None:
|
|
109
|
+
out[name] = derived
|
|
110
|
+
return out
|
|
111
|
+
if isinstance(payload, (str, bytes)):
|
|
112
|
+
return payload
|
|
113
|
+
if isinstance(payload, Sequence):
|
|
114
|
+
return [with_derived_accessors(v, depth + 1) for v in payload]
|
|
115
|
+
return payload
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def is_boolean_accessor(stack: list[list[Any]], name: str) -> bool:
|
|
119
|
+
"""True when ``name`` is a derived accessor over a field reachable on ``stack``.
|
|
120
|
+
|
|
121
|
+
Mirrors the JVM's ``Verify.isBooleanAccessor``, including its deliberate
|
|
122
|
+
permissiveness: acceptance keys off the FIELD EXISTING, not off its type. Accessors
|
|
123
|
+
are simple (undotted) names; a dotted path is never an accessor.
|
|
124
|
+
"""
|
|
125
|
+
if "." in name:
|
|
126
|
+
return False
|
|
127
|
+
if not name.startswith(HAS_PREFIX):
|
|
128
|
+
return False
|
|
129
|
+
# Mustache outward walk (innermost → outermost).
|
|
130
|
+
for frame in reversed(stack):
|
|
131
|
+
for f in frame:
|
|
132
|
+
if name == has_accessor_name(f.name):
|
|
133
|
+
return True
|
|
134
|
+
return False
|