lapsed 3.0.0__tar.gz → 3.2.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.
- lapsed-3.2.2/.github/workflows/ci.yml +81 -0
- lapsed-3.2.2/.github/workflows/wheels.yml +212 -0
- lapsed-3.2.2/.gitignore +169 -0
- lapsed-3.0.0/CLAUDE.md → lapsed-3.2.2/AGENTS.md +35 -4
- lapsed-3.2.2/CLAUDE.md +1 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/Cargo.lock +322 -255
- {lapsed-3.0.0 → lapsed-3.2.2}/Cargo.toml +9 -5
- {lapsed-3.0.0 → lapsed-3.2.2}/PKG-INFO +1 -1
- {lapsed-3.0.0 → lapsed-3.2.2}/examples/profile_stages.rs +3 -3
- lapsed-3.2.2/legacy-python/.github/dependabot.yml +34 -0
- {lapsed-3.0.0 → lapsed-3.2.2/legacy-python}/.github/workflows/check-deadcode-on-python310.yml +8 -8
- lapsed-3.2.2/legacy-python/.github/workflows/test.yml +53 -0
- lapsed-3.2.2/legacy-python/.github/workflows/vulnerability-audit.yml +73 -0
- {lapsed-3.0.0 → lapsed-3.2.2/legacy-python}/.gitignore +1 -0
- lapsed-3.2.2/legacy-python/.pre-commit-config.yaml +22 -0
- lapsed-3.2.2/legacy-python/.pre-commit-hooks.yaml +10 -0
- lapsed-3.2.2/legacy-python/.readthedocs.yaml +20 -0
- lapsed-3.2.2/legacy-python/LICENSE +661 -0
- lapsed-3.2.2/legacy-python/Makefile +149 -0
- lapsed-3.2.2/legacy-python/README.md +470 -0
- lapsed-3.2.2/legacy-python/codecov.yml +7 -0
- lapsed-3.2.2/legacy-python/deadcode/__init__.py +8 -0
- lapsed-3.2.2/legacy-python/deadcode/actions/find_python_filenames.py +34 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/deadcode/actions/find_unused_names.py +6 -3
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/deadcode/actions/fix_or_show_unused_code.py +14 -13
- lapsed-3.2.2/legacy-python/deadcode/actions/get_unused_import_parts.py +207 -0
- lapsed-3.2.2/legacy-python/deadcode/actions/get_unused_names_error_message.py +41 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/deadcode/actions/merge_overlaping_file_parts.py +8 -9
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/deadcode/actions/parse_abstract_syntax_tree.py +3 -2
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/deadcode/actions/parse_arguments.py +46 -54
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/deadcode/actions/remove_file_parts_from_content.py +33 -11
- lapsed-3.2.2/legacy-python/deadcode/cli.py +67 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/deadcode/constants.py +7 -4
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/deadcode/data_types.py +3 -4
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/deadcode/utils/fix_indent.py +4 -12
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/deadcode/utils/flatten_lists.py +4 -4
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/deadcode/utils/nested_scopes.py +11 -29
- lapsed-3.2.2/legacy-python/deadcode/utils/normalize_path.py +9 -0
- lapsed-3.2.2/legacy-python/deadcode/utils/print_safely.py +29 -0
- lapsed-3.2.2/legacy-python/deadcode/visitor/code_item.py +84 -0
- lapsed-3.2.2/legacy-python/deadcode/visitor/dead_code_visitor.py +952 -0
- lapsed-3.2.2/legacy-python/deadcode/visitor/ignore.py +154 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/deadcode/visitor/lines.py +7 -6
- lapsed-3.2.2/legacy-python/deadcode/visitor/module_exports.py +80 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/deadcode/visitor/noqa.py +3 -4
- lapsed-3.2.2/legacy-python/deadcode/visitor/usage_graph.py +123 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/deadcode/visitor/utils.py +39 -17
- lapsed-3.2.2/legacy-python/docs/_static/AGPLv3-license.svg +23 -0
- lapsed-3.2.2/legacy-python/docs/_static/custom.css +19 -0
- lapsed-3.2.2/legacy-python/docs/_static/deadcode-logo-readme.png +0 -0
- lapsed-3.2.2/legacy-python/docs/comparison.md +93 -0
- lapsed-3.2.2/legacy-python/docs/conf.py +20 -0
- lapsed-3.2.2/legacy-python/docs/contributing.md +18 -0
- lapsed-3.2.2/legacy-python/docs/dep.md +166 -0
- lapsed-3.2.2/legacy-python/docs/dep_1.md +2 -0
- lapsed-3.2.2/legacy-python/docs/dep_2.md +2 -0
- lapsed-3.2.2/legacy-python/docs/dep_3.md +2 -0
- lapsed-3.2.2/legacy-python/docs/dep_4.md +2 -0
- lapsed-3.2.2/legacy-python/docs/dep_5.md +2 -0
- lapsed-3.2.2/legacy-python/docs/dep_6.md +2 -0
- lapsed-3.2.2/legacy-python/docs/dep_7.md +2 -0
- lapsed-3.2.2/legacy-python/docs/django.md +478 -0
- lapsed-3.2.2/legacy-python/docs/fastapi.md +241 -0
- lapsed-3.2.2/legacy-python/docs/features.md +73 -0
- lapsed-3.2.2/legacy-python/docs/index.md +70 -0
- lapsed-3.2.2/legacy-python/docs/installation.md +6 -0
- lapsed-3.2.2/legacy-python/docs/known_limitations.md +6 -0
- lapsed-3.2.2/legacy-python/docs/open_source_experiment.md +269 -0
- lapsed-3.2.2/legacy-python/docs/performance.md +81 -0
- lapsed-3.2.2/legacy-python/docs/pre_commit.md +109 -0
- lapsed-3.2.2/legacy-python/docs/release_notes.md +5 -0
- lapsed-3.2.2/legacy-python/docs/requirements.txt +3 -0
- lapsed-3.2.2/legacy-python/docs/rules.md +8 -0
- lapsed-3.2.2/legacy-python/docs/rust.md +84 -0
- lapsed-3.2.2/legacy-python/docs/security.md +70 -0
- lapsed-3.2.2/legacy-python/docs/usage.md +13 -0
- lapsed-3.2.2/legacy-python/enhancement_proposals/dep_0.md +23 -0
- lapsed-3.2.2/legacy-python/enhancement_proposals/dep_1.md +238 -0
- lapsed-3.2.2/legacy-python/enhancement_proposals/dep_2.md +214 -0
- lapsed-3.2.2/legacy-python/enhancement_proposals/dep_3.md +176 -0
- lapsed-3.2.2/legacy-python/enhancement_proposals/dep_4.md +341 -0
- lapsed-3.2.2/legacy-python/enhancement_proposals/dep_5.md +174 -0
- lapsed-3.2.2/legacy-python/enhancement_proposals/dep_6.md +163 -0
- lapsed-3.2.2/legacy-python/enhancement_proposals/dep_7.md +337 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/pyproject.toml +22 -11
- lapsed-3.2.2/legacy-python/requirements-dev.txt +273 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/requirements.txt +2 -1
- lapsed-3.2.2/legacy-python/tests/actions/test_find_python_filenames.py +165 -0
- lapsed-3.2.2/legacy-python/tests/actions/test_get_unused_import_parts.py +229 -0
- lapsed-3.2.2/legacy-python/tests/actions/test_merge_overlaping_file_parts.py +86 -0
- lapsed-3.2.2/legacy-python/tests/actions/test_remove_file_parts_from_content.py +73 -0
- lapsed-3.2.2/legacy-python/tests/cli/test_cli_exit_status.py +163 -0
- lapsed-3.2.2/legacy-python/tests/cli/test_cli_module_entry_point.py +22 -0
- lapsed-3.2.2/legacy-python/tests/cli/test_cli_output_encoding.py +117 -0
- lapsed-3.2.2/legacy-python/tests/cli/test_deadcode.py +69 -0
- lapsed-3.2.2/legacy-python/tests/cli/test_output.py +138 -0
- lapsed-3.2.2/legacy-python/tests/cli/test_verbose_output_encoding.py +97 -0
- lapsed-3.2.2/legacy-python/tests/cli_args/test_argument_routes.py +117 -0
- lapsed-3.2.2/legacy-python/tests/cli_args/test_count.py +79 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/tests/cli_args/test_dry.py +131 -121
- lapsed-3.2.2/legacy-python/tests/cli_args/test_exclude.py +88 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/tests/cli_args/test_fix.py +291 -208
- lapsed-3.2.2/legacy-python/tests/cli_args/test_ignore_bodies_if_decorated_with.py +112 -0
- lapsed-3.2.2/legacy-python/tests/cli_args/test_ignore_bodies_if_inherits_from.py +158 -0
- lapsed-3.2.2/legacy-python/tests/cli_args/test_ignore_bodies_of.py +141 -0
- lapsed-3.2.2/legacy-python/tests/cli_args/test_ignore_definitions.py +282 -0
- lapsed-3.2.2/legacy-python/tests/cli_args/test_ignore_definitions_if_decorated_with.py +155 -0
- lapsed-3.2.2/legacy-python/tests/cli_args/test_ignore_definitions_if_inherits_from.py +291 -0
- lapsed-3.2.2/legacy-python/tests/cli_args/test_ignore_names.py +90 -0
- lapsed-3.2.2/legacy-python/tests/cli_args/test_ignore_names_if_decorated_with.py +201 -0
- lapsed-3.2.2/legacy-python/tests/cli_args/test_ignore_names_if_inherits_from.py +269 -0
- lapsed-3.2.2/legacy-python/tests/cli_args/test_ignore_names_in_files.py +99 -0
- lapsed-3.2.2/legacy-python/tests/cli_args/test_ignore_option_combinations.py +114 -0
- lapsed-3.2.2/legacy-python/tests/cli_args/test_ignore_rules.py +106 -0
- lapsed-3.2.2/legacy-python/tests/cli_args/test_no_color.py +37 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/tests/cli_args/test_only.py +64 -63
- lapsed-3.2.2/legacy-python/tests/cli_args/test_parsing.py +263 -0
- lapsed-3.2.2/legacy-python/tests/cli_args/test_pyproject_boolean_options.py +116 -0
- lapsed-3.2.2/legacy-python/tests/cli_args/test_pyproject_list_options.py +121 -0
- lapsed-3.2.2/legacy-python/tests/cli_args/test_quiet.py +82 -0
- lapsed-3.2.2/legacy-python/tests/cli_args/test_verbose.py +75 -0
- lapsed-3.2.2/legacy-python/tests/cli_args/test_version.py +34 -0
- lapsed-3.2.2/legacy-python/tests/code_item/test_code_item.py +102 -0
- lapsed-3.2.2/legacy-python/tests/configuration/test_decorator_pyproject_configuration.py +114 -0
- lapsed-3.2.2/legacy-python/tests/conftest.py +108 -0
- lapsed-3.2.2/legacy-python/tests/documented_examples/test_django.py +654 -0
- lapsed-3.2.2/legacy-python/tests/documented_examples/test_documented_features.py +180 -0
- lapsed-3.2.2/legacy-python/tests/documented_examples/test_documented_options.py +82 -0
- lapsed-3.2.2/legacy-python/tests/documented_examples/test_documented_rules.py +91 -0
- lapsed-3.2.2/legacy-python/tests/documented_examples/test_fastapi.py +120 -0
- lapsed-3.2.2/legacy-python/tests/documented_examples/test_fastapi_dependency_injection.py +74 -0
- lapsed-3.2.2/legacy-python/tests/documented_examples/test_fastapi_documentation.py +70 -0
- lapsed-3.2.2/legacy-python/tests/documented_examples/test_pre_commit_hook_configuration.py +66 -0
- lapsed-3.2.2/legacy-python/tests/documented_examples/test_readme_coverage_badge.py +41 -0
- lapsed-3.2.2/legacy-python/tests/files/classes.py +15 -0
- lapsed-3.2.2/legacy-python/tests/files/django/admin.py +20 -0
- lapsed-3.2.2/legacy-python/tests/files/django/api.py +46 -0
- lapsed-3.2.2/legacy-python/tests/files/django/apps.py +9 -0
- lapsed-3.2.2/legacy-python/tests/files/django/forms.py +16 -0
- lapsed-3.2.2/legacy-python/tests/files/django/import_forms.py +34 -0
- lapsed-3.2.2/legacy-python/tests/files/django/management/commands/import_data.py +16 -0
- lapsed-3.2.2/legacy-python/tests/files/django/managers.py +14 -0
- lapsed-3.2.2/legacy-python/tests/files/django/middleware.py +29 -0
- lapsed-3.2.2/legacy-python/tests/files/django/migrations/0001_initial.py +18 -0
- lapsed-3.2.2/legacy-python/tests/files/django/models.py +36 -0
- lapsed-3.2.2/legacy-python/tests/files/django/settings.py +38 -0
- lapsed-3.2.2/legacy-python/tests/files/django/signals.py +20 -0
- lapsed-3.2.2/legacy-python/tests/files/django/templatetags/blog_tags.py +17 -0
- lapsed-3.2.2/legacy-python/tests/files/django/tests.py +27 -0
- lapsed-3.2.2/legacy-python/tests/files/django/urls.py +21 -0
- lapsed-3.2.2/legacy-python/tests/files/django/views.py +54 -0
- lapsed-3.2.2/legacy-python/tests/files/fastapi/dependencies.py +9 -0
- lapsed-3.2.2/legacy-python/tests/files/fastapi/main.py +37 -0
- lapsed-3.2.2/legacy-python/tests/files/fastapi/models.py +10 -0
- lapsed-3.2.2/legacy-python/tests/files/fastapi/routes/users.py +20 -0
- lapsed-3.2.2/legacy-python/tests/files/fastapi_dependency_injection/dependencies.py +49 -0
- lapsed-3.2.2/legacy-python/tests/files/fastapi_dependency_injection/main.py +116 -0
- lapsed-3.2.2/legacy-python/tests/files/fastapi_dependency_injection/models.py +5 -0
- lapsed-3.2.2/legacy-python/tests/files/fastapi_dependency_injection/security.py +26 -0
- lapsed-3.2.2/legacy-python/tests/files/fastapi_features/background.py +2 -0
- lapsed-3.2.2/legacy-python/tests/files/fastapi_features/errors.py +7 -0
- lapsed-3.2.2/legacy-python/tests/files/fastapi_features/main.py +103 -0
- lapsed-3.2.2/legacy-python/tests/files/fastapi_features/middleware.py +11 -0
- lapsed-3.2.2/legacy-python/tests/files/fastapi_features/models.py +36 -0
- lapsed-3.2.2/legacy-python/tests/files/fastapi_features/routes/items.py +66 -0
- lapsed-3.2.2/legacy-python/tests/files/fastapi_features/security.py +21 -0
- lapsed-3.2.2/legacy-python/tests/fix/test_assign.py +487 -0
- lapsed-3.2.2/legacy-python/tests/fix/test_attribute.py +46 -0
- lapsed-3.2.2/legacy-python/tests/fix/test_cascading_dead_code.py +122 -0
- lapsed-3.2.2/legacy-python/tests/fix/test_class_def.py +128 -0
- lapsed-3.2.2/legacy-python/tests/fix/test_commented_out_code.py +68 -0
- lapsed-3.2.2/legacy-python/tests/fix/test_empty_files.py +37 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/tests/fix/test_method_def.py +29 -24
- lapsed-3.2.2/legacy-python/tests/fix/test_property.py +38 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/tests/fix/test_scope.py +130 -80
- lapsed-3.2.2/legacy-python/tests/fix/test_unreachable_code.py +141 -0
- lapsed-3.2.2/legacy-python/tests/fix/test_unused_imports.py +732 -0
- lapsed-3.2.2/legacy-python/tests/nested_scope/test_nested_scope.py +223 -0
- lapsed-3.2.2/legacy-python/tests/noqa/test_noqa_comments.py +638 -0
- lapsed-3.2.2/legacy-python/tests/regression/test_cascading_dead_code.py +415 -0
- lapsed-3.2.2/legacy-python/tests/regression/test_name_shadowing.py +355 -0
- lapsed-3.2.2/legacy-python/tests/regression/test_python314_attribute_error.py +29 -0
- lapsed-3.2.2/legacy-python/tests/utils/test_add_colors_to_diff.py +34 -0
- lapsed-3.2.2/legacy-python/tests/utils/test_fix_indent.py +34 -0
- lapsed-3.2.2/legacy-python/tests/utils/test_normalize_path.py +27 -0
- lapsed-3.2.2/legacy-python/tests/utils/test_print_ast.py +16 -0
- lapsed-3.2.2/legacy-python/tests/utils/test_print_safely.py +145 -0
- lapsed-3.2.2/legacy-python/tests/visitor/test_accurate_usage_detection.py +54 -0
- lapsed-3.2.2/legacy-python/tests/visitor/test_commented_out_code.py +113 -0
- lapsed-3.2.2/legacy-python/tests/visitor/test_decorator_without_id_attribute.py +47 -0
- lapsed-3.2.2/legacy-python/tests/visitor/test_django_lifecycle_methods.py +207 -0
- lapsed-3.2.2/legacy-python/tests/visitor/test_ignore.py +28 -0
- lapsed-3.2.2/legacy-python/tests/visitor/test_ignore_interface_decorators.py +212 -0
- lapsed-3.2.2/legacy-python/tests/visitor/test_imports.py +379 -0
- lapsed-3.2.2/legacy-python/tests/visitor/test_line_number_detection.py +124 -0
- lapsed-3.2.2/legacy-python/tests/visitor/test_middleware_registration.py +122 -0
- lapsed-3.2.2/legacy-python/tests/visitor/test_name_usage_and_unreachable_detection.py +149 -0
- lapsed-3.2.2/legacy-python/tests/visitor/test_qualified_name_resolution.py +151 -0
- lapsed-3.2.2/legacy-python/tests/visitor/test_unittest_lifecycle_methods.py +107 -0
- lapsed-3.2.2/legacy-python/tests/visitor/test_utils.py +72 -0
- {lapsed-3.0.0/legacy-python/tests → lapsed-3.2.2/legacy-python/tests/visitor}/test_variable_parsing_from_ast_dump.py +0 -6
- lapsed-3.2.2/legacy-python/tests/visitor/test_wildcard_imports.py +466 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/pyproject.toml +1 -1
- lapsed-3.2.2/scripts/check.py +214 -0
- lapsed-3.2.2/scripts/parity.py +221 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/src/actions/find_python_filenames.rs +71 -9
- {lapsed-3.0.0 → lapsed-3.2.2}/src/actions/fix_or_show_unused_code.rs +52 -22
- lapsed-3.2.2/src/actions/get_unused_import_parts.rs +342 -0
- lapsed-3.2.2/src/actions/parse_abstract_syntax_tree.rs +103 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/src/actions/parse_arguments.rs +76 -4
- {lapsed-3.0.0 → lapsed-3.2.2}/src/actions/parse_tach_config.rs +89 -7
- lapsed-3.2.2/src/actions/remove_file_parts_from_content.rs +502 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/src/cli.rs +151 -8
- {lapsed-3.0.0 → lapsed-3.2.2}/src/constants.rs +5 -2
- {lapsed-3.0.0 → lapsed-3.2.2}/src/data_types.rs +9 -5
- {lapsed-3.0.0 → lapsed-3.2.2}/src/lib.rs +2 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/src/utils/fix_indent.rs +1 -1
- {lapsed-3.0.0 → lapsed-3.2.2}/src/utils/line_index.rs +5 -5
- lapsed-3.2.2/src/visitor/dead_code_visitor.rs +2194 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/src/visitor/ignore.rs +67 -5
- {lapsed-3.0.0 → lapsed-3.2.2}/src/visitor/utils.rs +7 -14
- lapsed-3.2.2/tests/attrs_field_hooks.rs +90 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/tests/deadcode_integration.rs +8 -3
- {lapsed-3.0.0 → lapsed-3.2.2}/tests/exit_code.rs +50 -0
- lapsed-3.2.2/tests/files/functions.py +21 -0
- lapsed-3.2.2/tests/files/subdir/another_subdir/__init__.py +1 -0
- lapsed-3.2.2/tests/files/subdir/one_more_file.py +2 -0
- lapsed-3.2.2/tests/files/variables.py +8 -0
- lapsed-3.2.2/tests/fix_special_cases.rs +349 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/tests/ignore_flags_cli.rs +1 -1
- {lapsed-3.0.0 → lapsed-3.2.2}/tests/imports_and_output.rs +4 -1
- lapsed-3.2.2/tests/modern_python_syntax.rs +158 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/tests/noqa_comments.rs +12 -0
- lapsed-3.2.2/tests/parity/cases/absimport/main.py +2 -0
- lapsed-3.2.2/tests/parity/cases/absimport/pkg/a.py +4 -0
- lapsed-3.2.2/tests/parity/cases/abstract/m.py +10 -0
- lapsed-3.2.2/tests/parity/cases/cascade/m.py +5 -0
- lapsed-3.2.2/tests/parity/cases/dc06/m.py +6 -0
- lapsed-3.2.2/tests/parity/cases/dc09/m.py +8 -0
- lapsed-3.2.2/tests/parity/cases/dc09b/m.py +15 -0
- lapsed-3.2.2/tests/parity/cases/dc12/m.py +6 -0
- lapsed-3.2.2/tests/parity/cases/dc13/m.py +4 -0
- lapsed-3.2.2/tests/parity/cases/django/m.py +21 -0
- lapsed-3.2.2/tests/parity/cases/django_mw/proj/middleware.py +7 -0
- lapsed-3.2.2/tests/parity/cases/django_mw/proj/settings.py +1 -0
- lapsed-3.2.2/tests/parity/cases/dotted_base/m.py +10 -0
- lapsed-3.2.2/tests/parity/cases/fastapi/m.py +14 -0
- lapsed-3.2.2/tests/parity/cases/fix_edge_cases/m.py +33 -0
- lapsed-3.2.2/tests/parity/cases/imports_fix/m.py +9 -0
- lapsed-3.2.2/tests/parity/cases/multiline_assign/m.py +6 -0
- lapsed-3.2.2/tests/parity/cases/noqa_decorated/m.py +7 -0
- lapsed-3.2.2/tests/parity/cases/pyproject_options/m.py +2 -0
- lapsed-3.2.2/tests/parity/cases/pyproject_options/pyproject.toml +4 -0
- lapsed-3.2.2/tests/parity/cases/quoted/m.py +6 -0
- lapsed-3.2.2/tests/parity/cases/samename/a.py +2 -0
- lapsed-3.2.2/tests/parity/cases/samename/b.py +2 -0
- lapsed-3.2.2/tests/parity/cases/samename/c.py +2 -0
- lapsed-3.2.2/tests/parity/cases/shadowing/m.py +7 -0
- lapsed-3.2.2/tests/parity/cases/typecomment/m.py +4 -0
- lapsed-3.2.2/tests/parity/cases/unicode/m.py +2 -0
- lapsed-3.2.2/tests/parity/cases/wildcard/m.py +6 -0
- lapsed-3.2.2/tests/parity/known_differences.txt +27 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/tests/pytest_and_typing.rs +85 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/tests/scope_tracking.rs +36 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/tests/tach_config_cli.rs +153 -0
- lapsed-3.2.2/tests/version_consistency.rs +94 -0
- lapsed-3.0.0/.github/workflows/wheels.yml +0 -113
- lapsed-3.0.0/RUST_PORT_PLAN.md +0 -284
- lapsed-3.0.0/example.txt +0 -6
- lapsed-3.0.0/legacy-python/Makefile +0 -53
- lapsed-3.0.0/legacy-python/deadcode/__init__.py +0 -10
- lapsed-3.0.0/legacy-python/deadcode/actions/find_python_filenames.py +0 -64
- lapsed-3.0.0/legacy-python/deadcode/actions/get_unused_names_error_message.py +0 -37
- lapsed-3.0.0/legacy-python/deadcode/actions/parse_tach_config.py +0 -257
- lapsed-3.0.0/legacy-python/deadcode/cli.py +0 -57
- lapsed-3.0.0/legacy-python/deadcode/todo +0 -163
- lapsed-3.0.0/legacy-python/deadcode/utils/base_test_case.py +0 -88
- lapsed-3.0.0/legacy-python/deadcode/visitor/code_item.py +0 -142
- lapsed-3.0.0/legacy-python/deadcode/visitor/dead_code_visitor.py +0 -594
- lapsed-3.0.0/legacy-python/deadcode/visitor/ignore.py +0 -176
- lapsed-3.0.0/legacy-python/requirements-dev.txt +0 -185
- lapsed-3.0.0/legacy-python/tests/actions/test_find_python_filenames.py +0 -36
- lapsed-3.0.0/legacy-python/tests/actions/test_merge_overlaping_file_parts.py +0 -62
- lapsed-3.0.0/legacy-python/tests/cli_args/test_exclude.py +0 -24
- lapsed-3.0.0/legacy-python/tests/cli_args/test_ignore_bodies_if_inherits_from.py +0 -46
- lapsed-3.0.0/legacy-python/tests/cli_args/test_ignore_class_attributes.py +0 -74
- lapsed-3.0.0/legacy-python/tests/cli_args/test_ignore_definitions.py +0 -106
- lapsed-3.0.0/legacy-python/tests/cli_args/test_ignore_definitions_if_inherits_from.py +0 -125
- lapsed-3.0.0/legacy-python/tests/cli_args/test_ignore_names.py +0 -79
- lapsed-3.0.0/legacy-python/tests/cli_args/test_ignore_non_self_attributes.py +0 -52
- lapsed-3.0.0/legacy-python/tests/cli_args/test_parsing.py +0 -117
- lapsed-3.0.0/legacy-python/tests/cli_args/test_quiet.py +0 -0
- lapsed-3.0.0/legacy-python/tests/cli_args/test_tach_config.py +0 -366
- lapsed-3.0.0/legacy-python/tests/cli_args/test_verbose.py +0 -0
- lapsed-3.0.0/legacy-python/tests/cli_args/test_version.py +0 -41
- lapsed-3.0.0/legacy-python/tests/code_item/test_code_item.py +0 -16
- lapsed-3.0.0/legacy-python/tests/fix/test_assign.py +0 -92
- lapsed-3.0.0/legacy-python/tests/fix/test_class_def.py +0 -117
- lapsed-3.0.0/legacy-python/tests/fix/test_empty_files.py +0 -36
- lapsed-3.0.0/legacy-python/tests/fix/test_unreachable_code.py +0 -100
- lapsed-3.0.0/legacy-python/tests/fix/test_unused_imports.py +0 -59
- lapsed-3.0.0/legacy-python/tests/nested_scope/test_nested_scope.py +0 -180
- lapsed-3.0.0/legacy-python/tests/noqa/test_noqa_comments.py +0 -400
- lapsed-3.0.0/legacy-python/tests/tach/test_parse_tach_config.py +0 -260
- lapsed-3.0.0/legacy-python/tests/test_accurate_usage_detection.py +0 -49
- lapsed-3.0.0/legacy-python/tests/test_deadcode.py +0 -68
- lapsed-3.0.0/legacy-python/tests/test_exit_code.py +0 -82
- lapsed-3.0.0/legacy-python/tests/test_imports.py +0 -101
- lapsed-3.0.0/legacy-python/tests/test_line_number_detection.py +0 -97
- lapsed-3.0.0/legacy-python/tests/test_output.py +0 -137
- lapsed-3.0.0/legacy-python/tests/test_pytest_fixtures.py +0 -172
- lapsed-3.0.0/legacy-python/tests/test_pytest_hooks.py +0 -47
- lapsed-3.0.0/legacy-python/tests/test_typing_override.py +0 -75
- lapsed-3.0.0/legacy-python/tests/utils/test_add_colors_to_diff.py +0 -38
- lapsed-3.0.0/legacy-python/tests/utils/test_fix_indent.py +0 -10
- lapsed-3.0.0/legacy-python/tests/visitor/test_utils.py +0 -35
- lapsed-3.0.0/profiling_comparison.md +0 -74
- lapsed-3.0.0/profiling_report.md +0 -339
- lapsed-3.0.0/profiling_report_after.md +0 -329
- lapsed-3.0.0/profiling_report_round2.md +0 -159
- lapsed-3.0.0/profiling_round2_raw.txt +0 -267
- lapsed-3.0.0/profiling_rust_vs_python.md +0 -111
- lapsed-3.0.0/src/actions/remove_file_parts_from_content.rs +0 -206
- lapsed-3.0.0/src/visitor/dead_code_visitor.rs +0 -1432
- lapsed-3.0.0/tests/fix_special_cases.rs +0 -109
- {lapsed-3.0.0 → lapsed-3.2.2}/.pre-commit-hooks.yaml +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/LICENSE +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/README.md +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/docs/_static/AGPLv3-license.svg +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/docs/_static/deadcode-logo-readme.png +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/enhancement_proposals/dep_0.md +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/enhancement_proposals/dep_1.md +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/enhancement_proposals/dep_2.md +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/enhancement_proposals/dep_3.md +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/deadcode/actions/__init__.py +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/deadcode/utils/__init__.py +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/deadcode/utils/add_colors_to_diff.py +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/deadcode/utils/print_ast.py +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/deadcode/visitor/__init__.py +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/legacy-python/tests/cli_args/__init__.py +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2/legacy-python}/tests/files/functions.py +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2/legacy-python}/tests/files/subdir/another_subdir/__init__.py +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2/legacy-python}/tests/files/subdir/one_more_file.py +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2/legacy-python}/tests/files/variables.py +0 -0
- {lapsed-3.0.0/legacy-python/tests/tach → lapsed-3.2.2/legacy-python/tests/fix}/__init__.py +0 -0
- {lapsed-3.0.0/legacy-python/tests/utils → lapsed-3.2.2/legacy-python/tests/regression}/__init__.py +0 -0
- /lapsed-3.0.0/legacy-python/tests/cli_args/test_count.py → /lapsed-3.2.2/legacy-python/tests/utils/__init__.py +0 -0
- /lapsed-3.0.0/legacy-python/tests/cli_args/test_ignore_names_in_files.py → /lapsed-3.2.2/legacy-python/tests/visitor/__init__.py +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/src/actions/get_unused_names_error_message.rs +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/src/actions/merge_overlapping_file_parts.rs +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/src/main.rs +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/src/utils/add_colors_to_diff.rs +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/src/utils/fnmatch.rs +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/src/utils/nested_scopes.rs +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/src/utils/path_utils.rs +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/src/visitor/code_item.rs +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/src/visitor/noqa.rs +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/tests/aspirational_unimplemented.rs +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/tests/common/mod.rs +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/tests/files/classes.py +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/tests/fix_cli_option.rs +0 -0
- {lapsed-3.0.0 → lapsed-3.2.2}/tests/line_number_detection.rs +0 -0
- /lapsed-3.0.0/legacy-python/tests/cli_args/test_no_color.py → /lapsed-3.2.2/tests/parity/cases/absimport/pkg/__init__.py +0 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
# Runs on every pull request regardless of base branch, and on v* tags.
|
|
4
|
+
#
|
|
5
|
+
# Deliberately NOT restricted to `branches: [main]` the way the older workflows
|
|
6
|
+
# are: this project develops through staging/test_release/feature branches, and
|
|
7
|
+
# a base-branch filter means a PR into anything but main gets no CI at all.
|
|
8
|
+
on:
|
|
9
|
+
pull_request:
|
|
10
|
+
push:
|
|
11
|
+
tags: ["v*"]
|
|
12
|
+
# Manual runs, useful for checking a branch before opening the PR.
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
|
|
18
|
+
# A newer push to the same PR supersedes the old run; tag builds are never
|
|
19
|
+
# cancelled, since those gate a release.
|
|
20
|
+
concurrency:
|
|
21
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
22
|
+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
# Version-independent checks: the Rust toolchain, the Python linters (which
|
|
26
|
+
# analyse source rather than run it), and parity, which runs the Rust CLI and
|
|
27
|
+
# legacy-python side by side (see scripts/parity.py).
|
|
28
|
+
static:
|
|
29
|
+
name: ${{ matrix.check }}
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
strategy:
|
|
32
|
+
# Report every failing check in one run, rather than hiding the rest
|
|
33
|
+
# behind whichever fails first.
|
|
34
|
+
fail-fast: false
|
|
35
|
+
matrix:
|
|
36
|
+
check: [fmt, clippy, test, ruff, ruff-format, mypy, parity]
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@v4
|
|
39
|
+
|
|
40
|
+
- name: Install Rust
|
|
41
|
+
uses: dtolnay/rust-toolchain@stable
|
|
42
|
+
with:
|
|
43
|
+
# Only the checks that need them, so the Python jobs stay lean.
|
|
44
|
+
components: ${{ (matrix.check == 'fmt' && 'rustfmt') || (matrix.check == 'clippy' && 'clippy') || '' }}
|
|
45
|
+
|
|
46
|
+
- name: Cache cargo
|
|
47
|
+
uses: Swatinem/rust-cache@v2
|
|
48
|
+
with:
|
|
49
|
+
key: ${{ matrix.check }}
|
|
50
|
+
|
|
51
|
+
- name: Install uv
|
|
52
|
+
uses: astral-sh/setup-uv@v5
|
|
53
|
+
with:
|
|
54
|
+
enable-cache: true
|
|
55
|
+
|
|
56
|
+
# The exact command a developer runs locally.
|
|
57
|
+
- run: python scripts/check.py ${{ matrix.check }}
|
|
58
|
+
|
|
59
|
+
# The legacy Python suite, once per supported interpreter.
|
|
60
|
+
#
|
|
61
|
+
# Keep this list in sync with PYTHON_VERSIONS in scripts/check.py and the
|
|
62
|
+
# classifiers in legacy-python/pyproject.toml. 3.14 matters most here: it
|
|
63
|
+
# removed ast.Str/Num/Bytes/NameConstant/Ellipsis, which the visitor used.
|
|
64
|
+
pytest:
|
|
65
|
+
name: pytest (Python ${{ matrix.python }})
|
|
66
|
+
runs-on: ubuntu-latest
|
|
67
|
+
strategy:
|
|
68
|
+
fail-fast: false
|
|
69
|
+
matrix:
|
|
70
|
+
python: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/checkout@v4
|
|
73
|
+
|
|
74
|
+
- name: Install uv
|
|
75
|
+
uses: astral-sh/setup-uv@v5
|
|
76
|
+
with:
|
|
77
|
+
enable-cache: true
|
|
78
|
+
|
|
79
|
+
# uv fetches the interpreter itself, so no setup-python step is needed
|
|
80
|
+
# and the matrix cannot drift from what the runner image happens to ship.
|
|
81
|
+
- run: python scripts/check.py pytest --python ${{ matrix.python }}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
name: Build Rust wheels
|
|
2
|
+
|
|
3
|
+
# Wheels are the release artifact, so v* tags must build them -- previously
|
|
4
|
+
# tags triggered nothing at all. `pull_request` is unfiltered for the same
|
|
5
|
+
# reason as in ci.yml: a base-branch filter means PRs into staging or
|
|
6
|
+
# test_release get no wheel build.
|
|
7
|
+
on:
|
|
8
|
+
pull_request:
|
|
9
|
+
push:
|
|
10
|
+
branches: [ "main" ]
|
|
11
|
+
tags: [ "v*" ]
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
test:
|
|
19
|
+
name: cargo test (${{ matrix.os }})
|
|
20
|
+
runs-on: ${{ matrix.os }}
|
|
21
|
+
strategy:
|
|
22
|
+
fail-fast: false
|
|
23
|
+
matrix:
|
|
24
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v4
|
|
27
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
28
|
+
- run: cargo test --all-features
|
|
29
|
+
|
|
30
|
+
linux:
|
|
31
|
+
name: wheel (linux ${{ matrix.target }})
|
|
32
|
+
needs: test
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
strategy:
|
|
35
|
+
fail-fast: false
|
|
36
|
+
matrix:
|
|
37
|
+
target: [x86_64, aarch64]
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/checkout@v4
|
|
40
|
+
- name: Build manylinux wheel
|
|
41
|
+
uses: PyO3/maturin-action@v1
|
|
42
|
+
with:
|
|
43
|
+
target: ${{ matrix.target }}
|
|
44
|
+
args: --release --out dist
|
|
45
|
+
manylinux: auto
|
|
46
|
+
- uses: actions/upload-artifact@v4
|
|
47
|
+
with:
|
|
48
|
+
name: wheels-linux-${{ matrix.target }}
|
|
49
|
+
path: dist/*.whl
|
|
50
|
+
|
|
51
|
+
windows:
|
|
52
|
+
name: wheel (windows ${{ matrix.target }})
|
|
53
|
+
needs: test
|
|
54
|
+
runs-on: windows-latest
|
|
55
|
+
strategy:
|
|
56
|
+
fail-fast: false
|
|
57
|
+
matrix:
|
|
58
|
+
target: [x64, x86]
|
|
59
|
+
steps:
|
|
60
|
+
- uses: actions/checkout@v4
|
|
61
|
+
- uses: actions/setup-python@v5
|
|
62
|
+
with:
|
|
63
|
+
python-version: "3.12"
|
|
64
|
+
architecture: ${{ matrix.target }}
|
|
65
|
+
- name: Build wheel
|
|
66
|
+
uses: PyO3/maturin-action@v1
|
|
67
|
+
with:
|
|
68
|
+
target: ${{ matrix.target == 'x64' && 'x86_64-pc-windows-msvc' || 'i686-pc-windows-msvc' }}
|
|
69
|
+
args: --release --out dist
|
|
70
|
+
- uses: actions/upload-artifact@v4
|
|
71
|
+
with:
|
|
72
|
+
name: wheels-windows-${{ matrix.target }}
|
|
73
|
+
path: dist/*.whl
|
|
74
|
+
|
|
75
|
+
macos:
|
|
76
|
+
name: wheel (macos ${{ matrix.target }})
|
|
77
|
+
needs: test
|
|
78
|
+
runs-on: macos-latest
|
|
79
|
+
strategy:
|
|
80
|
+
fail-fast: false
|
|
81
|
+
matrix:
|
|
82
|
+
target: [x86_64, aarch64]
|
|
83
|
+
steps:
|
|
84
|
+
- uses: actions/checkout@v4
|
|
85
|
+
- name: Build wheel
|
|
86
|
+
uses: PyO3/maturin-action@v1
|
|
87
|
+
with:
|
|
88
|
+
target: ${{ matrix.target }}
|
|
89
|
+
args: --release --out dist
|
|
90
|
+
- uses: actions/upload-artifact@v4
|
|
91
|
+
with:
|
|
92
|
+
name: wheels-macos-${{ matrix.target }}
|
|
93
|
+
path: dist/*.whl
|
|
94
|
+
|
|
95
|
+
sdist:
|
|
96
|
+
name: source distribution
|
|
97
|
+
needs: test
|
|
98
|
+
runs-on: ubuntu-latest
|
|
99
|
+
steps:
|
|
100
|
+
- uses: actions/checkout@v4
|
|
101
|
+
- uses: PyO3/maturin-action@v1
|
|
102
|
+
with:
|
|
103
|
+
command: sdist
|
|
104
|
+
args: --out dist
|
|
105
|
+
- uses: actions/upload-artifact@v4
|
|
106
|
+
with:
|
|
107
|
+
name: sdist
|
|
108
|
+
path: dist/*.tar.gz
|
|
109
|
+
|
|
110
|
+
# Every wheel installs and runs on its target platform.
|
|
111
|
+
smoke-test:
|
|
112
|
+
name: install & smoke test (${{ matrix.os }})
|
|
113
|
+
needs: [linux, windows, macos]
|
|
114
|
+
runs-on: ${{ matrix.os }}
|
|
115
|
+
strategy:
|
|
116
|
+
fail-fast: false
|
|
117
|
+
# Runner and artifact are paired explicitly rather than derived from the
|
|
118
|
+
# OS name. A wheel only installs on a matching architecture, and the
|
|
119
|
+
# previous nested-ternary form hardcoded macos-x86_64 -- which broke once
|
|
120
|
+
# `macos-latest` became Apple Silicon (macos-26-arm64), since the x86_64
|
|
121
|
+
# wheel is not installable there. Pairing them here means adding a
|
|
122
|
+
# platform is one obvious edit instead of an easily-missed branch.
|
|
123
|
+
#
|
|
124
|
+
# Not every built wheel has a runner to test on: linux-aarch64,
|
|
125
|
+
# windows-x86, and (as of GitHub retiring free Intel macOS hosting
|
|
126
|
+
# entirely -- every x64 macOS label is now a paid large-runner, e.g.
|
|
127
|
+
# macos-15-intel/macos-14-large -- macos-x86_64) are shipped untested.
|
|
128
|
+
# macos-13 used to cover the x86_64 wheel, but that label has no runner
|
|
129
|
+
# left to schedule it on: the job just queues forever and gets
|
|
130
|
+
# auto-cancelled by GitHub after 24h, which is what happened here.
|
|
131
|
+
matrix:
|
|
132
|
+
include:
|
|
133
|
+
- os: ubuntu-latest
|
|
134
|
+
artifact: wheels-linux-x86_64
|
|
135
|
+
- os: windows-latest
|
|
136
|
+
artifact: wheels-windows-x64
|
|
137
|
+
# macos-latest tracks whatever Apple Silicon image GitHub currently
|
|
138
|
+
# calls "latest", so it catches drift early.
|
|
139
|
+
- os: macos-latest
|
|
140
|
+
artifact: wheels-macos-aarch64
|
|
141
|
+
# macos-15 is a hard-pinned Apple Silicon version (not a moving
|
|
142
|
+
# "-latest" symlink), so this job stays reproducible even if/when
|
|
143
|
+
# "latest" moves again.
|
|
144
|
+
- os: macos-15
|
|
145
|
+
artifact: wheels-macos-aarch64
|
|
146
|
+
steps:
|
|
147
|
+
- uses: actions/checkout@v4
|
|
148
|
+
- uses: actions/setup-python@v5
|
|
149
|
+
with:
|
|
150
|
+
python-version: "3.12"
|
|
151
|
+
- name: Download this OS's wheel
|
|
152
|
+
uses: actions/download-artifact@v4
|
|
153
|
+
with:
|
|
154
|
+
pattern: ${{ matrix.artifact }}
|
|
155
|
+
path: dist
|
|
156
|
+
merge-multiple: true
|
|
157
|
+
# Fail loudly if the download produced nothing, rather than letting the
|
|
158
|
+
# install step report a confusing "no matching distribution".
|
|
159
|
+
- name: Verify a wheel was downloaded
|
|
160
|
+
shell: bash
|
|
161
|
+
run: |
|
|
162
|
+
ls -l dist
|
|
163
|
+
if [ "$(ls dist/*.whl 2>/dev/null | wc -l)" -eq 0 ]; then
|
|
164
|
+
echo "::error::no .whl in dist for ${{ matrix.artifact }}"
|
|
165
|
+
exit 1
|
|
166
|
+
fi
|
|
167
|
+
# The distribution is `lapsed`; the command it installs is `deadcode`.
|
|
168
|
+
# `--no-index` matters: this previously asked for `deadcode`, which does
|
|
169
|
+
# not match the built `lapsed-*.whl`, so pip fell through to PyPI and
|
|
170
|
+
# smoke-tested an unrelated package instead of this build. Forbidding the
|
|
171
|
+
# index makes that failure loud rather than silent.
|
|
172
|
+
- run: pip install --no-index --find-links dist lapsed
|
|
173
|
+
- run: deadcode --version
|
|
174
|
+
|
|
175
|
+
# Pushing a `v*` tag publishes to PyPI once every wheel built and smoke-tested.
|
|
176
|
+
# Uses PyPI trusted publishing (OIDC), so there is no token in the repository:
|
|
177
|
+
# register this workflow as a trusted publisher for `lapsed` on PyPI
|
|
178
|
+
# (owner ColinKennedy, repo deadcode, workflow wheels.yml, environment pypi).
|
|
179
|
+
publish:
|
|
180
|
+
name: publish to PyPI
|
|
181
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
182
|
+
needs: [sdist, smoke-test]
|
|
183
|
+
runs-on: ubuntu-latest
|
|
184
|
+
environment:
|
|
185
|
+
name: pypi
|
|
186
|
+
url: https://pypi.org/project/lapsed/
|
|
187
|
+
permissions:
|
|
188
|
+
id-token: write
|
|
189
|
+
steps:
|
|
190
|
+
- uses: actions/checkout@v4
|
|
191
|
+
- uses: actions/download-artifact@v4
|
|
192
|
+
with:
|
|
193
|
+
path: dist
|
|
194
|
+
merge-multiple: true
|
|
195
|
+
# A tag that disagrees with Cargo.toml would upload the wrong version.
|
|
196
|
+
- name: Check the tag matches the package version
|
|
197
|
+
shell: bash
|
|
198
|
+
run: |
|
|
199
|
+
expected="${GITHUB_REF_NAME#v}"
|
|
200
|
+
actual="$(grep -m1 '^version = ' Cargo.toml | cut -d'"' -f2)"
|
|
201
|
+
if [ "$expected" != "$actual" ]; then
|
|
202
|
+
echo "::error::tag $GITHUB_REF_NAME does not match Cargo.toml version $actual"
|
|
203
|
+
exit 1
|
|
204
|
+
fi
|
|
205
|
+
ls -l dist
|
|
206
|
+
if ls dist | grep -v -E "^lapsed-$expected[-.]" ; then
|
|
207
|
+
echo "::error::dist holds files that are not version $expected"
|
|
208
|
+
exit 1
|
|
209
|
+
fi
|
|
210
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
211
|
+
with:
|
|
212
|
+
packages-dir: dist
|
lapsed-3.2.2/.gitignore
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py,cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# poetry
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
102
|
+
#poetry.lock
|
|
103
|
+
|
|
104
|
+
# pdm
|
|
105
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
106
|
+
#pdm.lock
|
|
107
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
108
|
+
# in version control.
|
|
109
|
+
# https://pdm.fming.dev/#use-with-ide
|
|
110
|
+
.pdm.toml
|
|
111
|
+
|
|
112
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
113
|
+
__pypackages__/
|
|
114
|
+
|
|
115
|
+
# Celery stuff
|
|
116
|
+
celerybeat-schedule
|
|
117
|
+
celerybeat.pid
|
|
118
|
+
|
|
119
|
+
# SageMath parsed files
|
|
120
|
+
*.sage.py
|
|
121
|
+
|
|
122
|
+
# Environments
|
|
123
|
+
.env
|
|
124
|
+
.venv
|
|
125
|
+
env/
|
|
126
|
+
venv/
|
|
127
|
+
ENV/
|
|
128
|
+
env.bak/
|
|
129
|
+
venv.bak/
|
|
130
|
+
|
|
131
|
+
# Spyder project settings
|
|
132
|
+
.spyderproject
|
|
133
|
+
.spyproject
|
|
134
|
+
|
|
135
|
+
# Rope project settings
|
|
136
|
+
.ropeproject
|
|
137
|
+
|
|
138
|
+
# mkdocs documentation
|
|
139
|
+
/site
|
|
140
|
+
|
|
141
|
+
# mypy
|
|
142
|
+
.mypy_cache/
|
|
143
|
+
.dmypy.json
|
|
144
|
+
dmypy.json
|
|
145
|
+
|
|
146
|
+
# ruff
|
|
147
|
+
.ruff_cache/
|
|
148
|
+
|
|
149
|
+
# Pyre type checker
|
|
150
|
+
.pyre/
|
|
151
|
+
|
|
152
|
+
# pytype static type analyzer
|
|
153
|
+
.pytype/
|
|
154
|
+
|
|
155
|
+
# Cython debug symbols
|
|
156
|
+
cython_debug/
|
|
157
|
+
|
|
158
|
+
# PyCharm
|
|
159
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
160
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
161
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
162
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
163
|
+
#.idea/
|
|
164
|
+
|
|
165
|
+
notes
|
|
166
|
+
|
|
167
|
+
# uv lockfile for the archived Python package; generated on demand by the
|
|
168
|
+
# check runner, not a source of truth for anything shipped.
|
|
169
|
+
legacy-python/uv.lock
|
|
@@ -10,7 +10,8 @@ As of the `refactor_to_rust` branch, the implementation is **Rust**, not Python
|
|
|
10
10
|
|
|
11
11
|
- **Language:** Rust (edition 2021), packaged for PyPI via `maturin` with `bindings = "bin"` — the wheel ships a compiled native binary + console-script shim, no PyO3/Python bindings.
|
|
12
12
|
- **Entry point:** `src/main.rs` → `deadcode::cli::print_main()`
|
|
13
|
-
- **AST parsing:** `rustpython-parser
|
|
13
|
+
- **AST parsing:** `ruff_python_parser`/`ruff_python_ast` (Astral's parser, published on crates.io). This replaced `rustpython-parser`, whose newest release (0.4.0) tops out around Python 3.11 and could not parse 3.12+ source — see `src/actions/parse_abstract_syntax_tree.rs` for the specifics and `RUST_PORT_PLAN.md` for why the original choice was reversed.
|
|
14
|
+
- **Minimum Rust:** 1.95 (required by the ruff crates).
|
|
14
15
|
- **Config:** `pyproject.toml` at repo root now configures the `maturin` build, not tool behavior (there is no `[tool.deadcode]` section for the Rust CLI itself yet — config merging support could be re-added if needed, but the CLI flags are the primary interface).
|
|
15
16
|
|
|
16
17
|
## Development Setup
|
|
@@ -31,7 +32,7 @@ pip install target/wheels/deadcode-*.whl
|
|
|
31
32
|
|
|
32
33
|
## Architecture
|
|
33
34
|
|
|
34
|
-
Mirrors the original Python pipeline, module-for-module, with two structural differences: AST traversal is a hand-written exhaustive `match` over `
|
|
35
|
+
Mirrors the original Python pipeline, module-for-module, with two structural differences: AST traversal is a hand-written exhaustive `match` over `ruff_python_ast`'s `Stmt`/`Expr` enums (no dynamic dispatch, no Python-style `ast.iter_fields` reflection), and `NestedScope` only tracks classes (confirmed behavior-preserving by tracing what actually reads it — see `src/utils/nested_scopes.rs`'s doc comment).
|
|
35
36
|
|
|
36
37
|
1. **`src/actions/parse_arguments.rs`** — Parses CLI args (`clap`) and merges `pyproject.toml`'s `[tool.deadcode]` (if present) — mirrors `flatten_lists_of_comma_separated_values` + `parse_pyproject_toml`.
|
|
37
38
|
2. **`src/actions/find_python_filenames.rs`** — Discovers `.py` files, applying `--exclude`/`--only` filters and tach.toml source-root rules.
|
|
@@ -46,12 +47,40 @@ Mirrors the original Python pipeline, module-for-module, with two structural dif
|
|
|
46
47
|
| `src/constants.rs` | `UnusedCodeType` enum, DC01–DC13 error codes (DC10 deliberately absent) |
|
|
47
48
|
| `src/data_types.rs` | `Args` struct (doubles as the `clap` CLI definition), `Part` |
|
|
48
49
|
| `src/visitor/code_item.rs` | `CodeItem` — a single unused-code finding |
|
|
49
|
-
| `src/
|
|
50
|
+
| `src/actions/parse_abstract_syntax_tree.rs` | The only place source is parsed; pins the parser's `target_version` to the newest Python grammar |
|
|
51
|
+
| `src/utils/line_index.rs` | Byte-offset → (line, column) conversion (the parser gives byte ranges, not line/col directly) |
|
|
50
52
|
| `src/utils/nested_scopes.rs` | Class inherits-from chain tracking |
|
|
51
53
|
| `src/utils/fnmatch.rs` | Rust port of Python's `fnmatch` glob semantics |
|
|
52
|
-
| `src/actions/
|
|
54
|
+
| `src/actions/get_unused_import_parts.rs` | Statement-aware removal parts for unused imports (commas, `;` separators, emptied statements) — port of upstream's `get_unused_import_parts.py` |
|
|
55
|
+
| `src/actions/remove_file_parts_from_content.rs` | Byte-level code removal for `--fix` — preserves the Python original's quirks except where they produce invalid Python (see its module doc comment) |
|
|
53
56
|
| `src/actions/parse_tach_config.rs` | tach.toml support (source_roots, interfaces/expose, unchecked modules, tach.domain.toml merging) |
|
|
54
57
|
|
|
58
|
+
### Where ruff's AST differs from CPython's `ast`
|
|
59
|
+
|
|
60
|
+
The visitor is a port of Python code and is written to match CPython's `ast`
|
|
61
|
+
semantics exactly. `ruff_python_ast` is not a 1:1 mirror of `ast`, so a few
|
|
62
|
+
places translate deliberately. Each is commented at its site; the ones worth
|
|
63
|
+
knowing before editing the visitor:
|
|
64
|
+
|
|
65
|
+
- **A decorated `def`/`class` node's range starts at its first decorator**, where
|
|
66
|
+
CPython points at the `def`/`class` keyword. `push_definition` corrects for this
|
|
67
|
+
via `definition_keyword_start`. Getting this wrong reports decorated definitions
|
|
68
|
+
on the decorator's line and silently breaks `# noqa` lookup (the comment sits on
|
|
69
|
+
the `def` line).
|
|
70
|
+
- **Merged node kinds:** `async def`/`def`, `async for`/`for`, `async with`/`with`
|
|
71
|
+
are one node with an `is_async` flag; `try`/`except*` is one node with `is_star`.
|
|
72
|
+
- **Split literals:** CPython's single `ast.Constant` is one variant per literal
|
|
73
|
+
kind (`StringLiteral`, `NumberLiteral`, …).
|
|
74
|
+
- **Restructured nodes:** `if`/`elif`/`else` is flattened into `elif_else_clauses`
|
|
75
|
+
rather than nested in `orelse`; `Dict` pairs keys and values in one `items` list;
|
|
76
|
+
`MatchClass` merges `kwd_attrs`/`kwd_patterns` into one `keywords` list.
|
|
77
|
+
- **f-strings/t-strings are not plain expression trees.** They are lists of parts
|
|
78
|
+
(to support PEP 701 and implicit concatenation), so interpolations must be walked
|
|
79
|
+
explicitly via `walk_interpolated_element` — this is what makes a name used only
|
|
80
|
+
inside `f"{x}"` count as a usage.
|
|
81
|
+
- **`ExprContext` has a fourth `Invalid` variant** with no CPython equivalent, used
|
|
82
|
+
for error-recovery nodes. Ignored.
|
|
83
|
+
|
|
55
84
|
### Deliberately NOT ported (confirmed dead/inert in the Python original)
|
|
56
85
|
|
|
57
86
|
- `unreachable_code`/DC09 detection: computed in the Python code but explicitly excluded from `get_unused_code_items()`'s output and untested — zero observable effect, so it isn't implemented here at all.
|
|
@@ -65,6 +94,8 @@ DC01 unused-variable, DC02 unused-function, DC03 unused-class, DC04 unused-metho
|
|
|
65
94
|
|
|
66
95
|
Unit tests live inline in `src/**` (`#[cfg(test)] mod tests`); integration tests live in `tests/*.rs`, using real temp directories (no filesystem mocking — this port always does real I/O) via the shared harness in `tests/common/mod.rs`. `tests/files/*.py` are real fixture files (not copies) whose exact line numbers are asserted against — do not reformat them without checking `tests/deadcode_integration.rs`.
|
|
67
96
|
|
|
97
|
+
**Parity with upstream:** `python scripts/check.py parity` runs the Rust CLI and `legacy-python/` side by side on `tests/parity/cases/*` and every legacy fixture, comparing findings, exit codes and `--dry` diffs, and checks that Rust `--fix` never leaves an unparseable file. Known differences are listed with reasons in `tests/parity/known_differences.txt`; the check fails on a new difference *and* on a listed one that disappeared, so delete the line when you fix one. `python scripts/parity.py --show <case>` prints a case's differences.
|
|
98
|
+
|
|
68
99
|
**Run a single test:**
|
|
69
100
|
```bash
|
|
70
101
|
cargo test --test fix_cli_option
|
lapsed-3.2.2/CLAUDE.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|