deadcode 2.3.0__tar.gz → 2.3.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.
- {deadcode-2.3.0 → deadcode-2.3.1}/PKG-INFO +26 -9
- {deadcode-2.3.0 → deadcode-2.3.1}/README.md +13 -4
- {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/actions/find_python_filenames.py +6 -6
- {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/actions/fix_or_show_unused_code.py +16 -14
- {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/actions/get_unused_names_error_message.py +6 -6
- {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/actions/merge_overlaping_file_parts.py +2 -7
- {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/actions/parse_abstract_syntax_tree.py +1 -1
- deadcode-2.3.1/deadcode/actions/parse_arguments.py +229 -0
- {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/actions/remove_file_parts_from_content.py +36 -19
- {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/cli.py +3 -3
- deadcode-2.3.1/deadcode/constants.py +49 -0
- {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/data_types.py +1 -1
- deadcode-2.3.1/deadcode/utils/add_colors_to_diff.py +10 -0
- deadcode-2.3.0/deadcode/tests/base.py → deadcode-2.3.1/deadcode/utils/base_test_case.py +18 -18
- deadcode-2.3.1/deadcode/utils/fix_indent.py +69 -0
- {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/utils/flatten_lists.py +2 -2
- {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/utils/nested_scopes.py +2 -2
- deadcode-2.3.1/deadcode/utils/print_ast.py +5 -0
- {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/visitor/code_item.py +15 -28
- {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/visitor/dead_code_visitor.py +62 -65
- {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/visitor/ignore.py +29 -29
- {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/visitor/lines.py +3 -3
- {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/visitor/noqa.py +33 -33
- {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/visitor/utils.py +1 -1
- deadcode-2.3.1/pyproject.toml +208 -0
- deadcode-2.3.0/black/action/main.py +0 -176
- deadcode-2.3.0/black/docs/conf.py +0 -218
- deadcode-2.3.0/black/gallery/gallery.py +0 -294
- deadcode-2.3.0/black/profiling/dict_big.py +0 -8001
- deadcode-2.3.0/black/profiling/dict_huge.py +0 -41440
- deadcode-2.3.0/black/profiling/list_big.py +0 -4000
- deadcode-2.3.0/black/profiling/list_huge.py +0 -22431
- deadcode-2.3.0/black/profiling/mix_big.py +0 -1002
- deadcode-2.3.0/black/profiling/mix_huge.py +0 -7692
- deadcode-2.3.0/black/profiling/mix_small.py +0 -102
- deadcode-2.3.0/black/scripts/check_pre_commit_rev_in_example.py +0 -54
- deadcode-2.3.0/black/scripts/check_version_in_basics_example.py +0 -48
- deadcode-2.3.0/black/scripts/diff_shades_gha_helper.py +0 -236
- deadcode-2.3.0/black/scripts/fuzz.py +0 -92
- deadcode-2.3.0/black/scripts/generate_schema.py +0 -74
- deadcode-2.3.0/black/scripts/make_width_table.py +0 -66
- deadcode-2.3.0/black/scripts/migrate-black.py +0 -96
- deadcode-2.3.0/black/scripts/release.py +0 -245
- deadcode-2.3.0/black/scripts/release_tests.py +0 -69
- deadcode-2.3.0/black/src/black/__init__.py +0 -1605
- deadcode-2.3.0/black/src/black/__main__.py +0 -3
- deadcode-2.3.0/black/src/black/_width_table.py +0 -478
- deadcode-2.3.0/black/src/black/brackets.py +0 -382
- deadcode-2.3.0/black/src/black/cache.py +0 -150
- deadcode-2.3.0/black/src/black/comments.py +0 -415
- deadcode-2.3.0/black/src/black/concurrency.py +0 -190
- deadcode-2.3.0/black/src/black/const.py +0 -4
- deadcode-2.3.0/black/src/black/debug.py +0 -54
- deadcode-2.3.0/black/src/black/files.py +0 -433
- deadcode-2.3.0/black/src/black/handle_ipynb_magics.py +0 -452
- deadcode-2.3.0/black/src/black/linegen.py +0 -1745
- deadcode-2.3.0/black/src/black/lines.py +0 -1073
- deadcode-2.3.0/black/src/black/mode.py +0 -265
- deadcode-2.3.0/black/src/black/nodes.py +0 -1007
- deadcode-2.3.0/black/src/black/numerics.py +0 -61
- deadcode-2.3.0/black/src/black/output.py +0 -122
- deadcode-2.3.0/black/src/black/parsing.py +0 -244
- deadcode-2.3.0/black/src/black/ranges.py +0 -521
- deadcode-2.3.0/black/src/black/report.py +0 -107
- deadcode-2.3.0/black/src/black/rusty.py +0 -28
- deadcode-2.3.0/black/src/black/schema.py +0 -20
- deadcode-2.3.0/black/src/black/strings.py +0 -325
- deadcode-2.3.0/black/src/black/trans.py +0 -2534
- deadcode-2.3.0/black/src/blackd/__init__.py +0 -259
- deadcode-2.3.0/black/src/blackd/__main__.py +0 -3
- deadcode-2.3.0/black/src/blackd/middlewares.py +0 -45
- deadcode-2.3.0/black/src/blib2to3/__init__.py +0 -1
- deadcode-2.3.0/black/src/blib2to3/pgen2/__init__.py +0 -4
- deadcode-2.3.0/black/src/blib2to3/pgen2/conv.py +0 -256
- deadcode-2.3.0/black/src/blib2to3/pgen2/driver.py +0 -316
- deadcode-2.3.0/black/src/blib2to3/pgen2/grammar.py +0 -227
- deadcode-2.3.0/black/src/blib2to3/pgen2/literals.py +0 -66
- deadcode-2.3.0/black/src/blib2to3/pgen2/parse.py +0 -411
- deadcode-2.3.0/black/src/blib2to3/pgen2/pgen.py +0 -428
- deadcode-2.3.0/black/src/blib2to3/pgen2/token.py +0 -88
- deadcode-2.3.0/black/src/blib2to3/pgen2/tokenize.py +0 -698
- deadcode-2.3.0/black/src/blib2to3/pygram.py +0 -200
- deadcode-2.3.0/black/src/blib2to3/pytree.py +0 -986
- deadcode-2.3.0/black/tests/conftest.py +0 -28
- deadcode-2.3.0/black/tests/data/cases/allow_empty_first_line.py +0 -166
- deadcode-2.3.0/black/tests/data/cases/async_stmts.py +0 -27
- deadcode-2.3.0/black/tests/data/cases/attribute_access_on_number_literals.py +0 -47
- deadcode-2.3.0/black/tests/data/cases/beginning_backslash.py +0 -12
- deadcode-2.3.0/black/tests/data/cases/bracketmatch.py +0 -15
- deadcode-2.3.0/black/tests/data/cases/bytes_docstring.py +0 -34
- deadcode-2.3.0/black/tests/data/cases/class_blank_parentheses.py +0 -59
- deadcode-2.3.0/black/tests/data/cases/class_methods_new_line.py +0 -270
- deadcode-2.3.0/black/tests/data/cases/collections.py +0 -174
- deadcode-2.3.0/black/tests/data/cases/comment_after_escaped_newline.py +0 -18
- deadcode-2.3.0/black/tests/data/cases/comment_type_hint.py +0 -3
- deadcode-2.3.0/black/tests/data/cases/comments.py +0 -96
- deadcode-2.3.0/black/tests/data/cases/comments2.py +0 -344
- deadcode-2.3.0/black/tests/data/cases/comments3.py +0 -48
- deadcode-2.3.0/black/tests/data/cases/comments4.py +0 -94
- deadcode-2.3.0/black/tests/data/cases/comments5.py +0 -70
- deadcode-2.3.0/black/tests/data/cases/comments6.py +0 -118
- deadcode-2.3.0/black/tests/data/cases/comments8.py +0 -15
- deadcode-2.3.0/black/tests/data/cases/comments9.py +0 -305
- deadcode-2.3.0/black/tests/data/cases/comments_in_blocks.py +0 -111
- deadcode-2.3.0/black/tests/data/cases/comments_in_double_parens.py +0 -113
- deadcode-2.3.0/black/tests/data/cases/comments_non_breaking_space.py +0 -44
- deadcode-2.3.0/black/tests/data/cases/composition.py +0 -181
- deadcode-2.3.0/black/tests/data/cases/composition_no_trailing_comma.py +0 -367
- deadcode-2.3.0/black/tests/data/cases/conditional_expression.py +0 -204
- deadcode-2.3.0/black/tests/data/cases/context_managers_38.py +0 -55
- deadcode-2.3.0/black/tests/data/cases/context_managers_39.py +0 -175
- deadcode-2.3.0/black/tests/data/cases/context_managers_autodetect_310.py +0 -36
- deadcode-2.3.0/black/tests/data/cases/context_managers_autodetect_311.py +0 -38
- deadcode-2.3.0/black/tests/data/cases/context_managers_autodetect_38.py +0 -46
- deadcode-2.3.0/black/tests/data/cases/context_managers_autodetect_39.py +0 -35
- deadcode-2.3.0/black/tests/data/cases/docstring.py +0 -457
- deadcode-2.3.0/black/tests/data/cases/docstring_newline_preview.py +0 -4
- deadcode-2.3.0/black/tests/data/cases/docstring_no_extra_empty_line_before_eof.py +0 -4
- deadcode-2.3.0/black/tests/data/cases/docstring_no_string_normalization.py +0 -250
- deadcode-2.3.0/black/tests/data/cases/docstring_preview.py +0 -104
- deadcode-2.3.0/black/tests/data/cases/dummy_implementations.py +0 -144
- deadcode-2.3.0/black/tests/data/cases/empty_lines.py +0 -187
- deadcode-2.3.0/black/tests/data/cases/expression.py +0 -630
- deadcode-2.3.0/black/tests/data/cases/f_docstring.py +0 -20
- deadcode-2.3.0/black/tests/data/cases/fmtonoff.py +0 -409
- deadcode-2.3.0/black/tests/data/cases/fmtonoff2.py +0 -40
- deadcode-2.3.0/black/tests/data/cases/fmtonoff3.py +0 -35
- deadcode-2.3.0/black/tests/data/cases/fmtonoff4.py +0 -36
- deadcode-2.3.0/black/tests/data/cases/fmtonoff5.py +0 -175
- deadcode-2.3.0/black/tests/data/cases/fmtpass_imports.py +0 -19
- deadcode-2.3.0/black/tests/data/cases/fmtskip.py +0 -3
- deadcode-2.3.0/black/tests/data/cases/fmtskip2.py +0 -20
- deadcode-2.3.0/black/tests/data/cases/fmtskip3.py +0 -20
- deadcode-2.3.0/black/tests/data/cases/fmtskip4.py +0 -13
- deadcode-2.3.0/black/tests/data/cases/fmtskip5.py +0 -22
- deadcode-2.3.0/black/tests/data/cases/fmtskip6.py +0 -13
- deadcode-2.3.0/black/tests/data/cases/fmtskip7.py +0 -11
- deadcode-2.3.0/black/tests/data/cases/fmtskip8.py +0 -62
- deadcode-2.3.0/black/tests/data/cases/fmtskip9.py +0 -9
- deadcode-2.3.0/black/tests/data/cases/form_feeds.py +0 -226
- deadcode-2.3.0/black/tests/data/cases/fstring.py +0 -25
- deadcode-2.3.0/black/tests/data/cases/funcdef_return_type_trailing_comma.py +0 -301
- deadcode-2.3.0/black/tests/data/cases/function.py +0 -244
- deadcode-2.3.0/black/tests/data/cases/function2.py +0 -121
- deadcode-2.3.0/black/tests/data/cases/function_trailing_comma.py +0 -178
- deadcode-2.3.0/black/tests/data/cases/ignore_pyi.py +0 -42
- deadcode-2.3.0/black/tests/data/cases/import_spacing.py +0 -118
- deadcode-2.3.0/black/tests/data/cases/is_simple_lookup_for_doublestar_expression.py +0 -14
- deadcode-2.3.0/black/tests/data/cases/keep_newline_after_match.py +0 -41
- deadcode-2.3.0/black/tests/data/cases/line_ranges_basic.py +0 -107
- deadcode-2.3.0/black/tests/data/cases/line_ranges_diff_edge_case.py +0 -28
- deadcode-2.3.0/black/tests/data/cases/line_ranges_exceeding_end.py +0 -36
- deadcode-2.3.0/black/tests/data/cases/line_ranges_fmt_off.py +0 -49
- deadcode-2.3.0/black/tests/data/cases/line_ranges_fmt_off_decorator.py +0 -47
- deadcode-2.3.0/black/tests/data/cases/line_ranges_fmt_off_overlap.py +0 -37
- deadcode-2.3.0/black/tests/data/cases/line_ranges_imports.py +0 -9
- deadcode-2.3.0/black/tests/data/cases/line_ranges_indentation.py +0 -27
- deadcode-2.3.0/black/tests/data/cases/line_ranges_outside_source.py +0 -7
- deadcode-2.3.0/black/tests/data/cases/line_ranges_two_passes.py +0 -27
- deadcode-2.3.0/black/tests/data/cases/line_ranges_unwrapping.py +0 -25
- deadcode-2.3.0/black/tests/data/cases/linelength6.py +0 -6
- deadcode-2.3.0/black/tests/data/cases/long_strings_flag_disabled.py +0 -296
- deadcode-2.3.0/black/tests/data/cases/module_docstring_1.py +0 -25
- deadcode-2.3.0/black/tests/data/cases/module_docstring_2.py +0 -70
- deadcode-2.3.0/black/tests/data/cases/module_docstring_3.py +0 -7
- deadcode-2.3.0/black/tests/data/cases/module_docstring_4.py +0 -8
- deadcode-2.3.0/black/tests/data/cases/module_docstring_followed_by_class.py +0 -10
- deadcode-2.3.0/black/tests/data/cases/module_docstring_followed_by_function.py +0 -10
- deadcode-2.3.0/black/tests/data/cases/multiline_consecutive_open_parentheses_ignore.py +0 -41
- deadcode-2.3.0/black/tests/data/cases/nested_stub.py +0 -69
- deadcode-2.3.0/black/tests/data/cases/no_blank_line_before_docstring.py +0 -66
- deadcode-2.3.0/black/tests/data/cases/numeric_literals.py +0 -39
- deadcode-2.3.0/black/tests/data/cases/numeric_literals_skip_underscores.py +0 -19
- deadcode-2.3.0/black/tests/data/cases/one_element_subscript.py +0 -36
- deadcode-2.3.0/black/tests/data/cases/parenthesized_context_managers.py +0 -46
- deadcode-2.3.0/black/tests/data/cases/pattern_matching_complex.py +0 -155
- deadcode-2.3.0/black/tests/data/cases/pattern_matching_extras.py +0 -102
- deadcode-2.3.0/black/tests/data/cases/pattern_matching_generic.py +0 -108
- deadcode-2.3.0/black/tests/data/cases/pattern_matching_long.py +0 -34
- deadcode-2.3.0/black/tests/data/cases/pattern_matching_simple.py +0 -93
- deadcode-2.3.0/black/tests/data/cases/pattern_matching_style.py +0 -92
- deadcode-2.3.0/black/tests/data/cases/pattern_matching_trailing_comma.py +0 -39
- deadcode-2.3.0/black/tests/data/cases/pattern_matching_with_if_stmt.py +0 -72
- deadcode-2.3.0/black/tests/data/cases/pep604_union_types_line_breaks.py +0 -188
- deadcode-2.3.0/black/tests/data/cases/pep_570.py +0 -45
- deadcode-2.3.0/black/tests/data/cases/pep_572.py +0 -48
- deadcode-2.3.0/black/tests/data/cases/pep_572_do_not_remove_parens.py +0 -26
- deadcode-2.3.0/black/tests/data/cases/pep_572_py310.py +0 -16
- deadcode-2.3.0/black/tests/data/cases/pep_572_py39.py +0 -8
- deadcode-2.3.0/black/tests/data/cases/pep_572_remove_parens.py +0 -142
- deadcode-2.3.0/black/tests/data/cases/pep_572_slices.py +0 -6
- deadcode-2.3.0/black/tests/data/cases/pep_604.py +0 -25
- deadcode-2.3.0/black/tests/data/cases/pep_646.py +0 -195
- deadcode-2.3.0/black/tests/data/cases/pep_654.py +0 -54
- deadcode-2.3.0/black/tests/data/cases/pep_654_style.py +0 -112
- deadcode-2.3.0/black/tests/data/cases/percent_precedence.py +0 -41
- deadcode-2.3.0/black/tests/data/cases/power_op_newline.py +0 -11
- deadcode-2.3.0/black/tests/data/cases/power_op_spacing.py +0 -149
- deadcode-2.3.0/black/tests/data/cases/power_op_spacing_long.py +0 -96
- deadcode-2.3.0/black/tests/data/cases/prefer_rhs_split.py +0 -106
- deadcode-2.3.0/black/tests/data/cases/prefer_rhs_split_reformatted.py +0 -38
- deadcode-2.3.0/black/tests/data/cases/preview_cantfit.py +0 -94
- deadcode-2.3.0/black/tests/data/cases/preview_cantfit_string.py +0 -18
- deadcode-2.3.0/black/tests/data/cases/preview_comments7.py +0 -309
- deadcode-2.3.0/black/tests/data/cases/preview_format_unicode_escape_seq.py +0 -34
- deadcode-2.3.0/black/tests/data/cases/preview_hug_parens_with_braces_and_square_brackets.py +0 -347
- deadcode-2.3.0/black/tests/data/cases/preview_hug_parens_with_braces_and_square_brackets_no_ll1.py +0 -106
- deadcode-2.3.0/black/tests/data/cases/preview_long_dict_values.py +0 -129
- deadcode-2.3.0/black/tests/data/cases/preview_long_strings.py +0 -928
- deadcode-2.3.0/black/tests/data/cases/preview_long_strings__east_asian_width.py +0 -26
- deadcode-2.3.0/black/tests/data/cases/preview_long_strings__edge_case.py +0 -141
- deadcode-2.3.0/black/tests/data/cases/preview_long_strings__regression.py +0 -1247
- deadcode-2.3.0/black/tests/data/cases/preview_long_strings__type_annotations.py +0 -60
- deadcode-2.3.0/black/tests/data/cases/preview_multiline_strings.py +0 -401
- deadcode-2.3.0/black/tests/data/cases/preview_return_annotation_brackets_string.py +0 -24
- deadcode-2.3.0/black/tests/data/cases/py310_pep572.py +0 -13
- deadcode-2.3.0/black/tests/data/cases/python37.py +0 -62
- deadcode-2.3.0/black/tests/data/cases/python38.py +0 -42
- deadcode-2.3.0/black/tests/data/cases/python39.py +0 -30
- deadcode-2.3.0/black/tests/data/cases/raw_docstring.py +0 -32
- deadcode-2.3.0/black/tests/data/cases/raw_docstring_no_string_normalization.py +0 -11
- deadcode-2.3.0/black/tests/data/cases/remove_await_parens.py +0 -195
- deadcode-2.3.0/black/tests/data/cases/remove_except_parens.py +0 -79
- deadcode-2.3.0/black/tests/data/cases/remove_for_brackets.py +0 -48
- deadcode-2.3.0/black/tests/data/cases/remove_newline_after_code_block_open.py +0 -212
- deadcode-2.3.0/black/tests/data/cases/remove_parens.py +0 -142
- deadcode-2.3.0/black/tests/data/cases/remove_redundant_parens_in_case_guard.py +0 -114
- deadcode-2.3.0/black/tests/data/cases/remove_with_brackets.py +0 -120
- deadcode-2.3.0/black/tests/data/cases/return_annotation_brackets.py +0 -219
- deadcode-2.3.0/black/tests/data/cases/single_line_format_skip_with_multiple_comments.py +0 -19
- deadcode-2.3.0/black/tests/data/cases/skip_magic_trailing_comma.py +0 -75
- deadcode-2.3.0/black/tests/data/cases/slices.py +0 -31
- deadcode-2.3.0/black/tests/data/cases/split_delimiter_comments.py +0 -51
- deadcode-2.3.0/black/tests/data/cases/starred_for_target.py +0 -28
- deadcode-2.3.0/black/tests/data/cases/string_prefixes.py +0 -45
- deadcode-2.3.0/black/tests/data/cases/stub.py +0 -152
- deadcode-2.3.0/black/tests/data/cases/torture.py +0 -91
- deadcode-2.3.0/black/tests/data/cases/trailing_comma.py +0 -55
- deadcode-2.3.0/black/tests/data/cases/trailing_comma_optional_parens1.py +0 -63
- deadcode-2.3.0/black/tests/data/cases/trailing_comma_optional_parens2.py +0 -12
- deadcode-2.3.0/black/tests/data/cases/trailing_comma_optional_parens3.py +0 -21
- deadcode-2.3.0/black/tests/data/cases/trailing_commas_in_leading_parts.py +0 -88
- deadcode-2.3.0/black/tests/data/cases/tricky_unicode_symbols.py +0 -9
- deadcode-2.3.0/black/tests/data/cases/tupleassign.py +0 -23
- deadcode-2.3.0/black/tests/data/cases/type_aliases.py +0 -30
- deadcode-2.3.0/black/tests/data/cases/type_comment_syntax_error.py +0 -11
- deadcode-2.3.0/black/tests/data/cases/type_params.py +0 -58
- deadcode-2.3.0/black/tests/data/cases/typed_params_trailing_comma.py +0 -24
- deadcode-2.3.0/black/tests/data/cases/walrus_in_dict.py +0 -9
- deadcode-2.3.0/black/tests/data/cases/whitespace.py +0 -6
- deadcode-2.3.0/black/tests/data/gitignore_used_on_multiple_sources/dir1/a.py +0 -0
- deadcode-2.3.0/black/tests/data/gitignore_used_on_multiple_sources/dir1/b.py +0 -0
- deadcode-2.3.0/black/tests/data/gitignore_used_on_multiple_sources/dir2/a.py +0 -0
- deadcode-2.3.0/black/tests/data/gitignore_used_on_multiple_sources/dir2/b.py +0 -0
- deadcode-2.3.0/black/tests/data/ignore_subfolders_gitignore_tests/a.py +0 -0
- deadcode-2.3.0/black/tests/data/ignore_subfolders_gitignore_tests/subdir/b.py +0 -0
- deadcode-2.3.0/black/tests/data/ignore_subfolders_gitignore_tests/subdir/subdir/c.py +0 -0
- deadcode-2.3.0/black/tests/data/include_exclude_tests/b/.definitely_exclude/a.py +0 -0
- deadcode-2.3.0/black/tests/data/include_exclude_tests/b/dont_exclude/a.py +0 -0
- deadcode-2.3.0/black/tests/data/include_exclude_tests/b/exclude/a.py +0 -0
- deadcode-2.3.0/black/tests/data/invalid_gitignore_tests/a.py +0 -0
- deadcode-2.3.0/black/tests/data/invalid_nested_gitignore_tests/a/a.py +0 -0
- deadcode-2.3.0/black/tests/data/invalid_nested_gitignore_tests/a.py +0 -0
- deadcode-2.3.0/black/tests/data/line_ranges_formatted/basic.py +0 -50
- deadcode-2.3.0/black/tests/data/line_ranges_formatted/pattern_matching.py +0 -25
- deadcode-2.3.0/black/tests/data/miscellaneous/async_as_identifier.py +0 -49
- deadcode-2.3.0/black/tests/data/miscellaneous/blackd_diff.py +0 -6
- deadcode-2.3.0/black/tests/data/miscellaneous/debug_visitor.py +0 -32
- deadcode-2.3.0/black/tests/data/miscellaneous/decorators.py +0 -182
- deadcode-2.3.0/black/tests/data/miscellaneous/force_py36.py +0 -16
- deadcode-2.3.0/black/tests/data/miscellaneous/force_pyi.py +0 -66
- deadcode-2.3.0/black/tests/data/miscellaneous/invalid_header.py +0 -2
- deadcode-2.3.0/black/tests/data/miscellaneous/missing_final_newline.py +0 -3
- deadcode-2.3.0/black/tests/data/miscellaneous/pattern_matching_invalid.py +0 -18
- deadcode-2.3.0/black/tests/data/miscellaneous/python2_detection.py +0 -90
- deadcode-2.3.0/black/tests/data/miscellaneous/string_quotes.py +0 -114
- deadcode-2.3.0/black/tests/data/nested_gitignore_tests/root/a.py +0 -1
- deadcode-2.3.0/black/tests/data/nested_gitignore_tests/root/b.py +0 -1
- deadcode-2.3.0/black/tests/data/nested_gitignore_tests/root/c.py +0 -1
- deadcode-2.3.0/black/tests/data/nested_gitignore_tests/root/child/a.py +0 -1
- deadcode-2.3.0/black/tests/data/nested_gitignore_tests/root/child/b.py +0 -1
- deadcode-2.3.0/black/tests/data/nested_gitignore_tests/root/child/c.py +0 -1
- deadcode-2.3.0/black/tests/data/nested_gitignore_tests/x.py +0 -0
- deadcode-2.3.0/black/tests/optional.py +0 -132
- deadcode-2.3.0/black/tests/test_black.py +0 -2980
- deadcode-2.3.0/black/tests/test_blackd.py +0 -248
- deadcode-2.3.0/black/tests/test_docs.py +0 -74
- deadcode-2.3.0/black/tests/test_format.py +0 -90
- deadcode-2.3.0/black/tests/test_ipynb.py +0 -517
- deadcode-2.3.0/black/tests/test_no_ipynb.py +0 -36
- deadcode-2.3.0/black/tests/test_ranges.py +0 -249
- deadcode-2.3.0/black/tests/test_schema.py +0 -17
- deadcode-2.3.0/black/tests/test_trans.py +0 -51
- deadcode-2.3.0/black/tests/util.py +0 -354
- deadcode-2.3.0/call_arg_map_to_parameters_poc.py +0 -173
- deadcode-2.3.0/deadcode/actions/__init__.py +0 -0
- deadcode-2.3.0/deadcode/actions/parse_arguments.py +0 -229
- deadcode-2.3.0/deadcode/constants.py +0 -49
- deadcode-2.3.0/deadcode/tests/actions/test_find_python_filenames.py +0 -36
- deadcode-2.3.0/deadcode/tests/actions/test_merge_overlaping_file_parts.py +0 -62
- deadcode-2.3.0/deadcode/tests/cli_args/test_count.py +0 -0
- deadcode-2.3.0/deadcode/tests/cli_args/test_dry.py +0 -318
- deadcode-2.3.0/deadcode/tests/cli_args/test_exclude.py +0 -24
- deadcode-2.3.0/deadcode/tests/cli_args/test_fix.py +0 -528
- deadcode-2.3.0/deadcode/tests/cli_args/test_ignore_bodies_if_inherits_from.py +0 -46
- deadcode-2.3.0/deadcode/tests/cli_args/test_ignore_definitions.py +0 -106
- deadcode-2.3.0/deadcode/tests/cli_args/test_ignore_definitions_if_inherits_from.py +0 -125
- deadcode-2.3.0/deadcode/tests/cli_args/test_ignore_names.py +0 -79
- deadcode-2.3.0/deadcode/tests/cli_args/test_ignore_names_in_files.py +0 -0
- deadcode-2.3.0/deadcode/tests/cli_args/test_no_color.py +0 -0
- deadcode-2.3.0/deadcode/tests/cli_args/test_parsing.py +0 -113
- deadcode-2.3.0/deadcode/tests/cli_args/test_quiet.py +0 -0
- deadcode-2.3.0/deadcode/tests/cli_args/test_verbose.py +0 -0
- deadcode-2.3.0/deadcode/tests/code_item/test_code_item.py +0 -16
- deadcode-2.3.0/deadcode/tests/files/classes.py +0 -15
- deadcode-2.3.0/deadcode/tests/files/functions.py +0 -21
- deadcode-2.3.0/deadcode/tests/files/subdir/another_subdir/__init__.py +0 -1
- deadcode-2.3.0/deadcode/tests/files/subdir/one_more_file.py +0 -2
- deadcode-2.3.0/deadcode/tests/files/variables.py +0 -8
- deadcode-2.3.0/deadcode/tests/fix/test_assign.py +0 -92
- deadcode-2.3.0/deadcode/tests/fix/test_class_def.py +0 -116
- deadcode-2.3.0/deadcode/tests/fix/test_empty_files.py +0 -36
- deadcode-2.3.0/deadcode/tests/fix/test_method_def.py +0 -66
- deadcode-2.3.0/deadcode/tests/fix/test_scope.py +0 -243
- deadcode-2.3.0/deadcode/tests/fix/test_unreachable_code.py +0 -100
- deadcode-2.3.0/deadcode/tests/nested_scope/test_nested_scope.py +0 -180
- deadcode-2.3.0/deadcode/tests/noqa/test_noqa_comments.py +0 -329
- deadcode-2.3.0/deadcode/tests/test_accurate_usage_detection.py +0 -49
- deadcode-2.3.0/deadcode/tests/test_deadcode.py +0 -68
- deadcode-2.3.0/deadcode/tests/test_imports.py +0 -101
- deadcode-2.3.0/deadcode/tests/test_line_number_detection.py +0 -97
- deadcode-2.3.0/deadcode/tests/test_output.py +0 -137
- deadcode-2.3.0/deadcode/tests/test_variable_parsing_from_ast_dump.py +0 -12
- deadcode-2.3.0/deadcode/tests/utils/test_add_colors_to_diff.py +0 -38
- deadcode-2.3.0/deadcode/tests/utils/test_fix_indent.py +0 -10
- deadcode-2.3.0/deadcode/utils/__init__.py +0 -0
- deadcode-2.3.0/deadcode/utils/add_colors_to_diff.py +0 -10
- deadcode-2.3.0/deadcode/utils/fix_indent.py +0 -36
- deadcode-2.3.0/deadcode/utils/print_ast.py +0 -5
- deadcode-2.3.0/deadcode/visitor/__init__.py +0 -0
- deadcode-2.3.0/pyproject.toml +0 -94
- {deadcode-2.3.0 → deadcode-2.3.1}/.gitignore +0 -0
- {deadcode-2.3.0 → deadcode-2.3.1}/LICENSE +0 -0
- {deadcode-2.3.0/black/scripts → deadcode-2.3.1/deadcode}/__init__.py +0 -0
- {deadcode-2.3.0/black/src/black/resources → deadcode-2.3.1/deadcode/actions}/__init__.py +0 -0
- {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/actions/find_unused_names.py +0 -0
- {deadcode-2.3.0/black/tests → deadcode-2.3.1/deadcode/utils}/__init__.py +0 -0
- {deadcode-2.3.0/deadcode → deadcode-2.3.1/deadcode/visitor}/__init__.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: deadcode
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.1
|
|
4
4
|
Summary: Find and remove dead code.
|
|
5
|
-
Project-URL:
|
|
6
|
-
Project-URL:
|
|
5
|
+
Project-URL: homepage, https://github.com/albertas/deadcode
|
|
6
|
+
Project-URL: documentation, https://deadcode.readthedocs.io/
|
|
7
7
|
Author-email: Albertas Gimbutas <albertasgim@gmail.com>
|
|
8
8
|
License-File: LICENSE
|
|
9
9
|
Classifier: Development Status :: 3 - Alpha
|
|
@@ -15,8 +15,16 @@ Classifier: Programming Language :: Python :: 3.8
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.9
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.10
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
19
|
Requires-Python: >=3.8
|
|
19
|
-
Requires-Dist: tomli
|
|
20
|
+
Requires-Dist: tomli>=2.0.1
|
|
21
|
+
Provides-Extra: test
|
|
22
|
+
Requires-Dist: hatch; extra == 'test'
|
|
23
|
+
Requires-Dist: mypy; extra == 'test'
|
|
24
|
+
Requires-Dist: pip-audit; extra == 'test'
|
|
25
|
+
Requires-Dist: pytest; extra == 'test'
|
|
26
|
+
Requires-Dist: pytest-cov; extra == 'test'
|
|
27
|
+
Requires-Dist: ruff; extra == 'test'
|
|
20
28
|
Description-Content-Type: text/markdown
|
|
21
29
|
|
|
22
30
|
[](https://deadcode.readthedocs.io/en/stable/)
|
|
@@ -46,7 +54,7 @@ To see suggested fixes for all files:
|
|
|
46
54
|
deadcode . --fix --dry
|
|
47
55
|
```
|
|
48
56
|
|
|
49
|
-
To see suggested fixes for
|
|
57
|
+
To see suggested fixes only for `foo.py` file:
|
|
50
58
|
```shell
|
|
51
59
|
deadcode . --fix --dry foo.py
|
|
52
60
|
```
|
|
@@ -69,7 +77,7 @@ ignore-names = ["BaseTestCase", "*Mixin"]
|
|
|
69
77
|
ignore-names-in-files = ["migrations"]
|
|
70
78
|
```
|
|
71
79
|
|
|
72
|
-
|
|
80
|
+
## Command line options
|
|
73
81
|
|
|
74
82
|
| Option | Type | Meaning |
|
|
75
83
|
|-------------------------------------------|------|----------------------------------------------------------------------|
|
|
@@ -177,13 +185,13 @@ code base is implemented in.
|
|
|
177
185
|
- [ ] Distinguish between definitions with same name, but different files.
|
|
178
186
|
- [ ] Repeated application of `deadcode` till the output stops changing.
|
|
179
187
|
- [ ] Unreachable code detection and fixing: this should only be scoped for if statements and only limited to primitive variables.
|
|
180
|
-
- [
|
|
188
|
+
- [x] `--fix --dry [filenames]` - only show whats about to change in the listed filenames.
|
|
181
189
|
- [ ] Benchmarking performance with larger projects (time, CPU and memory consumption) in order to optimize.
|
|
182
190
|
- [ ] `--fix` could accept a list of filenames as well (only those files would be changed, but the summary could would be full).
|
|
183
191
|
(This might be confusing, because filenames, which have to be considered are provided without any flag, --fix is expected to not accept arguments)
|
|
184
192
|
- [ ] pre-commit-hook.
|
|
185
193
|
- [ ] language server.
|
|
186
|
-
- [
|
|
194
|
+
- [x] Use only two digits for error codes instead of 3. Two is plenty and it simplifies usage a bit
|
|
187
195
|
- [ ] DC10: remove code after terminal statements like `raise`, `return`, `break`, `continue` and comes in the same scope.
|
|
188
196
|
- [ ] Add `ignore` and `per-file-ignores` command line and pyproject.toml options, which allows to skip some rules.
|
|
189
197
|
- [ ] Make sure that all rules are being skipped by `noqa` comment and all rules react to `noqa: rule_id` comments.
|
|
@@ -191,3 +199,12 @@ code base is implemented in.
|
|
|
191
199
|
- [ ] All options should be able to accept dot-separated path or a generic name, e.g. "marshmallow.Schema" vs "Schema",
|
|
192
200
|
documentation should cleary demonstrate the behaviour/example that "Schema" means "*.Schema".
|
|
193
201
|
- [ ] Redefinition of an existing name makes previous name unreachable, unless it is assigned somehow.
|
|
202
|
+
- [ ] Check if file is still valid/parsable after automatic fixing, if not: halt the change and report error.
|
|
203
|
+
|
|
204
|
+
## Release notes
|
|
205
|
+
- v2.3.1:
|
|
206
|
+
- Started analysing files in bytes instead of trying to convert them into UTF-8 encoded strings.
|
|
207
|
+
- Improved automatic removal of unused imports.
|
|
208
|
+
- v2.3.0:
|
|
209
|
+
- Add `--dry` option.
|
|
210
|
+
- Update error codes to use DCXX format instead of DCXXX.
|
|
@@ -25,7 +25,7 @@ To see suggested fixes for all files:
|
|
|
25
25
|
deadcode . --fix --dry
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
To see suggested fixes for
|
|
28
|
+
To see suggested fixes only for `foo.py` file:
|
|
29
29
|
```shell
|
|
30
30
|
deadcode . --fix --dry foo.py
|
|
31
31
|
```
|
|
@@ -48,7 +48,7 @@ ignore-names = ["BaseTestCase", "*Mixin"]
|
|
|
48
48
|
ignore-names-in-files = ["migrations"]
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
## Command line options
|
|
52
52
|
|
|
53
53
|
| Option | Type | Meaning |
|
|
54
54
|
|-------------------------------------------|------|----------------------------------------------------------------------|
|
|
@@ -156,13 +156,13 @@ code base is implemented in.
|
|
|
156
156
|
- [ ] Distinguish between definitions with same name, but different files.
|
|
157
157
|
- [ ] Repeated application of `deadcode` till the output stops changing.
|
|
158
158
|
- [ ] Unreachable code detection and fixing: this should only be scoped for if statements and only limited to primitive variables.
|
|
159
|
-
- [
|
|
159
|
+
- [x] `--fix --dry [filenames]` - only show whats about to change in the listed filenames.
|
|
160
160
|
- [ ] Benchmarking performance with larger projects (time, CPU and memory consumption) in order to optimize.
|
|
161
161
|
- [ ] `--fix` could accept a list of filenames as well (only those files would be changed, but the summary could would be full).
|
|
162
162
|
(This might be confusing, because filenames, which have to be considered are provided without any flag, --fix is expected to not accept arguments)
|
|
163
163
|
- [ ] pre-commit-hook.
|
|
164
164
|
- [ ] language server.
|
|
165
|
-
- [
|
|
165
|
+
- [x] Use only two digits for error codes instead of 3. Two is plenty and it simplifies usage a bit
|
|
166
166
|
- [ ] DC10: remove code after terminal statements like `raise`, `return`, `break`, `continue` and comes in the same scope.
|
|
167
167
|
- [ ] Add `ignore` and `per-file-ignores` command line and pyproject.toml options, which allows to skip some rules.
|
|
168
168
|
- [ ] Make sure that all rules are being skipped by `noqa` comment and all rules react to `noqa: rule_id` comments.
|
|
@@ -170,3 +170,12 @@ code base is implemented in.
|
|
|
170
170
|
- [ ] All options should be able to accept dot-separated path or a generic name, e.g. "marshmallow.Schema" vs "Schema",
|
|
171
171
|
documentation should cleary demonstrate the behaviour/example that "Schema" means "*.Schema".
|
|
172
172
|
- [ ] Redefinition of an existing name makes previous name unreachable, unless it is assigned somehow.
|
|
173
|
+
- [ ] Check if file is still valid/parsable after automatic fixing, if not: halt the change and report error.
|
|
174
|
+
|
|
175
|
+
## Release notes
|
|
176
|
+
- v2.3.1:
|
|
177
|
+
- Started analysing files in bytes instead of trying to convert them into UTF-8 encoded strings.
|
|
178
|
+
- Improved automatic removal of unused imports.
|
|
179
|
+
- v2.3.0:
|
|
180
|
+
- Add `--dry` option.
|
|
181
|
+
- Update error codes to use DCXX format instead of DCXXX.
|
|
@@ -16,21 +16,21 @@ def find_python_filenames(args: Args) -> List[str]:
|
|
|
16
16
|
|
|
17
17
|
if _match(path, args.exclude):
|
|
18
18
|
if args.verbose:
|
|
19
|
-
logger.info(f
|
|
19
|
+
logger.info(f'Ignoring: {path}')
|
|
20
20
|
continue
|
|
21
21
|
|
|
22
|
-
if path.is_file() and path.suffix ==
|
|
22
|
+
if path.is_file() and path.suffix == '.py':
|
|
23
23
|
filenames.append(str(path))
|
|
24
24
|
elif path.is_dir():
|
|
25
|
-
paths += list([str(p) for p in path.glob(
|
|
25
|
+
paths += list([str(p) for p in path.glob('*')])
|
|
26
26
|
elif not path.exists():
|
|
27
27
|
# TODO: unify error logging and reporting
|
|
28
28
|
# Maybe a cli flag could be added to stop on error
|
|
29
|
-
logger.error(f
|
|
29
|
+
logger.error(f'Error: {path} could not be found.')
|
|
30
30
|
|
|
31
31
|
if args.verbose:
|
|
32
|
-
sep =
|
|
33
|
-
logger.info(f
|
|
32
|
+
sep = '\n - '
|
|
33
|
+
logger.info(f'Files to be checked for dead code: {sep.join(filenames)}')
|
|
34
34
|
return filenames
|
|
35
35
|
|
|
36
36
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from collections import defaultdict
|
|
2
|
-
from difflib import unified_diff
|
|
2
|
+
from difflib import diff_bytes, unified_diff
|
|
3
3
|
from typing import Iterable
|
|
4
4
|
import os
|
|
5
5
|
|
|
@@ -27,37 +27,39 @@ def fix_or_show_unused_code(unused_items: Iterable[CodeItem], args: Args) -> str
|
|
|
27
27
|
|
|
28
28
|
result = []
|
|
29
29
|
|
|
30
|
-
for filename,
|
|
31
|
-
file_parts = flatten_list([item.code_parts for item in
|
|
30
|
+
for filename, file_unused_items in filename_to_unused_items.items():
|
|
31
|
+
file_parts = flatten_list([item.code_parts for item in file_unused_items])
|
|
32
32
|
|
|
33
33
|
unused_file_parts = merge_overlaping_file_parts(file_parts)
|
|
34
34
|
|
|
35
|
-
with open(filename) as f:
|
|
35
|
+
with open(filename, 'rb') as f:
|
|
36
36
|
file_content_lines = f.readlines()
|
|
37
37
|
|
|
38
38
|
updated_file_content_lines = remove_file_parts_from_content(file_content_lines, unused_file_parts)
|
|
39
|
-
updated_file_content =
|
|
39
|
+
updated_file_content = b''.join(updated_file_content_lines)
|
|
40
40
|
if updated_file_content.strip():
|
|
41
|
-
if args.dry and (
|
|
42
|
-
with open(filename,
|
|
43
|
-
|
|
41
|
+
if args.dry and ('__all_files__' in args.dry or _match(filename, args.dry)):
|
|
42
|
+
with open(filename, 'rb') as f:
|
|
43
|
+
filename_bytes = filename.encode()
|
|
44
|
+
diff = diff_bytes(unified_diff, f.readlines(), updated_file_content_lines,
|
|
45
|
+
fromfile=filename_bytes, tofile=filename_bytes)
|
|
44
46
|
# TODO: consider printing result instantly to save memory
|
|
45
|
-
|
|
47
|
+
result_chunk = b''.join(diff)
|
|
46
48
|
if args.no_color:
|
|
47
|
-
result.append(
|
|
49
|
+
result.append(result_chunk)
|
|
48
50
|
else:
|
|
49
|
-
result.append(add_colors_to_diff(
|
|
51
|
+
result.append(add_colors_to_diff(result_chunk))
|
|
50
52
|
|
|
51
53
|
elif args.fix:
|
|
52
|
-
with open(filename,
|
|
54
|
+
with open(filename, 'wb') as f:
|
|
53
55
|
# TODO: is there a method writelines?
|
|
54
56
|
f.write(updated_file_content)
|
|
55
57
|
else:
|
|
56
58
|
os.remove(filename)
|
|
57
59
|
|
|
58
60
|
if result:
|
|
59
|
-
return
|
|
60
|
-
return
|
|
61
|
+
return b'\n'.join(result).decode()
|
|
62
|
+
return ''
|
|
61
63
|
|
|
62
64
|
# TODO: update this one: solution is to use read and write operations.
|
|
63
65
|
#
|
|
@@ -11,25 +11,25 @@ def get_unused_names_error_message(unused_names: Iterable[CodeItem], args: Args)
|
|
|
11
11
|
return None
|
|
12
12
|
|
|
13
13
|
if args.quiet:
|
|
14
|
-
return
|
|
14
|
+
return ''
|
|
15
15
|
|
|
16
16
|
if args.count:
|
|
17
|
-
return f
|
|
17
|
+
return f'{len(unused_names)}'
|
|
18
18
|
|
|
19
19
|
messages = []
|
|
20
20
|
for item in unused_names:
|
|
21
|
-
message = f
|
|
21
|
+
message = f'{item.filename_with_position} \033[91m{item.error_code}\033[0m '
|
|
22
22
|
message += item.message or (
|
|
23
23
|
f"{item.type_.replace('_', ' ').capitalize()} " f"`\033[1m{item.name}\033[0m` " f"is never used"
|
|
24
24
|
)
|
|
25
25
|
if args.no_color:
|
|
26
|
-
message = message.replace(
|
|
26
|
+
message = message.replace('\033[91m', '').replace('\033[1m', '').replace('\033[0m', '')
|
|
27
27
|
messages.append(message)
|
|
28
28
|
|
|
29
29
|
if args.fix:
|
|
30
30
|
message = f"\nRemoved \033[1m{len(unused_names)}\033[0m unused code item{'s' if len(unused_names) > 1 else ''}!"
|
|
31
31
|
if args.no_color:
|
|
32
|
-
message = message.replace(
|
|
32
|
+
message = message.replace('\x1b[1m', '').replace('\x1b[0m', '')
|
|
33
33
|
messages.append(message)
|
|
34
34
|
|
|
35
|
-
return
|
|
35
|
+
return '\n'.join(messages)
|
|
@@ -10,9 +10,7 @@ def does_include(bigger_part: Part, smaller_part: Part) -> bool:
|
|
|
10
10
|
|
|
11
11
|
ends_faster = (line_end_b < line_end_s) or ((line_end_b == line_end_b) and (col_end_b <= col_end_s))
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
return True
|
|
15
|
-
return False
|
|
13
|
+
return bool(starts_later and ends_faster)
|
|
16
14
|
|
|
17
15
|
|
|
18
16
|
def sort_parts(bigger_part: Part, smaller_part: Part) -> Tuple[Part, Part]:
|
|
@@ -34,10 +32,7 @@ def does_overlap(bigger_part: Part, smaller_part: Part) -> bool:
|
|
|
34
32
|
line_start_s, line_end_s, col_start_s, col_end_s = smaller_part
|
|
35
33
|
|
|
36
34
|
# ar pirmo pabaiga perlipa antro pradžia
|
|
37
|
-
|
|
38
|
-
return True
|
|
39
|
-
|
|
40
|
-
return False
|
|
35
|
+
return bool((line_end_b > line_start_s) or ((line_end_b == line_start_s) and (col_end_b > col_start_s)))
|
|
41
36
|
|
|
42
37
|
|
|
43
38
|
def merge_parts(p1: Part, p2: Part) -> Optional[Part]:
|
|
@@ -9,5 +9,5 @@ def parse_abstract_syntax_tree(file_content: FileContent, args: Args, filename:
|
|
|
9
9
|
return ast.parse(file_content, filename=filename, type_comments=True)
|
|
10
10
|
except: # noqa: E722
|
|
11
11
|
if not args.count and not args.quiet:
|
|
12
|
-
print(f
|
|
12
|
+
print(f'Error: Failed to parse {filename} file, ignoring it.')
|
|
13
13
|
return ast.Module()
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
from typing import Any, Dict, List, Optional
|
|
3
|
+
import sys
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
if sys.version_info >= (3, 11):
|
|
7
|
+
import tomllib
|
|
8
|
+
else:
|
|
9
|
+
import tomli as tomllib
|
|
10
|
+
|
|
11
|
+
from deadcode.data_types import Args
|
|
12
|
+
from deadcode.utils.flatten_lists import flatten_lists_of_comma_separated_values
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def parse_arguments(args: Optional[List[str]]) -> Args:
|
|
16
|
+
"""Parses arguments (execution options) for deadcode tool.
|
|
17
|
+
|
|
18
|
+
Arguments for DeadCode can be provided via:
|
|
19
|
+
- via command line
|
|
20
|
+
- via pyproject.toml
|
|
21
|
+
- via function arguments
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
if not args:
|
|
25
|
+
args = sys.argv[1:]
|
|
26
|
+
|
|
27
|
+
# Docs: https://docs.python.org/3/library/argparse.html
|
|
28
|
+
parser = argparse.ArgumentParser()
|
|
29
|
+
parser.add_argument('paths', help='Paths where to search for python files', nargs='+')
|
|
30
|
+
parser.add_argument(
|
|
31
|
+
'--fix',
|
|
32
|
+
help='Automatically remove detected unused code expressions from the code base.',
|
|
33
|
+
action='store_true',
|
|
34
|
+
default=False,
|
|
35
|
+
)
|
|
36
|
+
parser.add_argument(
|
|
37
|
+
'--dry',
|
|
38
|
+
help='Show changes which would be made in files with --fix option.',
|
|
39
|
+
nargs='*',
|
|
40
|
+
action='append',
|
|
41
|
+
default=[['__all_files__']],
|
|
42
|
+
type=str,
|
|
43
|
+
)
|
|
44
|
+
parser.add_argument(
|
|
45
|
+
'--exclude',
|
|
46
|
+
help='Filenames (or path expressions), which will be completely skipped without being analysed.',
|
|
47
|
+
nargs='*',
|
|
48
|
+
action='append',
|
|
49
|
+
default=[],
|
|
50
|
+
type=str,
|
|
51
|
+
)
|
|
52
|
+
parser.add_argument(
|
|
53
|
+
'--ignore-names',
|
|
54
|
+
help=(
|
|
55
|
+
'Removes provided list of names from the output. '
|
|
56
|
+
'Regexp expressions to match multiple names can also be provided.'
|
|
57
|
+
),
|
|
58
|
+
nargs='*',
|
|
59
|
+
action='append',
|
|
60
|
+
default=[],
|
|
61
|
+
type=str,
|
|
62
|
+
)
|
|
63
|
+
parser.add_argument(
|
|
64
|
+
'--ignore-bodies-of',
|
|
65
|
+
help='Ignores body of an expression if its name matches any of the provided names.',
|
|
66
|
+
nargs='*',
|
|
67
|
+
action='append',
|
|
68
|
+
default=[],
|
|
69
|
+
type=str,
|
|
70
|
+
)
|
|
71
|
+
parser.add_argument(
|
|
72
|
+
'--ignore-bodies-if-decorated-with',
|
|
73
|
+
help='Ignores body of an expression if its decorated with one of the provided decorator names.',
|
|
74
|
+
nargs='*',
|
|
75
|
+
action='append',
|
|
76
|
+
default=[],
|
|
77
|
+
type=str,
|
|
78
|
+
)
|
|
79
|
+
parser.add_argument(
|
|
80
|
+
'--ignore-bodies-if-inherits-from',
|
|
81
|
+
help='Ignores body of a class if it inherits from any of the provided class names.',
|
|
82
|
+
nargs='*',
|
|
83
|
+
action='append',
|
|
84
|
+
default=[],
|
|
85
|
+
type=str,
|
|
86
|
+
)
|
|
87
|
+
parser.add_argument(
|
|
88
|
+
'--ignore-definitions',
|
|
89
|
+
help=(
|
|
90
|
+
'Ignores definition (including name and body) if a '
|
|
91
|
+
'name of an expression matches any of the provided ones.'
|
|
92
|
+
),
|
|
93
|
+
nargs='*',
|
|
94
|
+
action='append',
|
|
95
|
+
default=[],
|
|
96
|
+
type=str,
|
|
97
|
+
)
|
|
98
|
+
parser.add_argument(
|
|
99
|
+
'--ignore-definitions-if-inherits-from',
|
|
100
|
+
help=(
|
|
101
|
+
'Ignores definition (including name and body) of a class if '
|
|
102
|
+
'it inherits from any of the provided class names.'
|
|
103
|
+
),
|
|
104
|
+
nargs='*',
|
|
105
|
+
action='append',
|
|
106
|
+
default=[],
|
|
107
|
+
type=str,
|
|
108
|
+
)
|
|
109
|
+
parser.add_argument(
|
|
110
|
+
'--ignore-definitions-if-decorated-with',
|
|
111
|
+
help=(
|
|
112
|
+
'Ignores definition (including name and body) of an expression, '
|
|
113
|
+
'which is decorated with any of the provided decorator names.'
|
|
114
|
+
),
|
|
115
|
+
nargs='*',
|
|
116
|
+
action='append',
|
|
117
|
+
default=[],
|
|
118
|
+
type=str,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
parser.add_argument(
|
|
122
|
+
'--ignore-if-decorated-with',
|
|
123
|
+
help='Ignores both the name and its definition if its decorated with one of the provided decorator names.',
|
|
124
|
+
nargs='*',
|
|
125
|
+
action='append',
|
|
126
|
+
default=[],
|
|
127
|
+
type=str,
|
|
128
|
+
)
|
|
129
|
+
parser.add_argument(
|
|
130
|
+
'--ignore-if-inherits-from',
|
|
131
|
+
help='Ignores both the name and its definition if the class inerits from the provided class name.',
|
|
132
|
+
nargs='*',
|
|
133
|
+
action='append',
|
|
134
|
+
default=[],
|
|
135
|
+
type=str,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
parser.add_argument(
|
|
139
|
+
'--ignore-names-if-inherits-from',
|
|
140
|
+
help='Ignores names of classes, which inherit from provided class names.',
|
|
141
|
+
nargs='*',
|
|
142
|
+
action='append',
|
|
143
|
+
default=[],
|
|
144
|
+
type=str,
|
|
145
|
+
)
|
|
146
|
+
parser.add_argument(
|
|
147
|
+
'--ignore-names-if-decorated-with',
|
|
148
|
+
help='Ignores names of an expression, which is decorated with one of the provided decorator names.',
|
|
149
|
+
nargs='*',
|
|
150
|
+
action='append',
|
|
151
|
+
default=[],
|
|
152
|
+
type=str,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
parser.add_argument(
|
|
156
|
+
'--ignore-names-in-files',
|
|
157
|
+
help='Ignores unused names in files, which filenames match provided path expressions.',
|
|
158
|
+
nargs='*',
|
|
159
|
+
action='append',
|
|
160
|
+
default=[],
|
|
161
|
+
type=str,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
parser.add_argument(
|
|
165
|
+
'--no-color',
|
|
166
|
+
help='Turn off colors in the output',
|
|
167
|
+
action='store_true',
|
|
168
|
+
default=False,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
parser.add_argument(
|
|
172
|
+
'--quiet',
|
|
173
|
+
help='Does not output anything. Makefile still fails with exit code 1 if unused names are found.',
|
|
174
|
+
action='store_true',
|
|
175
|
+
default=False,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
parser.add_argument(
|
|
179
|
+
'--count',
|
|
180
|
+
help='Provides the count of the detected unused names instead of printing them all out.',
|
|
181
|
+
action='store_true',
|
|
182
|
+
default=False,
|
|
183
|
+
)
|
|
184
|
+
parser.add_argument(
|
|
185
|
+
'-v',
|
|
186
|
+
'--verbose',
|
|
187
|
+
help='Shows logs useful for debuging',
|
|
188
|
+
action='store_true',
|
|
189
|
+
default=False,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
parsed_args = parser.parse_args(args).__dict__
|
|
193
|
+
|
|
194
|
+
for arg_name, arg_value in parsed_args.items():
|
|
195
|
+
if isinstance(arg_value, list) and arg_name != 'paths':
|
|
196
|
+
parsed_args[arg_name] = flatten_lists_of_comma_separated_values(parsed_args.get(arg_name))
|
|
197
|
+
|
|
198
|
+
# Extend the Args with the values provided in the pyproject.toml
|
|
199
|
+
for key, item in parse_pyproject_toml().items():
|
|
200
|
+
if key in parsed_args:
|
|
201
|
+
parsed_args[key].extend(item)
|
|
202
|
+
|
|
203
|
+
# Show changes for only provided files instead of all
|
|
204
|
+
if len(parsed_args['dry']) > 1 or '--dry' not in args:
|
|
205
|
+
parsed_args['dry'].remove('__all_files__')
|
|
206
|
+
|
|
207
|
+
# Do not fix if dry option is provided:
|
|
208
|
+
if parsed_args['dry']:
|
|
209
|
+
parsed_args['fix'] = False
|
|
210
|
+
|
|
211
|
+
return Args(**parsed_args)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def parse_pyproject_toml() -> Dict[str, Any]:
|
|
215
|
+
"""Parse a pyproject toml file, pulling out relevant parts for Black.
|
|
216
|
+
|
|
217
|
+
If parsing fails, will raise a tomllib.TOMLDecodeError.
|
|
218
|
+
Copied from: https://github.com/psf/black/blob/01b8d3d4095ebdb91d0d39012a517931625c63cb/src/black/files.py#LL113C15-L113C15
|
|
219
|
+
"""
|
|
220
|
+
pyproject_toml_filename = 'pyproject.toml'
|
|
221
|
+
if not os.path.isfile(pyproject_toml_filename):
|
|
222
|
+
return {}
|
|
223
|
+
|
|
224
|
+
with open(pyproject_toml_filename, 'rb') as f:
|
|
225
|
+
pyproject_toml = tomllib.load(f)
|
|
226
|
+
|
|
227
|
+
config: Dict[str, Any] = pyproject_toml.get('tool', {}).get('deadcode', {})
|
|
228
|
+
config = {k.replace('--', '').replace('-', '_'): v for k, v in config.items()}
|
|
229
|
+
return config
|
|
@@ -3,7 +3,7 @@ from typing import List, Optional, TypeVar
|
|
|
3
3
|
|
|
4
4
|
from deadcode.data_types import Part
|
|
5
5
|
|
|
6
|
-
T = TypeVar(
|
|
6
|
+
T = TypeVar('T')
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def list_get(list_: List[T], index: int) -> Optional[T]:
|
|
@@ -12,20 +12,20 @@ def list_get(list_: List[T], index: int) -> Optional[T]:
|
|
|
12
12
|
return None
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def ends_with_semicolon(line:
|
|
16
|
-
return line.strip().endswith(
|
|
15
|
+
def ends_with_semicolon(line: bytes) -> bool:
|
|
16
|
+
return line.strip().endswith(b':')
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def indentation_is_not_childs(previous_line:
|
|
19
|
+
def indentation_is_not_childs(previous_line: bytes, current_line: bytes) -> bool:
|
|
20
20
|
return len(get_indentation(previous_line)) >= len(get_indentation(current_line))
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
def get_indentation(line:
|
|
24
|
-
return
|
|
23
|
+
def get_indentation(line: bytes) -> bytes:
|
|
24
|
+
return bytes(re.findall(b'^\\s*', line)[0])
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
def remove_as_from_end(line:
|
|
28
|
-
if not (line_rstrip := line.rstrip()).endswith(
|
|
27
|
+
def remove_as_from_end(line: bytes) -> bytes:
|
|
28
|
+
if not (line_rstrip := line.rstrip()).endswith(b'as'):
|
|
29
29
|
return line
|
|
30
30
|
|
|
31
31
|
# Is there white spaces before as
|
|
@@ -34,7 +34,14 @@ def remove_as_from_end(line: str) -> str:
|
|
|
34
34
|
return line
|
|
35
35
|
|
|
36
36
|
|
|
37
|
-
def
|
|
37
|
+
def remove_comma_from_begining(line: bytes) -> bytes:
|
|
38
|
+
if not line.lstrip().startswith(b','):
|
|
39
|
+
return line
|
|
40
|
+
|
|
41
|
+
return line.lstrip()[1:].lstrip()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def remove_file_parts_from_content(content_lines: List[bytes], unused_file_parts: List[Part]) -> List[bytes]:
|
|
38
45
|
""" """
|
|
39
46
|
# How should move through the lines of content?
|
|
40
47
|
updated_content_lines = []
|
|
@@ -42,12 +49,12 @@ def remove_file_parts_from_content(content_lines: List[str], unused_file_parts:
|
|
|
42
49
|
# TODO: iterate by line and crop that line if needed.
|
|
43
50
|
unused_part_index = 0
|
|
44
51
|
|
|
45
|
-
previous_non_removed_line =
|
|
52
|
+
previous_non_removed_line = b''
|
|
46
53
|
was_block_removed = False
|
|
47
54
|
next_line_after_removed_block = None
|
|
48
|
-
indentation_of_first_removed_line =
|
|
49
|
-
empty_lines_in_a_row_list: List[
|
|
50
|
-
empty_lines_before_removed_block_list: List[
|
|
55
|
+
indentation_of_first_removed_line = b''
|
|
56
|
+
empty_lines_in_a_row_list: List[bytes] = []
|
|
57
|
+
empty_lines_before_removed_block_list: List[bytes] = []
|
|
51
58
|
|
|
52
59
|
for current_lineno, line in enumerate(content_lines, start=1):
|
|
53
60
|
from_line, to_line, from_col, to_col = 0, 0, 0, 0
|
|
@@ -63,10 +70,14 @@ def remove_file_parts_from_content(content_lines: List[str], unused_file_parts:
|
|
|
63
70
|
indentation_of_first_removed_line = get_indentation(line)
|
|
64
71
|
|
|
65
72
|
if from_line == to_line:
|
|
66
|
-
|
|
73
|
+
# TODO: this check is a workaround for an assignment expression.
|
|
74
|
+
# Clean-ups have to be applied based on removable expression type.
|
|
75
|
+
if (line[:from_col] + line[to_col:]).strip().startswith(b'='):
|
|
67
76
|
line = line[:from_col]
|
|
68
77
|
else:
|
|
69
|
-
|
|
78
|
+
# TODO: should apply `as` removal rule only for particular expression type only
|
|
79
|
+
# as well as comma removal.
|
|
80
|
+
line = remove_as_from_end(line[:from_col]) + remove_comma_from_begining(line[to_col:])
|
|
70
81
|
|
|
71
82
|
unused_part_index += 1
|
|
72
83
|
|
|
@@ -80,16 +91,22 @@ def remove_file_parts_from_content(content_lines: List[str], unused_file_parts:
|
|
|
80
91
|
else:
|
|
81
92
|
line = line[:from_col]
|
|
82
93
|
|
|
83
|
-
if line.strip() and not line.startswith(
|
|
94
|
+
if line.strip() and not line.startswith(b'#'):
|
|
84
95
|
previous_non_removed_line = line
|
|
85
96
|
updated_content_lines.append(line)
|
|
86
97
|
|
|
87
98
|
# Is it last line, from the block, which have to be ignored?
|
|
88
99
|
elif current_lineno == to_line:
|
|
89
100
|
line = line[to_col:]
|
|
101
|
+
|
|
102
|
+
# Remove trailing comma, if we have removed something.
|
|
103
|
+
# TODO: this should be applied only for specific expression types only.
|
|
104
|
+
if line.lstrip().startswith(b','):
|
|
105
|
+
line = line.lstrip()[1:].lstrip()
|
|
106
|
+
|
|
90
107
|
unused_part_index += 1
|
|
91
108
|
# TODO: Add tests for case, when comments are added at the start or end of the removed block
|
|
92
|
-
if line.strip() and not line.startswith(
|
|
109
|
+
if line.strip() and not line.startswith(b'#'):
|
|
93
110
|
updated_content_lines.append(line)
|
|
94
111
|
|
|
95
112
|
empty_lines_before_removed_block_list, empty_lines_in_a_row_list = (
|
|
@@ -118,7 +135,7 @@ def remove_file_parts_from_content(content_lines: List[str], unused_file_parts:
|
|
|
118
135
|
if indentation_is_not_childs(
|
|
119
136
|
previous_line=previous_non_removed_line, current_line=next_line_after_removed_block
|
|
120
137
|
):
|
|
121
|
-
updated_content_lines.append(
|
|
138
|
+
updated_content_lines.append(indentation_of_first_removed_line + b'pass\n')
|
|
122
139
|
|
|
123
140
|
# Add empty lines
|
|
124
141
|
if indentation_is_not_childs(
|
|
@@ -144,6 +161,6 @@ def remove_file_parts_from_content(content_lines: List[str], unused_file_parts:
|
|
|
144
161
|
|
|
145
162
|
if was_block_removed:
|
|
146
163
|
if ends_with_semicolon(previous_non_removed_line):
|
|
147
|
-
updated_content_lines.append(
|
|
164
|
+
updated_content_lines.append(indentation_of_first_removed_line + b'pass\n')
|
|
148
165
|
|
|
149
166
|
return updated_content_lines
|
|
@@ -24,12 +24,12 @@ def main(
|
|
|
24
24
|
file_diff = fix_or_show_unused_code(unused_names, args=args)
|
|
25
25
|
|
|
26
26
|
if (error_message := get_unused_names_error_message(unused_names, args=args)) is not None:
|
|
27
|
-
return error_message + (
|
|
27
|
+
return error_message + ('\n\n' + file_diff if file_diff else '')
|
|
28
28
|
|
|
29
29
|
if not args.count and not args.quiet:
|
|
30
|
-
print(
|
|
30
|
+
print('\033[1mWell done!\033[0m ✨ 🚀 ✨')
|
|
31
31
|
return None
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
if __name__ ==
|
|
34
|
+
if __name__ == '__main__':
|
|
35
35
|
main()
|