modelable 1.2.0__tar.gz → 1.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of modelable might be problematic. Click here for more details.
- {modelable-1.2.0 → modelable-1.2.1}/PKG-INFO +1 -1
- {modelable-1.2.0 → modelable-1.2.1}/mypy-baseline.txt +20 -20
- {modelable-1.2.0 → modelable-1.2.1}/pyproject.toml +1 -1
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/rust.py +49 -8
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_emit_rust.py +168 -0
- {modelable-1.2.0 → modelable-1.2.1}/uv.lock +1 -1
- {modelable-1.2.0 → modelable-1.2.1}/.gitignore +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/.python-version +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/LICENSE +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/README.md +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/__init__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/__main__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/_pydantic_py314_compat.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/cli.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/commands/__init__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/commands/apicurio.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/commands/codegen.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/commands/common.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/commands/compile.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/commands/create.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/commands/diff.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/commands/graph.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/commands/llm.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/commands/lsp.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/commands/runtime.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/commands/scenario.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/commands/spec.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/commands/sync.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/commands/workspace.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/compat/__init__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/compat/checker.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/compat/diff.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/compiler/__init__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/compiler/compiler.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/compiler/workspace.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/diagnostics/__init__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/diagnostics/model.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/__init__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/base.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/csharp.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/dbt_yaml.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/diagnostics.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/fhir.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/fhir_validator.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/go.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/grpc.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/java.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/json_schema.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/markdown.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/odcs.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/openlineage.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/openmetadata.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/protobuf.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/python.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/shapes.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/sql.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/targets.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/emitters/typescript.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/expressions/__init__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/expressions/cel.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/governance/__init__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/governance/checker.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/governance/por.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/grammar/__init__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/grammar/modelable.lark +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/graph/__init__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/graph/export.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/llm/__init__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/llm/chat.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/llm/config.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/llm/context.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/llm/engine.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/llm/importers.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/llm/provenance.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/llm/providers.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/llm/qa.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/llm/recommendations.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/llm/redaction.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/llm/render.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/llm/update_plan.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/llm/validation_help.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/lsp/__init__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/lsp/__main__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/lsp/code_actions.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/lsp/completion.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/lsp/definition.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/lsp/diagnostics.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/lsp/document_symbols.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/lsp/federation.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/lsp/folding.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/lsp/formatting.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/lsp/highlight.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/lsp/hover.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/lsp/inlay_hints.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/lsp/references.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/lsp/rename.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/lsp/semantic_tokens.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/lsp/server.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/lsp/workspace.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/lsp/workspace_symbols.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/parser/__init__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/parser/ir.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/parser/parse.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/parser/transformer.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/parser/wire.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/planner/__init__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/planner/lineage.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/planner/planner.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/planner/plans.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/py.typed +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/registry/__init__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/registry/apicurio.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/registry/base.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/registry/factory.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/registry/ids.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/registry/index.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/registry/local.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/registry/oci.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/registry/openlineage.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/registry/resolver.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/registry/schema.sql +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/registry/signature.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/release.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/runtime/__init__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/runtime/adapter/__init__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/runtime/adapter/base.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/runtime/adapter/postgres.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/specs/__init__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/specs/tracking.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/validation/__init__.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/src/modelable/validation/semantic.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/conftest.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/auto_projection_complex.mdl +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/billing_projection.mdl +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/breaking_changes.mdl +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/cel_error_cases.mdl +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/customer.mdl +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/federation_multi_registry/consumer.mdl +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/federation_multi_registry/provider.mdl +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/federation_multi_registry/workspace.mdl +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/fhir_patient_profile.mdl +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/governance_export_model.mdl +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/materialized_projection_chain.mdl +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/missing_header.mdl +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/multi_domain_joins.mdl +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/multi_language_target.mdl +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/no_owner.mdl +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/pii_governance.mdl +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/projection_of_projection.mdl +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/sql_and_dbt_targets.mdl +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/wire_golden/golden/protobuf/platform_widget_v1.proto +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/wire_golden/golden/rust/platform_widget_v1.rs +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/fixtures/wire_golden/wire_golden.mdl +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/helpers.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_apicurio_registry.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_apicurio_testcontainers.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_auto_projection.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_cel_validation.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_cli.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_cli_compile.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_cli_create.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_cli_inspect.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_codegen_docker_smoke.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_codegen_targets.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_compatibility.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_compiler.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_conformance_fixture.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_diagnostics.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_emit_csharp.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_emit_dbt_yaml.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_emit_fhir.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_emit_go.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_emit_grpc.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_emit_java.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_emit_json_schema.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_emit_markdown.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_emit_odcs.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_emit_openlineage.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_emit_openmetadata.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_emit_protobuf.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_emit_python.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_emit_sql.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_emit_typescript.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_fhir_validator.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_fixtures_regression.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_governance.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_grammar.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_graph_export.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_impact_analysis.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lineage.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_llm_features.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_llm_provider_integration.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_code_actions.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_completion.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_completion_mirrors.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_definition.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_diagnostics.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_document_symbols.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_features.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_federation_diagnostics.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_folding.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_formatting.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_highlight.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_hover.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_inlay_hints.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_integration.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_references.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_rename.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_semantic_tokens.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_server.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_workspace.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_lsp_workspace_symbols.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_mypy_baseline.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_openlineage_sync.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_openlineage_testcontainers.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_openmetadata_testcontainers.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_planner.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_por.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_postgres_adapter.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_py314_compat.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_registry.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_registry_ids.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_registry_index.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_release_metadata.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_release_workflow.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_repository_release.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_resolver.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_samples.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_semantic.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_serialization_hints.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_spec_tracking.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_transformer.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_validate_surface_detection.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_version_range_resolution.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_wire_golden.py +0 -0
- {modelable-1.2.0 → modelable-1.2.1}/tests/test_workspace.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: modelable
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.1
|
|
4
4
|
Summary: Compiler and language server for versioned, domain-owned data models
|
|
5
5
|
Project-URL: Homepage, https://github.com/ktjn/modelable
|
|
6
6
|
Project-URL: Documentation, https://ktjn.github.io/modelable/
|
|
@@ -133,35 +133,35 @@ src/modelable/emitters/python.py:279: error: Function is missing a type annotati
|
|
|
133
133
|
src/modelable/emitters/python.py:293: error: Item "ProjectionField" of "FieldDef | ProjectionField" has no attribute "optional" [union-attr]
|
|
134
134
|
src/modelable/emitters/python.py:293: error: Item "ProjectionField" of "FieldDef | ProjectionField" has no attribute "type" [union-attr]
|
|
135
135
|
src/modelable/emitters/python.py:75: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
|
136
|
+
src/modelable/emitters/rust.py:1001: error: Item "ProjectionField" of "FieldDef | ProjectionField" has no attribute "optional" [union-attr]
|
|
137
|
+
src/modelable/emitters/rust.py:1001: error: Item "ProjectionField" of "FieldDef | ProjectionField" has no attribute "type" [union-attr]
|
|
138
|
+
src/modelable/emitters/rust.py:1005: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
|
139
|
+
src/modelable/emitters/rust.py:1005: error: Missing type arguments for generic type "dict" [type-arg]
|
|
140
|
+
src/modelable/emitters/rust.py:1013: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return]
|
|
141
|
+
src/modelable/emitters/rust.py:1018: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return]
|
|
142
|
+
src/modelable/emitters/rust.py:1022: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return]
|
|
136
143
|
src/modelable/emitters/rust.py:116: error: Missing type arguments for generic type "dict" [type-arg]
|
|
137
144
|
src/modelable/emitters/rust.py:128: error: Incompatible types in assignment (expression has type "list[ProjectionVersion]", variable has type "list[ModelVersion]") [assignment]
|
|
138
145
|
src/modelable/emitters/rust.py:130: error: "ModelVersion" has no attribute "source" [attr-defined]
|
|
139
146
|
src/modelable/emitters/rust.py:135: error: Argument 3 to "_emit_projection" has incompatible type "ModelVersion"; expected "ProjectionVersion" [arg-type]
|
|
140
147
|
src/modelable/emitters/rust.py:190: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
|
141
148
|
src/modelable/emitters/rust.py:190: error: Missing type arguments for generic type "set" [type-arg]
|
|
142
|
-
src/modelable/emitters/rust.py:
|
|
143
|
-
src/modelable/emitters/rust.py:
|
|
144
|
-
src/modelable/emitters/rust.py:
|
|
145
|
-
src/modelable/emitters/rust.py:
|
|
149
|
+
src/modelable/emitters/rust.py:211: error: Missing type arguments for generic type "set" [type-arg]
|
|
150
|
+
src/modelable/emitters/rust.py:326: error: Missing type arguments for generic type "dict" [type-arg]
|
|
151
|
+
src/modelable/emitters/rust.py:387: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
|
152
|
+
src/modelable/emitters/rust.py:396: error: Missing type arguments for generic type "dict" [type-arg]
|
|
146
153
|
src/modelable/emitters/rust.py:41: error: Missing type arguments for generic type "dict" [type-arg]
|
|
147
|
-
src/modelable/emitters/rust.py:
|
|
154
|
+
src/modelable/emitters/rust.py:495: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
|
148
155
|
src/modelable/emitters/rust.py:56: error: Missing type arguments for generic type "frozenset" [type-arg]
|
|
149
|
-
src/modelable/emitters/rust.py:
|
|
150
|
-
src/modelable/emitters/rust.py:
|
|
151
|
-
src/modelable/emitters/rust.py:
|
|
152
|
-
src/modelable/emitters/rust.py:
|
|
153
|
-
src/modelable/emitters/rust.py:
|
|
154
|
-
src/modelable/emitters/rust.py:
|
|
156
|
+
src/modelable/emitters/rust.py:609: error: Missing type arguments for generic type "dict" [type-arg]
|
|
157
|
+
src/modelable/emitters/rust.py:776: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
|
158
|
+
src/modelable/emitters/rust.py:823: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
|
159
|
+
src/modelable/emitters/rust.py:852: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
|
160
|
+
src/modelable/emitters/rust.py:878: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
|
161
|
+
src/modelable/emitters/rust.py:892: error: Returning Any from function declared to return "str" [no-any-return]
|
|
155
162
|
src/modelable/emitters/rust.py:93: error: Item "dict[str, object]" of "dict[str, object] | str" has no attribute "rstrip" [union-attr]
|
|
156
|
-
src/modelable/emitters/rust.py:
|
|
157
|
-
src/modelable/emitters/rust.py:
|
|
158
|
-
src/modelable/emitters/rust.py:960: error: Item "ProjectionField" of "FieldDef | ProjectionField" has no attribute "optional" [union-attr]
|
|
159
|
-
src/modelable/emitters/rust.py:960: error: Item "ProjectionField" of "FieldDef | ProjectionField" has no attribute "type" [union-attr]
|
|
160
|
-
src/modelable/emitters/rust.py:964: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
|
161
|
-
src/modelable/emitters/rust.py:964: error: Missing type arguments for generic type "dict" [type-arg]
|
|
162
|
-
src/modelable/emitters/rust.py:972: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return]
|
|
163
|
-
src/modelable/emitters/rust.py:977: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return]
|
|
164
|
-
src/modelable/emitters/rust.py:981: error: Returning Any from function declared to return "dict[Any, Any]" [no-any-return]
|
|
163
|
+
src/modelable/emitters/rust.py:987: error: Function is missing a return type annotation [no-untyped-def]
|
|
164
|
+
src/modelable/emitters/rust.py:987: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
|
165
165
|
src/modelable/emitters/sql.py:196: error: Function is missing a return type annotation [no-untyped-def]
|
|
166
166
|
src/modelable/emitters/sql.py:196: error: Function is missing a type annotation for one or more parameters [no-untyped-def]
|
|
167
167
|
src/modelable/emitters/sql.py:211: error: Function is missing a return type annotation [no-untyped-def]
|
|
@@ -198,6 +198,16 @@ def _collect_named_type_refs(field_type, result: set) -> None:
|
|
|
198
198
|
_collect_named_type_refs(field_type.value, result)
|
|
199
199
|
|
|
200
200
|
|
|
201
|
+
def _collect_named_type_refs_from_shape(shape: TypeShape, result: set[str]) -> None:
|
|
202
|
+
"""Recursively collect NamedType references from a resolved TypeShape."""
|
|
203
|
+
if shape.kind == "named" and shape.ref:
|
|
204
|
+
result.add(shape.ref)
|
|
205
|
+
elif shape.kind == "array" and shape.element is not None:
|
|
206
|
+
_collect_named_type_refs_from_shape(shape.element, result)
|
|
207
|
+
elif shape.kind == "map" and shape.value is not None:
|
|
208
|
+
_collect_named_type_refs_from_shape(shape.value, result)
|
|
209
|
+
|
|
210
|
+
|
|
201
211
|
def _resolve_named_type_map(named_refs: set, mdl: MdlFile | None) -> tuple[dict[str, str], list[str]]:
|
|
202
212
|
"""Resolve NamedType references to Rust type names from the workspace.
|
|
203
213
|
|
|
@@ -207,7 +217,7 @@ def _resolve_named_type_map(named_refs: set, mdl: MdlFile | None) -> tuple[dict[
|
|
|
207
217
|
return {}, []
|
|
208
218
|
resolved_map: dict[str, str] = {}
|
|
209
219
|
use_statements: list[str] = []
|
|
210
|
-
for name in named_refs:
|
|
220
|
+
for name in sorted(named_refs):
|
|
211
221
|
resolved = False
|
|
212
222
|
for domain in mdl.domains:
|
|
213
223
|
if name in domain.models:
|
|
@@ -351,8 +361,13 @@ def _emit_model(
|
|
|
351
361
|
needs_serde_with = _any_needs_serde_with(field_specs)
|
|
352
362
|
needs_uuid = _any_needs_uuid(field_specs)
|
|
353
363
|
needs_serde_json = _any_needs_serde_json(field_specs)
|
|
364
|
+
needs_hashmap = _any_needs_hashmap(field_specs, nested_definitions)
|
|
354
365
|
lines = _header_lines(
|
|
355
|
-
serde_with=needs_serde_with,
|
|
366
|
+
serde_with=needs_serde_with,
|
|
367
|
+
uuid=needs_uuid,
|
|
368
|
+
serde_json=needs_serde_json,
|
|
369
|
+
hashmap=needs_hashmap,
|
|
370
|
+
extra_uses=use_statements,
|
|
356
371
|
)
|
|
357
372
|
lines.extend(_render_struct_definition(type_name, field_specs))
|
|
358
373
|
lines.extend(_render_nested_definitions(nested_definitions))
|
|
@@ -385,10 +400,19 @@ def _emit_projection(
|
|
|
385
400
|
nested_definitions: dict[str, list[str]] = {}
|
|
386
401
|
local_enum_info: dict[str, list[str]] = {}
|
|
387
402
|
|
|
403
|
+
field_shapes: dict[str, TypeShape | None] = {
|
|
404
|
+
field.name: _resolve_projection_field_shape(field, version, mdl) for field in version.fields
|
|
405
|
+
}
|
|
406
|
+
named_refs: set[str] = set()
|
|
407
|
+
for field_shape in field_shapes.values():
|
|
408
|
+
if field_shape is not None:
|
|
409
|
+
_collect_named_type_refs_from_shape(field_shape, named_refs)
|
|
410
|
+
named_type_map, use_statements = _resolve_named_type_map(named_refs, mdl)
|
|
411
|
+
|
|
388
412
|
field_specs: list[_FieldSpec] = []
|
|
389
413
|
warnings: list[str] = []
|
|
390
414
|
for index, field in enumerate(version.fields):
|
|
391
|
-
field_shape =
|
|
415
|
+
field_shape = field_shapes[field.name]
|
|
392
416
|
if field_shape is None:
|
|
393
417
|
warnings.append(type_loss(f"{domain.name}.{projection_name}.{field.name}"))
|
|
394
418
|
field_specs.append(_FieldSpec(index=index, name=field.name, annotation="String", optional=False))
|
|
@@ -407,6 +431,7 @@ def _emit_projection(
|
|
|
407
431
|
rust_hint=wire.get("rust"),
|
|
408
432
|
clickhouse_hint=wire.get("clickhouse"),
|
|
409
433
|
enum_info=local_enum_info,
|
|
434
|
+
named_type_map=named_type_map,
|
|
410
435
|
)
|
|
411
436
|
optional = field_shape.optional or field_shape.nullable
|
|
412
437
|
serde_attrs = _serde_attrs_for_field(wire, field_shape, clickhouse=clickhouse_row)
|
|
@@ -421,6 +446,7 @@ def _emit_projection(
|
|
|
421
446
|
needs_serde_json = _any_needs_serde_json(field_specs) or any(
|
|
422
447
|
_projection_field_is_json_passthrough_to_string(f, version, mdl) for f in version.fields
|
|
423
448
|
)
|
|
449
|
+
needs_hashmap = _any_needs_hashmap(field_specs, nested_definitions)
|
|
424
450
|
storage_gated = sqlx_fromrow or clickhouse_row
|
|
425
451
|
extra_derives: list[str] = []
|
|
426
452
|
if sqlx_fromrow:
|
|
@@ -433,6 +459,8 @@ def _emit_projection(
|
|
|
433
459
|
clickhouse=clickhouse_row,
|
|
434
460
|
uuid=needs_uuid,
|
|
435
461
|
serde_json=needs_serde_json,
|
|
462
|
+
hashmap=needs_hashmap,
|
|
463
|
+
extra_uses=use_statements,
|
|
436
464
|
)
|
|
437
465
|
lines.extend(
|
|
438
466
|
_render_struct_definition(type_name, field_specs, extra_derives=extra_derives, storage_gated=storage_gated)
|
|
@@ -541,6 +569,9 @@ def _emit_from_impl(
|
|
|
541
569
|
lines.append(f"use super::{src_module}::{enum_type};")
|
|
542
570
|
if storage_gated:
|
|
543
571
|
lines.append('#[cfg(feature = "storage")]')
|
|
572
|
+
# Direct-mapped fields always go through `.into()` below, which is a no-op
|
|
573
|
+
# (and a clippy lint) when the source and projected field share a type.
|
|
574
|
+
lines.append("#[allow(clippy::useless_conversion)]")
|
|
544
575
|
lines.append(f"impl From<{src_type_name}> for {proj_type_name} {{")
|
|
545
576
|
lines.append(f" fn from(src: {src_type_name}) -> Self {{")
|
|
546
577
|
lines.append(" Self {")
|
|
@@ -608,6 +639,16 @@ def _any_needs_serde_json(field_specs: list[_FieldSpec]) -> bool:
|
|
|
608
639
|
return any("serde_json::Value" in spec.annotation for spec in field_specs)
|
|
609
640
|
|
|
610
641
|
|
|
642
|
+
def _any_needs_hashmap(field_specs: list[_FieldSpec], nested_definitions: dict[str, list[str]] | None = None) -> bool:
|
|
643
|
+
if any("HashMap<" in spec.annotation for spec in field_specs):
|
|
644
|
+
return True
|
|
645
|
+
if nested_definitions:
|
|
646
|
+
for lines in nested_definitions.values():
|
|
647
|
+
if any("HashMap<" in line for line in lines):
|
|
648
|
+
return True
|
|
649
|
+
return False
|
|
650
|
+
|
|
651
|
+
|
|
611
652
|
def _shape_involves_object(shape: TypeShape) -> bool:
|
|
612
653
|
"""Return True if the shape contains an inline object type.
|
|
613
654
|
|
|
@@ -630,13 +671,13 @@ def _header_lines(
|
|
|
630
671
|
clickhouse: bool = False,
|
|
631
672
|
uuid: bool = False,
|
|
632
673
|
serde_json: bool = False,
|
|
674
|
+
hashmap: bool = False,
|
|
633
675
|
extra_uses: list[str] | None = None,
|
|
634
676
|
) -> list[str]:
|
|
635
|
-
lines = [
|
|
636
|
-
|
|
637
|
-
"use std::collections::HashMap;"
|
|
638
|
-
|
|
639
|
-
]
|
|
677
|
+
lines = ["// @generated by Modelable"]
|
|
678
|
+
if hashmap:
|
|
679
|
+
lines.append("use std::collections::HashMap;")
|
|
680
|
+
lines.append("")
|
|
640
681
|
if clickhouse:
|
|
641
682
|
lines.insert(1, "// requires: clickhouse (https://docs.rs/clickhouse)")
|
|
642
683
|
if sqlx:
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import hashlib
|
|
2
|
+
import os
|
|
3
|
+
import subprocess
|
|
4
|
+
import sys
|
|
2
5
|
|
|
3
6
|
from click.testing import CliRunner
|
|
4
7
|
|
|
@@ -388,6 +391,168 @@ domain customer {
|
|
|
388
391
|
assert "pub name: String," in proj_art.content
|
|
389
392
|
|
|
390
393
|
|
|
394
|
+
def test_emit_rust_projection_imports_named_type_fields(tmp_path):
|
|
395
|
+
mdl = tmp_path / "test.mdl"
|
|
396
|
+
mdl.write_text(
|
|
397
|
+
"""
|
|
398
|
+
domain orders {
|
|
399
|
+
owner: "test-team"
|
|
400
|
+
|
|
401
|
+
semantic BuyerId : uuid(7)
|
|
402
|
+
|
|
403
|
+
value OrderLine @ 1 (additive) {
|
|
404
|
+
sku: string
|
|
405
|
+
quantity: u32
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
event OrderPlaced @ 1 (additive) {
|
|
409
|
+
orderId: uuid
|
|
410
|
+
buyerId: BuyerId
|
|
411
|
+
lines: array<OrderLine>
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
projection OrderHistory @ 1
|
|
415
|
+
from orders.OrderPlaced @ 1 as placed
|
|
416
|
+
{
|
|
417
|
+
orderId <- placed.orderId
|
|
418
|
+
buyerId <- placed.buyerId
|
|
419
|
+
lines <- placed.lines
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
""",
|
|
423
|
+
encoding="utf-8",
|
|
424
|
+
)
|
|
425
|
+
from modelable.compiler.workspace import load_workspace
|
|
426
|
+
|
|
427
|
+
workspace = load_workspace(tmp_path)
|
|
428
|
+
artifacts = emit_rust(workspace, tmp_path / "out")
|
|
429
|
+
proj_art = next(a for a in artifacts if a.ref == "orders.OrderHistory@1")
|
|
430
|
+
# Field types must be the generated Rust type names, not the raw .mdl names.
|
|
431
|
+
assert "pub buyer_id: BuyerId," in proj_art.content
|
|
432
|
+
assert "pub lines: Vec<OrdersOrderLineV1>," in proj_art.content
|
|
433
|
+
# Every named type referenced by a field must have a matching use import.
|
|
434
|
+
assert "use super::buyer_id::BuyerId;" in proj_art.content
|
|
435
|
+
assert "use super::orders_order_line_v1::OrdersOrderLineV1;" in proj_art.content
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
def test_emit_rust_named_type_use_statements_are_hash_seed_independent(tmp_path):
|
|
439
|
+
"""Rust output must be byte-identical across processes/interpreters.
|
|
440
|
+
|
|
441
|
+
`use` statements for named-type fields are built by iterating a `set` of
|
|
442
|
+
reference names. CPython's set iteration order for strings depends on
|
|
443
|
+
PYTHONHASHSEED, so an unsorted iteration reorders the generated `use`
|
|
444
|
+
lines between runs unless the seed is pinned — breaking reproducible
|
|
445
|
+
builds. Run the emitter in two subprocesses with different hash seeds
|
|
446
|
+
and require identical output.
|
|
447
|
+
"""
|
|
448
|
+
mdl = tmp_path / "test.mdl"
|
|
449
|
+
mdl.write_text(
|
|
450
|
+
"""
|
|
451
|
+
domain orders {
|
|
452
|
+
owner: "test-team"
|
|
453
|
+
|
|
454
|
+
semantic BuyerId : uuid(7)
|
|
455
|
+
semantic CartId : uuid(7)
|
|
456
|
+
semantic OrderId : uuid(7)
|
|
457
|
+
|
|
458
|
+
value OrderLine @ 1 (additive) {
|
|
459
|
+
sku: string
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
entity Order @ 1 (additive) {
|
|
463
|
+
@key orderId: OrderId
|
|
464
|
+
cartId: CartId
|
|
465
|
+
buyerId: BuyerId
|
|
466
|
+
lines: array<OrderLine>
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
event OrderPlaced @ 1 (additive) {
|
|
470
|
+
orderId: OrderId
|
|
471
|
+
cartId: CartId
|
|
472
|
+
buyerId: BuyerId
|
|
473
|
+
lines: array<OrderLine>
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
projection OrderHistory @ 1
|
|
477
|
+
from orders.OrderPlaced @ 1 as placed
|
|
478
|
+
{
|
|
479
|
+
orderId <- placed.orderId
|
|
480
|
+
cartId <- placed.cartId
|
|
481
|
+
buyerId <- placed.buyerId
|
|
482
|
+
lines <- placed.lines
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
""",
|
|
486
|
+
encoding="utf-8",
|
|
487
|
+
)
|
|
488
|
+
script = tmp_path / "emit.py"
|
|
489
|
+
script.write_text(
|
|
490
|
+
"import sys\n"
|
|
491
|
+
"from pathlib import Path\n"
|
|
492
|
+
"from modelable.compiler.workspace import load_workspace\n"
|
|
493
|
+
"from modelable.emitters.rust import emit_rust\n"
|
|
494
|
+
"workspace = load_workspace(Path(sys.argv[1]))\n"
|
|
495
|
+
"artifacts = emit_rust(workspace, Path(sys.argv[1]) / 'out')\n"
|
|
496
|
+
"for artifact in sorted(artifacts, key=lambda a: a.ref):\n"
|
|
497
|
+
" print(artifact.ref)\n"
|
|
498
|
+
" print(artifact.content)\n",
|
|
499
|
+
encoding="utf-8",
|
|
500
|
+
)
|
|
501
|
+
|
|
502
|
+
def run_with_seed(seed: str) -> str:
|
|
503
|
+
env = {**os.environ, "PYTHONHASHSEED": seed}
|
|
504
|
+
result = subprocess.run(
|
|
505
|
+
[sys.executable, str(script), str(tmp_path)],
|
|
506
|
+
capture_output=True,
|
|
507
|
+
text=True,
|
|
508
|
+
env=env,
|
|
509
|
+
check=True,
|
|
510
|
+
)
|
|
511
|
+
return result.stdout
|
|
512
|
+
|
|
513
|
+
output_seed_0 = run_with_seed("0")
|
|
514
|
+
output_seed_1 = run_with_seed("1")
|
|
515
|
+
assert output_seed_0 == output_seed_1
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
def test_emit_rust_omits_hashmap_import_when_unused(tmp_path):
|
|
519
|
+
mdl = tmp_path / "test.mdl"
|
|
520
|
+
mdl.write_text(
|
|
521
|
+
"""
|
|
522
|
+
domain orders {
|
|
523
|
+
owner: "test-team"
|
|
524
|
+
value OrderLine @ 1 (additive) {
|
|
525
|
+
sku: string
|
|
526
|
+
quantity: u32
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
entity Order @ 1 (additive) {
|
|
530
|
+
@key orderId: uuid
|
|
531
|
+
lines: array<OrderLine>
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
projection OrderView @ 1
|
|
535
|
+
from orders.Order @ 1 as o
|
|
536
|
+
{
|
|
537
|
+
orderId <- o.orderId
|
|
538
|
+
lines <- o.lines
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
""",
|
|
542
|
+
encoding="utf-8",
|
|
543
|
+
)
|
|
544
|
+
workspace = load_workspace(tmp_path)
|
|
545
|
+
artifacts = emit_rust(workspace, tmp_path / "out")
|
|
546
|
+
# Neither struct has a map field, so the HashMap import (and the unused
|
|
547
|
+
# import it would otherwise produce) must not appear.
|
|
548
|
+
line_art = next(a for a in artifacts if a.ref == "orders.OrderLine@1")
|
|
549
|
+
order_art = next(a for a in artifacts if a.ref == "orders.Order@1")
|
|
550
|
+
view_art = next(a for a in artifacts if a.ref == "orders.OrderView@1")
|
|
551
|
+
assert "use std::collections::HashMap;" not in line_art.content
|
|
552
|
+
assert "use std::collections::HashMap;" not in order_art.content
|
|
553
|
+
assert "use std::collections::HashMap;" not in view_art.content
|
|
554
|
+
|
|
555
|
+
|
|
391
556
|
def test_emit_rust_struct_has_serde_derives(tmp_path):
|
|
392
557
|
mdl = tmp_path / "test.mdl"
|
|
393
558
|
mdl.write_text(
|
|
@@ -769,6 +934,9 @@ domain customer {
|
|
|
769
934
|
assert "customer_id: src.customer_id.into()," in proj.content
|
|
770
935
|
assert "display_name: src.display_name.into()," in proj.content
|
|
771
936
|
assert "use super::customer_customer_v1::CustomerCustomerV1;" in proj.content
|
|
937
|
+
# Direct-mapped fields keep an unconditional `.into()`, which is a no-op
|
|
938
|
+
# when source and target share a type; silence the resulting clippy lint.
|
|
939
|
+
assert "#[allow(clippy::useless_conversion)]\nimpl From<CustomerCustomerV1>" in proj.content
|
|
772
940
|
# Model struct itself should NOT have a From impl (no projection source)
|
|
773
941
|
model = next(a for a in artifacts if a.ref == "customer.Customer@1")
|
|
774
942
|
assert "impl From<" not in model.content
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|