pyvbaanalysis 1.4.2__tar.gz → 2.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/CHANGELOG.md +86 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/PKG-INFO +19 -11
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/README.md +16 -8
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/docs/api-reference.md +6 -3
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/docs/usage.md +43 -10
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyproject.toml +1 -1
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/__init__.py +13 -2
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/cli.py +6 -4
- pyvbaanalysis-2.0.0/pyvbaanalysis/data/access_host_model.json +1 -0
- pyvbaanalysis-2.0.0/pyvbaanalysis/data/powerpoint_host_model.json +1 -0
- pyvbaanalysis-2.0.0/pyvbaanalysis/data/word_host_model.json +1 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/analyze_module.py +39 -10
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/context.py +5 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/registry.py +14 -4
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/duplicates.py +4 -2
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/late_binding.py +5 -3
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/undeclared.py +8 -5
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/host/__init__.py +17 -1
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/host/host_model.py +72 -29
- pyvbaanalysis-2.0.0/pyvbaanalysis/host/host_registry.py +115 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/project.py +10 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/reader/__init__.py +14 -1
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/reader/vbe_module.py +27 -7
- pyvbaanalysis-2.0.0/pyvbaanalysis/reader/workbook.py +230 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_cli.py +1 -1
- pyvbaanalysis-2.0.0/tests/test_host_seam.py +469 -0
- pyvbaanalysis-2.0.0/tools/extract_host_model.mjs +31 -0
- pyvbaanalysis-1.4.2/pyvbaanalysis/reader/workbook.py +0 -106
- pyvbaanalysis-1.4.2/tools/extract_host_model.mjs +0 -12
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/.gitattributes +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/.github/dependabot.yml +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/.github/workflows/ci.yml +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/.github/workflows/publish.yml +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/.gitignore +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/CONTRIBUTING.md +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/LICENSE +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/docs/diagnostics-catalogue.md +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/__main__.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/call/__init__.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/call/call_context.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/completion/__init__.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/completion/cursor_context.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/completion/event_handlers.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/completion/member_access.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/completion/type_completion.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/conditional/__init__.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/conditional/conditional_compilation.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/constants/__init__.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/constants/integer_constant_expression.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/data/diagnostic_influence_audit.json +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/data/event_definitions.json +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/data/excel_host_model.json +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/data/manifest.json +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/data/rule_metadata.json +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/data/vba_runtime_tables.json +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/data/vbe_oracle_cases.json +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/__init__.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/argument_inference.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/call_extraction.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/callable_signatures.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/const_expr.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/dataflow.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/exprwalk.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/inline_suppression.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/model.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rule_metadata.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/__init__.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/argument_shape.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/argument_types.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/arrays.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/assignments.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/binary_operand_scalar.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/call_arity.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/control_flow.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/declarations.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/expressions.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/lexical.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/module_kind.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/numeric_literals.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/object_state.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/parameter_defaults.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/runtime_values.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/shared.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/rules/type_of_is.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/diagnostics/walker.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/evidence.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/flow/__init__.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/flow/procedure_labels.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/flow/procedure_unstructured.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/identity_cache.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/lexer/__init__.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/lexer/keyword_table.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/lexer/stripped_lines.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/lexer/token_helpers.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/lexer/token_kinds.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/lexer/tokenize.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/lexer/trivia.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/parser/__init__.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/parser/fixed_length_string.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/parser/nodes.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/parser/parse_expression.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/parser/parse_module.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/parser/parser_state.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/parser/type_declaration_suffix.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/py.typed +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/reader/loose_file.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/runtime/__init__.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/runtime/vba_runtime.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/symbols/__init__.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/symbols/build_module_symbols.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/symbols/name_resolution.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/symbols/project_index.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/symbols/symbol_model.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/types/__init__.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/types/type_inference.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/pyvbaanalysis/types/type_names.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/conftest.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/oracle_support.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_conditional_compilation.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_dataflow.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_diagnostics_engine.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_evidence.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_host_model.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_inline_suppression.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_integer_constant_expression.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_language_matrix.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_lexer.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_member_access_chains.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_parser.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_project.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_project_index.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_public_api.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_reader.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_real_world_false_positives.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_registry_parity.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rule_metadata.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_ambiguous_enum_member.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_argument_shape.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_argument_types.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_arrays.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_assignments.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_assignments_types.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_binary_operand_scalar.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_call_arity.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_control_flow.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_declarations.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_division_by_zero.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_duplicates.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_event_handler_module_scope.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_expression_calls.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_expressions.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_invalid_as_type_names.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_is_operator_non_object.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_late_binding.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_lexical.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_member_not_found.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_module_kind.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_numeric_literals.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_object_state.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_parameter_defaults.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_property_setter_value_parameters.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_runtime_values.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_scalar_and_foreach.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_type_of_is.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_typeof_is_always_false.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_rules_undeclared.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_runtime_tables.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_statement_token_derivation.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_stripped_lines.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_symbols.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_token_helpers.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_type_completion.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tests/test_type_names.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tools/extract_event_definitions.mjs +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tools/extract_rule_metadata.mjs +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tools/extract_runtime_tables.mjs +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tools/generate_diagnostics_catalogue.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tools/generate_manifest.py +0 -0
- {pyvbaanalysis-1.4.2 → pyvbaanalysis-2.0.0}/tools/oracle/build_combining_mark_probe.py +0 -0
|
@@ -5,6 +5,92 @@ All notable changes to pyVBAanalysis are recorded here. The format follows
|
|
|
5
5
|
follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html): a minor version
|
|
6
6
|
per milestone.
|
|
7
7
|
|
|
8
|
+
## 2.0.0 - 2026-08-19
|
|
9
|
+
|
|
10
|
+
Multi-host analysis: VBA is now measured against the object model of the Office
|
|
11
|
+
host it actually belongs to. Ports the XLIDE host-model seam and the Word,
|
|
12
|
+
PowerPoint and Access models (xlide_vscode 790e6ea and e56098b, its issues #24
|
|
13
|
+
and #25).
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
* A host seam on the analysis entry points. `analyze_project` and
|
|
18
|
+
`analyze_module_options_for` take a `host` token (`"excel"`, `"word"`,
|
|
19
|
+
`"powerpoint"`, `"access"`, ...), and `AnalyzeModuleOptions` carries `host`
|
|
20
|
+
alongside the existing `host_model`. The semantics are deliberately
|
|
21
|
+
asymmetric: absent means Excel, so every existing caller is unchanged, while a
|
|
22
|
+
NAMED host with no model asserts no host knowledge rather than falling back to
|
|
23
|
+
Excel's. An explicit `host_model` still outranks the token.
|
|
24
|
+
* Word, PowerPoint and Access object models, vendored as
|
|
25
|
+
`data/{word,powerpoint,access}_host_model.json` and extracted mechanically by
|
|
26
|
+
`tools/extract_host_model.mjs` from the generated XLIDE host modules, the same
|
|
27
|
+
pipeline that has always produced the Excel model. 364, 201 and 188
|
|
28
|
+
member-bearing types; 3,742, 1,480 and 1,116 enum constants. Every type is
|
|
29
|
+
non-exhaustive by construction, so absence never becomes a finding.
|
|
30
|
+
* `analyze_office_file(path)` and `read_office_modules(path)` read any container
|
|
31
|
+
pyOpenVBA opens: Excel (`.xlsm`, `.xlsb`, `.xlam`, `.xls`), Word (`.docm`,
|
|
32
|
+
`.dotm`, `.doc`), PowerPoint (`.pptm`, `.potm`) and Access (`.accdb`, `.mdb`,
|
|
33
|
+
read-only). The extension selects the host, so a Word document is analyzed
|
|
34
|
+
against Word's model without the caller saying anything. The CLI accepts them
|
|
35
|
+
all on the same footing.
|
|
36
|
+
* `host_token_for_file_name` and `host_object_model_for_token` on the public API.
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
|
|
40
|
+
* Word VBA no longer false-positives against Excel's object model. Analyzing a
|
|
41
|
+
Word module as a project previously reported four findings on legal code:
|
|
42
|
+
`ActiveDocument` twice and `wdOrientPortrait` as undeclared variables, and
|
|
43
|
+
`Selection.TypeText` as `member-not-found` against `Excel.Range`. Under the
|
|
44
|
+
Word host it reports none.
|
|
45
|
+
* Host metadata is per-model throughout, closing the Excel defaults that
|
|
46
|
+
remained under the seam. Application-member injection is keyed by model
|
|
47
|
+
(`Volatile` is a known bare call under Excel and unknown under Word), and the
|
|
48
|
+
four rules that consulted host metadata with a bare Excel default now take the
|
|
49
|
+
caller's model: undeclared variables, unknown call, ambiguous enum references,
|
|
50
|
+
and late-bound Friend members. `Me` types host-correctly in a document module:
|
|
51
|
+
`ThisWorkbook` is `Excel.Workbook` under Excel, `ThisDocument` is
|
|
52
|
+
`Word.Document` under Word, and nothing is asserted anywhere else.
|
|
53
|
+
* Word's `ThisDocument` classifies as a document module. It declares
|
|
54
|
+
`VB_Base = "1Normal.ThisDocument"`, naming no CLSID, so GUID matching missed
|
|
55
|
+
it; the host-generic signature is the `VB_PredeclaredId` + `VB_Exposed` pair
|
|
56
|
+
that Office gives every document module. A `.bas` extension or the container's
|
|
57
|
+
own standard-module flag still outranks that signature, since either states
|
|
58
|
+
outright that the module is standard. Differentialled across 116 modules in 16
|
|
59
|
+
real workbooks: nothing reclassified.
|
|
60
|
+
* A named host with no object model no longer reports what it cannot know. An
|
|
61
|
+
empty model is not uniformly quieter than Excel's: member lookups go silent
|
|
62
|
+
because no type resolves, but the rules that ask whether a bare name is legal
|
|
63
|
+
would answer no for every global the host injects, turning an Outlook
|
|
64
|
+
project's own surface into a wall of `undeclared-variable` findings. The four
|
|
65
|
+
rules that need host knowledge now stay silent under an unmodelled host, for
|
|
66
|
+
the same reason they already do on a partial project view.
|
|
67
|
+
* The host-model memos no longer key on a bare `id(model)`. Three caches
|
|
68
|
+
(`_host_model_index`, `_host_constant_index`, and the host-member name set)
|
|
69
|
+
used a plain `dict[int, ...]` that kept no reference to the model, so entries
|
|
70
|
+
accumulated one per model object ever seen and a collected model's id could be
|
|
71
|
+
recycled by a later one, serving one model's index for another. They now use
|
|
72
|
+
the repo's `IdentityLru`, which holds its keys alive and stays bounded. Latent
|
|
73
|
+
before this release, since only the permanently-live Excel singleton was ever
|
|
74
|
+
passed; reachable now that callers choose models.
|
|
75
|
+
|
|
76
|
+
### Changed
|
|
77
|
+
|
|
78
|
+
* `analyze_workbook` and `read_workbook_modules` keep their Excel-only contract
|
|
79
|
+
unchanged. Handed a container the generic reader could open, they now name
|
|
80
|
+
`analyze_office_file` in the error rather than only rejecting the extension.
|
|
81
|
+
* README, the usage guide, the API reference and agent.md describe the four
|
|
82
|
+
hosts; agent.md's pyOpenVBA floor was stale at 3.0.1 and now reads 3.4.0.
|
|
83
|
+
|
|
84
|
+
### Known limits
|
|
85
|
+
|
|
86
|
+
* Legacy `.ppt` is not readable. pyOpenVBA 3.4.0 lists it but reads it as a
|
|
87
|
+
plain CFB, while the VBA project lives in a zlib-compressed CFB inside an
|
|
88
|
+
`ExOleObjStg` record, so every open fails on the missing `dir` stream. The
|
|
89
|
+
extension is rejected up front rather than failing later with a parse error
|
|
90
|
+
that reads like file corruption. Reported as pyOpenVBA issue #17.
|
|
91
|
+
* Access is read-only, following pyOpenVBA: Access executes compiled p-code, so
|
|
92
|
+
a source write would silently change nothing.
|
|
93
|
+
|
|
8
94
|
## 1.4.2 - 2026-08-03
|
|
9
95
|
|
|
10
96
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: pyvbaanalysis
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: Pure-Python static analysis for Excel VBA
|
|
5
5
|
Project-URL: Homepage, https://github.com/WilliamSmithEdward/pyVBAanalysis
|
|
6
6
|
Project-URL: Repository, https://github.com/WilliamSmithEdward/pyVBAanalysis
|
|
@@ -24,16 +24,18 @@ Requires-Dist: twine>=5; extra == 'build'
|
|
|
24
24
|
Provides-Extra: dev
|
|
25
25
|
Requires-Dist: mypy==2.3.0; extra == 'dev'
|
|
26
26
|
Requires-Dist: pytest==9.1.1; extra == 'dev'
|
|
27
|
-
Requires-Dist: ruff==0.16.
|
|
27
|
+
Requires-Dist: ruff==0.16.2; extra == 'dev'
|
|
28
28
|
Description-Content-Type: text/markdown
|
|
29
29
|
|
|
30
30
|
# pyVBAanalysis
|
|
31
31
|
|
|
32
|
-
Static analysis for
|
|
33
|
-
errors the VBA compiler would catch, without opening
|
|
32
|
+
Static analysis for Office VBA. It reads your macros and reports likely bugs and the
|
|
33
|
+
errors the VBA compiler would catch, without opening Office or running any code.
|
|
34
34
|
|
|
35
|
-
Point it at
|
|
36
|
-
|
|
35
|
+
Point it at an Excel workbook, a Word document, a PowerPoint deck, an Access
|
|
36
|
+
database, or a set of exported module files, and it returns the problems it finds,
|
|
37
|
+
each with the exact line and a plain explanation. Each file is measured against its
|
|
38
|
+
own host's object model, so Word code is never judged by Excel's surface.
|
|
37
39
|
|
|
38
40
|
## What it checks
|
|
39
41
|
|
|
@@ -63,9 +65,9 @@ Python 3.10 or later. Nothing else to set up.
|
|
|
63
65
|
Analyze a workbook:
|
|
64
66
|
|
|
65
67
|
```python
|
|
66
|
-
from pyvbaanalysis import
|
|
68
|
+
from pyvbaanalysis import analyze_office_file
|
|
67
69
|
|
|
68
|
-
for module, problems in
|
|
70
|
+
for module, problems in analyze_office_file("Budget.xlsm").items():
|
|
69
71
|
for p in problems:
|
|
70
72
|
print(module, p.severity.value, p.code, p.message)
|
|
71
73
|
```
|
|
@@ -105,8 +107,14 @@ clean, so it drops into a CI check.
|
|
|
105
107
|
|
|
106
108
|
## Scope
|
|
107
109
|
|
|
108
|
-
This analyzes
|
|
109
|
-
|
|
110
|
+
This analyzes the VBA inside Office files. It does not run macros and does not need
|
|
111
|
+
Office installed.
|
|
112
|
+
|
|
113
|
+
Each file is measured against its own host's object model, so a Word document is
|
|
114
|
+
never judged by Excel's surface. Readable containers: Excel (.xlsm, .xlsb, .xlam,
|
|
115
|
+
.xls), Word (.docm, .dotm, .doc), PowerPoint (.pptm, .potm) and Access (.accdb,
|
|
116
|
+
.mdb, read-only). Legacy .ppt is not readable yet, because its VBA project sits in
|
|
117
|
+
a compressed record the reader does not open.
|
|
110
118
|
|
|
111
119
|
## Documentation
|
|
112
120
|
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# pyVBAanalysis
|
|
2
2
|
|
|
3
|
-
Static analysis for
|
|
4
|
-
errors the VBA compiler would catch, without opening
|
|
3
|
+
Static analysis for Office VBA. It reads your macros and reports likely bugs and the
|
|
4
|
+
errors the VBA compiler would catch, without opening Office or running any code.
|
|
5
5
|
|
|
6
|
-
Point it at
|
|
7
|
-
|
|
6
|
+
Point it at an Excel workbook, a Word document, a PowerPoint deck, an Access
|
|
7
|
+
database, or a set of exported module files, and it returns the problems it finds,
|
|
8
|
+
each with the exact line and a plain explanation. Each file is measured against its
|
|
9
|
+
own host's object model, so Word code is never judged by Excel's surface.
|
|
8
10
|
|
|
9
11
|
## What it checks
|
|
10
12
|
|
|
@@ -34,9 +36,9 @@ Python 3.10 or later. Nothing else to set up.
|
|
|
34
36
|
Analyze a workbook:
|
|
35
37
|
|
|
36
38
|
```python
|
|
37
|
-
from pyvbaanalysis import
|
|
39
|
+
from pyvbaanalysis import analyze_office_file
|
|
38
40
|
|
|
39
|
-
for module, problems in
|
|
41
|
+
for module, problems in analyze_office_file("Budget.xlsm").items():
|
|
40
42
|
for p in problems:
|
|
41
43
|
print(module, p.severity.value, p.code, p.message)
|
|
42
44
|
```
|
|
@@ -76,8 +78,14 @@ clean, so it drops into a CI check.
|
|
|
76
78
|
|
|
77
79
|
## Scope
|
|
78
80
|
|
|
79
|
-
This analyzes
|
|
80
|
-
|
|
81
|
+
This analyzes the VBA inside Office files. It does not run macros and does not need
|
|
82
|
+
Office installed.
|
|
83
|
+
|
|
84
|
+
Each file is measured against its own host's object model, so a Word document is
|
|
85
|
+
never judged by Excel's surface. Readable containers: Excel (.xlsm, .xlsb, .xlam,
|
|
86
|
+
.xls), Word (.docm, .dotm, .doc), PowerPoint (.pptm, .potm) and Access (.accdb,
|
|
87
|
+
.mdb, read-only). Legacy .ppt is not readable yet, because its VBA project sits in
|
|
88
|
+
a compressed record the reader does not open.
|
|
81
89
|
|
|
82
90
|
## Documentation
|
|
83
91
|
|
|
@@ -11,11 +11,14 @@ These are re-exported at the package root for convenience:
|
|
|
11
11
|
| Symbol | Role |
|
|
12
12
|
| --- | --- |
|
|
13
13
|
| `analyze_module(source, opts=None)` | Analyze one module's source; returns `list[VbaDiagnostic]`. Never raises. |
|
|
14
|
-
| `analyze_project(modules, *, only=None, severity_overrides=None, conditional_compilation=None, whole_project=True, inline_suppression=True)` | Analyze a set of `ModuleInput`s with cross-module context; returns `dict[str, list[VbaDiagnostic]]`. `whole_project=False` for a partial set. |
|
|
14
|
+
| `analyze_project(modules, *, only=None, severity_overrides=None, conditional_compilation=None, whole_project=True, inline_suppression=True, host=None)` | Analyze a set of `ModuleInput`s with cross-module context; returns `dict[str, list[VbaDiagnostic]]`. `whole_project=False` for a partial set. `host` names the Office host (absent means Excel). |
|
|
15
15
|
| `analyze_loose_file(path, *, severity_overrides=None, conditional_compilation=None, whole_project=False, inline_suppression=True)` | Analyze one `.bas`/`.cls`/`.frm` file (partial by default; the whole-project checks are skipped). |
|
|
16
16
|
| `analyze_loose_files(paths, *, only=None, severity_overrides=None, conditional_compilation=None, whole_project=True, inline_suppression=True)` | Analyze several loose files as one project. |
|
|
17
17
|
| `analyze_workbook(path, *, only=None, severity_overrides=None, conditional_compilation=None, inline_suppression=True)` | Analyze the VBA in an Excel workbook (via pyOpenVBA). |
|
|
18
|
-
| `
|
|
18
|
+
| `analyze_office_file(path, *, only=None, severity_overrides=None, conditional_compilation=None, inline_suppression=True)` | The same for any readable Office container (Excel, Word, PowerPoint, Access); the extension selects the host model. |
|
|
19
|
+
| `host_token_for_file_name(name)` | The host a container implies (`excel`, `word`, `powerpoint`, `access`), or `None`. |
|
|
20
|
+
| `host_object_model_for_token(host)` | The model a host token selects: `None` for Excel (the default), the host's own model, or the empty model when a named host has none. |
|
|
21
|
+
| `analyze_module_options_for(index, name, kind, *, severity_overrides=None, conditional_compilation=None, whole_project=True, inline_suppression=True, host=None)` | Build per-module `AnalyzeModuleOptions` from a populated `ProjectIndex`. |
|
|
19
22
|
| `build_project_index(modules)` | A `ProjectIndex` with every module registered. |
|
|
20
23
|
| `AnalyzeModuleOptions` | Inputs for `analyze_module` (name, kind, project context, overrides). |
|
|
21
24
|
| `VbaDiagnostic` | A single diagnostic (`code`, `message`, `severity`, `span`, `spec_reference`). |
|
|
@@ -69,7 +72,7 @@ them directly, but they are public and stable.
|
|
|
69
72
|
| `pyvbaanalysis.conditional` | Conditional-compilation indexing and activity (`index_conditional_compilation`, `evaluate_conditional_expression`, ...). |
|
|
70
73
|
| `pyvbaanalysis.types` | Type-name helpers: `normalize_type`, `is_known_scalar_type`, `is_numeric_type`, `numeric_literal_bounds`. |
|
|
71
74
|
| `pyvbaanalysis.completion` | Member-completion surface and project-type resolution (`resolve_member_surface_at`, `resolve_type_name`, ...). |
|
|
72
|
-
| `pyvbaanalysis.host` | The Excel host object
|
|
75
|
+
| `pyvbaanalysis.host` | The Excel, Word, PowerPoint and Access host object models and the host registry (`get_excel_object_model`, `host_object_model_for_token`, `resolve_host_alias`, ...). |
|
|
73
76
|
| `pyvbaanalysis.runtime` | VBA runtime functions, constants, and objects (`resolve_runtime_function`, ...). |
|
|
74
77
|
| `pyvbaanalysis.call` | Call-statement shape helpers. |
|
|
75
78
|
| `pyvbaanalysis.flow` | Procedure labels and unstructured-flow detection. |
|
|
@@ -136,21 +136,53 @@ analyze_loose_files(["Module1.bas", "Widget.cls"]) # several, as one project
|
|
|
136
136
|
skipped for it (see "Whole project vs a single file" below). Use `analyze_loose_files`
|
|
137
137
|
to analyze several files together with shared cross-module context.
|
|
138
138
|
|
|
139
|
-
###
|
|
139
|
+
### Office macro containers
|
|
140
140
|
|
|
141
|
-
The
|
|
141
|
+
The container reader reads VBA directly out of an Office file via pyOpenVBA (the one
|
|
142
142
|
runtime dependency). pyOpenVBA is imported lazily, so `import pyvbaanalysis` stays
|
|
143
|
-
light.
|
|
143
|
+
light.
|
|
144
|
+
|
|
145
|
+
| Host | Extensions |
|
|
146
|
+
| --- | --- |
|
|
147
|
+
| Excel | `.xlsm`, `.xlsb`, `.xlam`, `.xls` |
|
|
148
|
+
| Word | `.docm`, `.dotm`, `.doc` |
|
|
149
|
+
| PowerPoint | `.pptm`, `.potm` |
|
|
150
|
+
| Access | `.accdb`, `.mdb` (read-only) |
|
|
144
151
|
|
|
145
152
|
```python
|
|
146
|
-
from pyvbaanalysis import
|
|
153
|
+
from pyvbaanalysis import analyze_office_file
|
|
147
154
|
|
|
148
|
-
|
|
149
|
-
|
|
155
|
+
analyze_office_file("Book.xlsm") # dict: module name -> diagnostics
|
|
156
|
+
analyze_office_file("Report.docm") # resolved against Word's model
|
|
157
|
+
analyze_office_file("Book.xlsm", only=["Sheet1"]) # one module by name, full context
|
|
150
158
|
```
|
|
151
159
|
|
|
152
|
-
|
|
153
|
-
|
|
160
|
+
The extension selects the host, so Word code is measured against Word's object model
|
|
161
|
+
and never against Excel's. Analyzing a Word module under Excel's model reports
|
|
162
|
+
members and constants that are perfectly legal in Word (`Selection.TypeText`,
|
|
163
|
+
`ActiveDocument`, `wdOrientPortrait`), which is the false positive this avoids.
|
|
164
|
+
|
|
165
|
+
`analyze_workbook` remains the Excel-only entry point and is unchanged.
|
|
166
|
+
|
|
167
|
+
A path that is not a readable container, or a container with no readable VBA, raises
|
|
168
|
+
`WorkbookReadError`. Legacy `.ppt` is not readable: pyOpenVBA reads it as a plain
|
|
169
|
+
CFB, but its VBA project sits inside a compressed record, so the extension is
|
|
170
|
+
rejected rather than failing later with a parse error
|
|
171
|
+
([pyOpenVBA #17](https://github.com/WilliamSmithEdward/pyOpenVBA/issues/17)).
|
|
172
|
+
|
|
173
|
+
### Choosing the host yourself
|
|
174
|
+
|
|
175
|
+
When you already have the module text, name the host directly. Absent means Excel,
|
|
176
|
+
so existing calls are unchanged; a named host with no model asserts no host
|
|
177
|
+
knowledge at all rather than falling back to Excel's.
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
from pyvbaanalysis import analyze_project
|
|
181
|
+
|
|
182
|
+
analyze_project(modules, host="word") # Word's object model
|
|
183
|
+
analyze_project(modules, host="outlook") # no model yet: stays quiet, never Excel's
|
|
184
|
+
analyze_project(modules) # Excel, exactly as before
|
|
185
|
+
```
|
|
154
186
|
|
|
155
187
|
The reader loads the workbook and its VBA into memory and does not bound the input
|
|
156
188
|
size, so impose your own limit (for example a maximum file size) before pointing it
|
|
@@ -227,8 +259,9 @@ pyvbaanalysis Book.xlsm --format json
|
|
|
227
259
|
```
|
|
228
260
|
|
|
229
261
|
A path may be a loose file, a folder of loose files (analyzed together as one
|
|
230
|
-
project), or an
|
|
231
|
-
`
|
|
262
|
+
project), or an Office macro container, whose extension selects the host model.
|
|
263
|
+
`pyvbaanalysis --version` prints the version, and `python -m pyvbaanalysis` is
|
|
264
|
+
equivalent to the `pyvbaanalysis` command.
|
|
232
265
|
|
|
233
266
|
Flags:
|
|
234
267
|
|
|
@@ -38,7 +38,7 @@ dependencies = ["pyOpenVBA>=3.4.0"]
|
|
|
38
38
|
# underneath main (ruff 0.16 broke a green tree with zero repo commits).
|
|
39
39
|
# Dependabot's weekly pip updates turn each tool upgrade into its own gated
|
|
40
40
|
# PR, where a red CI run blocks the bump instead of breaking main.
|
|
41
|
-
dev = ["pytest==9.1.1", "ruff==0.16.
|
|
41
|
+
dev = ["pytest==9.1.1", "ruff==0.16.2", "mypy==2.3.0"]
|
|
42
42
|
build = ["build>=1.2", "twine>=5"]
|
|
43
43
|
|
|
44
44
|
[project.scripts]
|
|
@@ -9,6 +9,8 @@ The headline entry points are re-exported here for convenience:
|
|
|
9
9
|
* analyze_project(modules): analyze a set of modules with cross-module context.
|
|
10
10
|
* analyze_workbook(path): analyze the VBA in an Excel workbook (read via pyOpenVBA,
|
|
11
11
|
the one external runtime dependency).
|
|
12
|
+
* analyze_office_file(path): the same for any Office macro container (Excel, Word,
|
|
13
|
+
PowerPoint, or read-only Access), resolving against that host's object model.
|
|
12
14
|
* analyze_loose_file(path) / analyze_loose_files(paths): analyze loose
|
|
13
15
|
.bas / .cls / .frm export files.
|
|
14
16
|
|
|
@@ -30,10 +32,16 @@ from .diagnostics import (
|
|
|
30
32
|
validate_severity_overrides,
|
|
31
33
|
)
|
|
32
34
|
from .project import analyze_module_options_for, analyze_project, build_project_index
|
|
33
|
-
from .
|
|
35
|
+
from .host import host_object_model_for_token, host_token_for_file_name
|
|
36
|
+
from .reader import (
|
|
37
|
+
analyze_loose_file,
|
|
38
|
+
analyze_loose_files,
|
|
39
|
+
analyze_office_file,
|
|
40
|
+
analyze_workbook,
|
|
41
|
+
)
|
|
34
42
|
from .symbols import ModuleInput, ModuleSymbolKind, ProjectIndex, ProjectIndexOptions
|
|
35
43
|
|
|
36
|
-
__version__ = "
|
|
44
|
+
__version__ = "2.0.0"
|
|
37
45
|
|
|
38
46
|
__all__ = [
|
|
39
47
|
"AnalyzeModuleOptions",
|
|
@@ -50,9 +58,12 @@ __all__ = [
|
|
|
50
58
|
"analyze_loose_files",
|
|
51
59
|
"analyze_module",
|
|
52
60
|
"analyze_module_options_for",
|
|
61
|
+
"analyze_office_file",
|
|
53
62
|
"analyze_project",
|
|
54
63
|
"analyze_workbook",
|
|
55
64
|
"build_project_index",
|
|
65
|
+
"host_object_model_for_token",
|
|
66
|
+
"host_token_for_file_name",
|
|
56
67
|
"line_col",
|
|
57
68
|
"rule_metadata_by_code",
|
|
58
69
|
"validate_severity_overrides",
|
|
@@ -30,13 +30,14 @@ from .diagnostics import (
|
|
|
30
30
|
validate_severity_overrides,
|
|
31
31
|
)
|
|
32
32
|
from .project import analyze_project
|
|
33
|
+
from .host import host_token_for_file_name
|
|
33
34
|
from .reader import (
|
|
34
|
-
EXCEL_EXTENSIONS,
|
|
35
35
|
LOOSE_EXTENSIONS,
|
|
36
|
+
OFFICE_EXTENSIONS,
|
|
36
37
|
LooseFileReadError,
|
|
37
38
|
WorkbookReadError,
|
|
38
39
|
load_loose_module,
|
|
39
|
-
|
|
40
|
+
read_office_modules,
|
|
40
41
|
)
|
|
41
42
|
from .symbols import ModuleInput
|
|
42
43
|
|
|
@@ -151,7 +152,7 @@ def _analyze_workbook_group(
|
|
|
151
152
|
errors: list[str] = []
|
|
152
153
|
for path in paths:
|
|
153
154
|
try:
|
|
154
|
-
modules =
|
|
155
|
+
modules = read_office_modules(path)
|
|
155
156
|
except WorkbookReadError as exc:
|
|
156
157
|
errors.append(f"{path}: {exc}")
|
|
157
158
|
continue
|
|
@@ -163,6 +164,7 @@ def _analyze_workbook_group(
|
|
|
163
164
|
only=only or None,
|
|
164
165
|
severity_overrides=severity_overrides or None,
|
|
165
166
|
inline_suppression=inline_suppression,
|
|
167
|
+
host=host_token_for_file_name(path.name),
|
|
166
168
|
)
|
|
167
169
|
sources = {m.name: m.source for m in modules}
|
|
168
170
|
results.append(_ProjectResult(str(path), diagnostics, sources))
|
|
@@ -332,7 +334,7 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
332
334
|
print("error: unknown diagnostic code(s): " + ", ".join(unknown_codes), file=sys.stderr)
|
|
333
335
|
return 2
|
|
334
336
|
|
|
335
|
-
workbook_paths = [p for p in paths if p.is_file() and p.suffix.lower() in
|
|
337
|
+
workbook_paths = [p for p in paths if p.is_file() and p.suffix.lower() in OFFICE_EXTENSIONS]
|
|
336
338
|
other_paths = [p for p in paths if p not in workbook_paths]
|
|
337
339
|
loose_paths = _gather_loose_paths(other_paths)
|
|
338
340
|
unknown = [p for p in loose_paths if p.suffix.lower() not in LOOSE_EXTENSIONS]
|