deadcode 2.3.0__py3-none-any.whl → 2.3.1__py3-none-any.whl
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/actions/find_python_filenames.py +6 -6
- deadcode/actions/fix_or_show_unused_code.py +16 -14
- deadcode/actions/get_unused_names_error_message.py +6 -6
- deadcode/actions/merge_overlaping_file_parts.py +2 -7
- deadcode/actions/parse_abstract_syntax_tree.py +1 -1
- deadcode/actions/parse_arguments.py +87 -87
- deadcode/actions/remove_file_parts_from_content.py +36 -19
- deadcode/cli.py +3 -3
- deadcode/constants.py +36 -36
- deadcode/data_types.py +1 -1
- deadcode/utils/add_colors_to_diff.py +7 -7
- deadcode/{tests/base.py → utils/base_test_case.py} +18 -18
- deadcode/utils/fix_indent.py +62 -29
- deadcode/utils/flatten_lists.py +2 -2
- deadcode/utils/nested_scopes.py +2 -2
- deadcode/utils/print_ast.py +1 -1
- deadcode/visitor/code_item.py +15 -28
- deadcode/visitor/dead_code_visitor.py +62 -65
- deadcode/visitor/ignore.py +29 -29
- deadcode/visitor/lines.py +3 -3
- deadcode/visitor/noqa.py +33 -33
- deadcode/visitor/utils.py +1 -1
- {deadcode-2.3.0.dist-info → deadcode-2.3.1.dist-info}/METADATA +26 -9
- deadcode-2.3.1.dist-info/RECORD +32 -0
- {deadcode-2.3.0.dist-info → deadcode-2.3.1.dist-info}/WHEEL +1 -1
- black/action/main.py +0 -176
- black/docs/conf.py +0 -218
- black/gallery/gallery.py +0 -294
- black/profiling/dict_big.py +0 -8001
- black/profiling/dict_huge.py +0 -41440
- black/profiling/list_big.py +0 -4000
- black/profiling/list_huge.py +0 -22431
- black/profiling/mix_big.py +0 -1002
- black/profiling/mix_huge.py +0 -7692
- black/profiling/mix_small.py +0 -102
- black/scripts/__init__.py +0 -0
- black/scripts/check_pre_commit_rev_in_example.py +0 -54
- black/scripts/check_version_in_basics_example.py +0 -48
- black/scripts/diff_shades_gha_helper.py +0 -236
- black/scripts/fuzz.py +0 -92
- black/scripts/generate_schema.py +0 -74
- black/scripts/make_width_table.py +0 -66
- black/scripts/migrate-black.py +0 -96
- black/scripts/release.py +0 -245
- black/scripts/release_tests.py +0 -69
- black/src/black/__init__.py +0 -1605
- black/src/black/__main__.py +0 -3
- black/src/black/_width_table.py +0 -478
- black/src/black/brackets.py +0 -382
- black/src/black/cache.py +0 -150
- black/src/black/comments.py +0 -415
- black/src/black/concurrency.py +0 -190
- black/src/black/const.py +0 -4
- black/src/black/debug.py +0 -54
- black/src/black/files.py +0 -433
- black/src/black/handle_ipynb_magics.py +0 -452
- black/src/black/linegen.py +0 -1745
- black/src/black/lines.py +0 -1073
- black/src/black/mode.py +0 -265
- black/src/black/nodes.py +0 -1007
- black/src/black/numerics.py +0 -61
- black/src/black/output.py +0 -122
- black/src/black/parsing.py +0 -244
- black/src/black/ranges.py +0 -521
- black/src/black/report.py +0 -107
- black/src/black/resources/__init__.py +0 -0
- black/src/black/rusty.py +0 -28
- black/src/black/schema.py +0 -20
- black/src/black/strings.py +0 -325
- black/src/black/trans.py +0 -2534
- black/src/blackd/__init__.py +0 -259
- black/src/blackd/__main__.py +0 -3
- black/src/blackd/middlewares.py +0 -45
- black/src/blib2to3/__init__.py +0 -1
- black/src/blib2to3/pgen2/__init__.py +0 -4
- black/src/blib2to3/pgen2/conv.py +0 -256
- black/src/blib2to3/pgen2/driver.py +0 -316
- black/src/blib2to3/pgen2/grammar.py +0 -227
- black/src/blib2to3/pgen2/literals.py +0 -66
- black/src/blib2to3/pgen2/parse.py +0 -411
- black/src/blib2to3/pgen2/pgen.py +0 -428
- black/src/blib2to3/pgen2/token.py +0 -88
- black/src/blib2to3/pgen2/tokenize.py +0 -698
- black/src/blib2to3/pygram.py +0 -200
- black/src/blib2to3/pytree.py +0 -986
- black/tests/__init__.py +0 -0
- black/tests/conftest.py +0 -28
- black/tests/data/cases/allow_empty_first_line.py +0 -166
- black/tests/data/cases/async_stmts.py +0 -27
- black/tests/data/cases/attribute_access_on_number_literals.py +0 -47
- black/tests/data/cases/beginning_backslash.py +0 -12
- black/tests/data/cases/bracketmatch.py +0 -15
- black/tests/data/cases/bytes_docstring.py +0 -34
- black/tests/data/cases/class_blank_parentheses.py +0 -59
- black/tests/data/cases/class_methods_new_line.py +0 -270
- black/tests/data/cases/collections.py +0 -174
- black/tests/data/cases/comment_after_escaped_newline.py +0 -18
- black/tests/data/cases/comment_type_hint.py +0 -3
- black/tests/data/cases/comments.py +0 -96
- black/tests/data/cases/comments2.py +0 -344
- black/tests/data/cases/comments3.py +0 -48
- black/tests/data/cases/comments4.py +0 -94
- black/tests/data/cases/comments5.py +0 -70
- black/tests/data/cases/comments6.py +0 -118
- black/tests/data/cases/comments8.py +0 -15
- black/tests/data/cases/comments9.py +0 -305
- black/tests/data/cases/comments_in_blocks.py +0 -111
- black/tests/data/cases/comments_in_double_parens.py +0 -113
- black/tests/data/cases/comments_non_breaking_space.py +0 -44
- black/tests/data/cases/composition.py +0 -181
- black/tests/data/cases/composition_no_trailing_comma.py +0 -367
- black/tests/data/cases/conditional_expression.py +0 -204
- black/tests/data/cases/context_managers_38.py +0 -55
- black/tests/data/cases/context_managers_39.py +0 -175
- black/tests/data/cases/context_managers_autodetect_310.py +0 -36
- black/tests/data/cases/context_managers_autodetect_311.py +0 -38
- black/tests/data/cases/context_managers_autodetect_38.py +0 -46
- black/tests/data/cases/context_managers_autodetect_39.py +0 -35
- black/tests/data/cases/docstring.py +0 -457
- black/tests/data/cases/docstring_newline_preview.py +0 -4
- black/tests/data/cases/docstring_no_extra_empty_line_before_eof.py +0 -4
- black/tests/data/cases/docstring_no_string_normalization.py +0 -250
- black/tests/data/cases/docstring_preview.py +0 -104
- black/tests/data/cases/dummy_implementations.py +0 -144
- black/tests/data/cases/empty_lines.py +0 -187
- black/tests/data/cases/expression.py +0 -630
- black/tests/data/cases/f_docstring.py +0 -20
- black/tests/data/cases/fmtonoff.py +0 -409
- black/tests/data/cases/fmtonoff2.py +0 -40
- black/tests/data/cases/fmtonoff3.py +0 -35
- black/tests/data/cases/fmtonoff4.py +0 -36
- black/tests/data/cases/fmtonoff5.py +0 -175
- black/tests/data/cases/fmtpass_imports.py +0 -19
- black/tests/data/cases/fmtskip.py +0 -3
- black/tests/data/cases/fmtskip2.py +0 -20
- black/tests/data/cases/fmtskip3.py +0 -20
- black/tests/data/cases/fmtskip4.py +0 -13
- black/tests/data/cases/fmtskip5.py +0 -22
- black/tests/data/cases/fmtskip6.py +0 -13
- black/tests/data/cases/fmtskip7.py +0 -11
- black/tests/data/cases/fmtskip8.py +0 -62
- black/tests/data/cases/fmtskip9.py +0 -9
- black/tests/data/cases/form_feeds.py +0 -226
- black/tests/data/cases/fstring.py +0 -25
- black/tests/data/cases/funcdef_return_type_trailing_comma.py +0 -301
- black/tests/data/cases/function.py +0 -244
- black/tests/data/cases/function2.py +0 -121
- black/tests/data/cases/function_trailing_comma.py +0 -178
- black/tests/data/cases/ignore_pyi.py +0 -42
- black/tests/data/cases/import_spacing.py +0 -118
- black/tests/data/cases/is_simple_lookup_for_doublestar_expression.py +0 -14
- black/tests/data/cases/keep_newline_after_match.py +0 -41
- black/tests/data/cases/line_ranges_basic.py +0 -107
- black/tests/data/cases/line_ranges_diff_edge_case.py +0 -28
- black/tests/data/cases/line_ranges_exceeding_end.py +0 -36
- black/tests/data/cases/line_ranges_fmt_off.py +0 -49
- black/tests/data/cases/line_ranges_fmt_off_decorator.py +0 -47
- black/tests/data/cases/line_ranges_fmt_off_overlap.py +0 -37
- black/tests/data/cases/line_ranges_imports.py +0 -9
- black/tests/data/cases/line_ranges_indentation.py +0 -27
- black/tests/data/cases/line_ranges_outside_source.py +0 -7
- black/tests/data/cases/line_ranges_two_passes.py +0 -27
- black/tests/data/cases/line_ranges_unwrapping.py +0 -25
- black/tests/data/cases/linelength6.py +0 -6
- black/tests/data/cases/long_strings_flag_disabled.py +0 -296
- black/tests/data/cases/module_docstring_1.py +0 -25
- black/tests/data/cases/module_docstring_2.py +0 -70
- black/tests/data/cases/module_docstring_3.py +0 -7
- black/tests/data/cases/module_docstring_4.py +0 -8
- black/tests/data/cases/module_docstring_followed_by_class.py +0 -10
- black/tests/data/cases/module_docstring_followed_by_function.py +0 -10
- black/tests/data/cases/multiline_consecutive_open_parentheses_ignore.py +0 -41
- black/tests/data/cases/nested_stub.py +0 -69
- black/tests/data/cases/no_blank_line_before_docstring.py +0 -66
- black/tests/data/cases/numeric_literals.py +0 -39
- black/tests/data/cases/numeric_literals_skip_underscores.py +0 -19
- black/tests/data/cases/one_element_subscript.py +0 -36
- black/tests/data/cases/parenthesized_context_managers.py +0 -46
- black/tests/data/cases/pattern_matching_complex.py +0 -155
- black/tests/data/cases/pattern_matching_extras.py +0 -102
- black/tests/data/cases/pattern_matching_generic.py +0 -108
- black/tests/data/cases/pattern_matching_long.py +0 -34
- black/tests/data/cases/pattern_matching_simple.py +0 -93
- black/tests/data/cases/pattern_matching_style.py +0 -92
- black/tests/data/cases/pattern_matching_trailing_comma.py +0 -39
- black/tests/data/cases/pattern_matching_with_if_stmt.py +0 -72
- black/tests/data/cases/pep604_union_types_line_breaks.py +0 -188
- black/tests/data/cases/pep_570.py +0 -45
- black/tests/data/cases/pep_572.py +0 -48
- black/tests/data/cases/pep_572_do_not_remove_parens.py +0 -26
- black/tests/data/cases/pep_572_py310.py +0 -16
- black/tests/data/cases/pep_572_py39.py +0 -8
- black/tests/data/cases/pep_572_remove_parens.py +0 -142
- black/tests/data/cases/pep_572_slices.py +0 -6
- black/tests/data/cases/pep_604.py +0 -25
- black/tests/data/cases/pep_646.py +0 -195
- black/tests/data/cases/pep_654.py +0 -54
- black/tests/data/cases/pep_654_style.py +0 -112
- black/tests/data/cases/percent_precedence.py +0 -41
- black/tests/data/cases/power_op_newline.py +0 -11
- black/tests/data/cases/power_op_spacing.py +0 -149
- black/tests/data/cases/power_op_spacing_long.py +0 -96
- black/tests/data/cases/prefer_rhs_split.py +0 -106
- black/tests/data/cases/prefer_rhs_split_reformatted.py +0 -38
- black/tests/data/cases/preview_cantfit.py +0 -94
- black/tests/data/cases/preview_cantfit_string.py +0 -18
- black/tests/data/cases/preview_comments7.py +0 -309
- black/tests/data/cases/preview_format_unicode_escape_seq.py +0 -34
- black/tests/data/cases/preview_hug_parens_with_braces_and_square_brackets.py +0 -347
- black/tests/data/cases/preview_hug_parens_with_braces_and_square_brackets_no_ll1.py +0 -106
- black/tests/data/cases/preview_long_dict_values.py +0 -129
- black/tests/data/cases/preview_long_strings.py +0 -928
- black/tests/data/cases/preview_long_strings__east_asian_width.py +0 -26
- black/tests/data/cases/preview_long_strings__edge_case.py +0 -141
- black/tests/data/cases/preview_long_strings__regression.py +0 -1247
- black/tests/data/cases/preview_long_strings__type_annotations.py +0 -60
- black/tests/data/cases/preview_multiline_strings.py +0 -401
- black/tests/data/cases/preview_return_annotation_brackets_string.py +0 -24
- black/tests/data/cases/py310_pep572.py +0 -13
- black/tests/data/cases/python37.py +0 -62
- black/tests/data/cases/python38.py +0 -42
- black/tests/data/cases/python39.py +0 -30
- black/tests/data/cases/raw_docstring.py +0 -32
- black/tests/data/cases/raw_docstring_no_string_normalization.py +0 -11
- black/tests/data/cases/remove_await_parens.py +0 -195
- black/tests/data/cases/remove_except_parens.py +0 -79
- black/tests/data/cases/remove_for_brackets.py +0 -48
- black/tests/data/cases/remove_newline_after_code_block_open.py +0 -212
- black/tests/data/cases/remove_parens.py +0 -142
- black/tests/data/cases/remove_redundant_parens_in_case_guard.py +0 -114
- black/tests/data/cases/remove_with_brackets.py +0 -120
- black/tests/data/cases/return_annotation_brackets.py +0 -219
- black/tests/data/cases/single_line_format_skip_with_multiple_comments.py +0 -19
- black/tests/data/cases/skip_magic_trailing_comma.py +0 -75
- black/tests/data/cases/slices.py +0 -31
- black/tests/data/cases/split_delimiter_comments.py +0 -51
- black/tests/data/cases/starred_for_target.py +0 -28
- black/tests/data/cases/string_prefixes.py +0 -45
- black/tests/data/cases/stub.py +0 -152
- black/tests/data/cases/torture.py +0 -91
- black/tests/data/cases/trailing_comma.py +0 -55
- black/tests/data/cases/trailing_comma_optional_parens1.py +0 -63
- black/tests/data/cases/trailing_comma_optional_parens2.py +0 -12
- black/tests/data/cases/trailing_comma_optional_parens3.py +0 -21
- black/tests/data/cases/trailing_commas_in_leading_parts.py +0 -88
- black/tests/data/cases/tricky_unicode_symbols.py +0 -9
- black/tests/data/cases/tupleassign.py +0 -23
- black/tests/data/cases/type_aliases.py +0 -30
- black/tests/data/cases/type_comment_syntax_error.py +0 -11
- black/tests/data/cases/type_params.py +0 -58
- black/tests/data/cases/typed_params_trailing_comma.py +0 -24
- black/tests/data/cases/walrus_in_dict.py +0 -9
- black/tests/data/cases/whitespace.py +0 -6
- black/tests/data/gitignore_used_on_multiple_sources/dir1/a.py +0 -0
- black/tests/data/gitignore_used_on_multiple_sources/dir1/b.py +0 -0
- black/tests/data/gitignore_used_on_multiple_sources/dir2/a.py +0 -0
- black/tests/data/gitignore_used_on_multiple_sources/dir2/b.py +0 -0
- black/tests/data/ignore_subfolders_gitignore_tests/a.py +0 -0
- black/tests/data/ignore_subfolders_gitignore_tests/subdir/b.py +0 -0
- black/tests/data/ignore_subfolders_gitignore_tests/subdir/subdir/c.py +0 -0
- black/tests/data/include_exclude_tests/b/.definitely_exclude/a.py +0 -0
- black/tests/data/include_exclude_tests/b/dont_exclude/a.py +0 -0
- black/tests/data/include_exclude_tests/b/exclude/a.py +0 -0
- black/tests/data/invalid_gitignore_tests/a.py +0 -0
- black/tests/data/invalid_nested_gitignore_tests/a/a.py +0 -0
- black/tests/data/invalid_nested_gitignore_tests/a.py +0 -0
- black/tests/data/line_ranges_formatted/basic.py +0 -50
- black/tests/data/line_ranges_formatted/pattern_matching.py +0 -25
- black/tests/data/miscellaneous/async_as_identifier.py +0 -49
- black/tests/data/miscellaneous/blackd_diff.py +0 -6
- black/tests/data/miscellaneous/debug_visitor.py +0 -32
- black/tests/data/miscellaneous/decorators.py +0 -182
- black/tests/data/miscellaneous/force_py36.py +0 -16
- black/tests/data/miscellaneous/force_pyi.py +0 -66
- black/tests/data/miscellaneous/invalid_header.py +0 -2
- black/tests/data/miscellaneous/missing_final_newline.py +0 -3
- black/tests/data/miscellaneous/pattern_matching_invalid.py +0 -18
- black/tests/data/miscellaneous/python2_detection.py +0 -90
- black/tests/data/miscellaneous/string_quotes.py +0 -114
- black/tests/data/nested_gitignore_tests/root/a.py +0 -1
- black/tests/data/nested_gitignore_tests/root/b.py +0 -1
- black/tests/data/nested_gitignore_tests/root/c.py +0 -1
- black/tests/data/nested_gitignore_tests/root/child/a.py +0 -1
- black/tests/data/nested_gitignore_tests/root/child/b.py +0 -1
- black/tests/data/nested_gitignore_tests/root/child/c.py +0 -1
- black/tests/data/nested_gitignore_tests/x.py +0 -0
- black/tests/optional.py +0 -132
- black/tests/test_black.py +0 -2980
- black/tests/test_blackd.py +0 -248
- black/tests/test_docs.py +0 -74
- black/tests/test_format.py +0 -90
- black/tests/test_ipynb.py +0 -517
- black/tests/test_no_ipynb.py +0 -36
- black/tests/test_ranges.py +0 -249
- black/tests/test_schema.py +0 -17
- black/tests/test_trans.py +0 -51
- black/tests/util.py +0 -354
- call_arg_map_to_parameters_poc.py +0 -173
- deadcode/tests/actions/test_find_python_filenames.py +0 -36
- deadcode/tests/actions/test_merge_overlaping_file_parts.py +0 -62
- deadcode/tests/cli_args/test_count.py +0 -0
- deadcode/tests/cli_args/test_dry.py +0 -318
- deadcode/tests/cli_args/test_exclude.py +0 -24
- deadcode/tests/cli_args/test_fix.py +0 -528
- deadcode/tests/cli_args/test_ignore_bodies_if_inherits_from.py +0 -46
- deadcode/tests/cli_args/test_ignore_definitions.py +0 -106
- deadcode/tests/cli_args/test_ignore_definitions_if_inherits_from.py +0 -125
- deadcode/tests/cli_args/test_ignore_names.py +0 -79
- deadcode/tests/cli_args/test_ignore_names_in_files.py +0 -0
- deadcode/tests/cli_args/test_no_color.py +0 -0
- deadcode/tests/cli_args/test_parsing.py +0 -113
- deadcode/tests/cli_args/test_quiet.py +0 -0
- deadcode/tests/cli_args/test_verbose.py +0 -0
- deadcode/tests/code_item/test_code_item.py +0 -16
- deadcode/tests/files/classes.py +0 -15
- deadcode/tests/files/functions.py +0 -21
- deadcode/tests/files/subdir/another_subdir/__init__.py +0 -1
- deadcode/tests/files/subdir/one_more_file.py +0 -2
- deadcode/tests/files/variables.py +0 -8
- deadcode/tests/fix/test_assign.py +0 -92
- deadcode/tests/fix/test_class_def.py +0 -116
- deadcode/tests/fix/test_empty_files.py +0 -36
- deadcode/tests/fix/test_method_def.py +0 -66
- deadcode/tests/fix/test_scope.py +0 -243
- deadcode/tests/fix/test_unreachable_code.py +0 -100
- deadcode/tests/nested_scope/test_nested_scope.py +0 -180
- deadcode/tests/noqa/test_noqa_comments.py +0 -329
- deadcode/tests/test_accurate_usage_detection.py +0 -49
- deadcode/tests/test_deadcode.py +0 -68
- deadcode/tests/test_imports.py +0 -101
- deadcode/tests/test_line_number_detection.py +0 -97
- deadcode/tests/test_output.py +0 -137
- deadcode/tests/test_variable_parsing_from_ast_dump.py +0 -12
- deadcode/tests/utils/test_add_colors_to_diff.py +0 -38
- deadcode/tests/utils/test_fix_indent.py +0 -10
- deadcode-2.3.0.dist-info/RECORD +0 -342
- {deadcode-2.3.0.dist-info → deadcode-2.3.1.dist-info}/entry_points.txt +0 -0
- {deadcode-2.3.0.dist-info → deadcode-2.3.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -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()
|
|
@@ -26,173 +26,173 @@ def parse_arguments(args: Optional[List[str]]) -> Args:
|
|
|
26
26
|
|
|
27
27
|
# Docs: https://docs.python.org/3/library/argparse.html
|
|
28
28
|
parser = argparse.ArgumentParser()
|
|
29
|
-
parser.add_argument(
|
|
29
|
+
parser.add_argument('paths', help='Paths where to search for python files', nargs='+')
|
|
30
30
|
parser.add_argument(
|
|
31
|
-
|
|
32
|
-
help=
|
|
33
|
-
action=
|
|
31
|
+
'--fix',
|
|
32
|
+
help='Automatically remove detected unused code expressions from the code base.',
|
|
33
|
+
action='store_true',
|
|
34
34
|
default=False,
|
|
35
35
|
)
|
|
36
36
|
parser.add_argument(
|
|
37
|
-
|
|
38
|
-
help=
|
|
39
|
-
nargs=
|
|
40
|
-
action=
|
|
41
|
-
default=[[
|
|
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
42
|
type=str,
|
|
43
43
|
)
|
|
44
44
|
parser.add_argument(
|
|
45
|
-
|
|
46
|
-
help=
|
|
47
|
-
nargs=
|
|
48
|
-
action=
|
|
45
|
+
'--exclude',
|
|
46
|
+
help='Filenames (or path expressions), which will be completely skipped without being analysed.',
|
|
47
|
+
nargs='*',
|
|
48
|
+
action='append',
|
|
49
49
|
default=[],
|
|
50
50
|
type=str,
|
|
51
51
|
)
|
|
52
52
|
parser.add_argument(
|
|
53
|
-
|
|
53
|
+
'--ignore-names',
|
|
54
54
|
help=(
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
'Removes provided list of names from the output. '
|
|
56
|
+
'Regexp expressions to match multiple names can also be provided.'
|
|
57
57
|
),
|
|
58
|
-
nargs=
|
|
59
|
-
action=
|
|
58
|
+
nargs='*',
|
|
59
|
+
action='append',
|
|
60
60
|
default=[],
|
|
61
61
|
type=str,
|
|
62
62
|
)
|
|
63
63
|
parser.add_argument(
|
|
64
|
-
|
|
65
|
-
help=
|
|
66
|
-
nargs=
|
|
67
|
-
action=
|
|
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
68
|
default=[],
|
|
69
69
|
type=str,
|
|
70
70
|
)
|
|
71
71
|
parser.add_argument(
|
|
72
|
-
|
|
73
|
-
help=
|
|
74
|
-
nargs=
|
|
75
|
-
action=
|
|
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
76
|
default=[],
|
|
77
77
|
type=str,
|
|
78
78
|
)
|
|
79
79
|
parser.add_argument(
|
|
80
|
-
|
|
81
|
-
help=
|
|
82
|
-
nargs=
|
|
83
|
-
action=
|
|
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
84
|
default=[],
|
|
85
85
|
type=str,
|
|
86
86
|
)
|
|
87
87
|
parser.add_argument(
|
|
88
|
-
|
|
88
|
+
'--ignore-definitions',
|
|
89
89
|
help=(
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
'Ignores definition (including name and body) if a '
|
|
91
|
+
'name of an expression matches any of the provided ones.'
|
|
92
92
|
),
|
|
93
|
-
nargs=
|
|
94
|
-
action=
|
|
93
|
+
nargs='*',
|
|
94
|
+
action='append',
|
|
95
95
|
default=[],
|
|
96
96
|
type=str,
|
|
97
97
|
)
|
|
98
98
|
parser.add_argument(
|
|
99
|
-
|
|
99
|
+
'--ignore-definitions-if-inherits-from',
|
|
100
100
|
help=(
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
'Ignores definition (including name and body) of a class if '
|
|
102
|
+
'it inherits from any of the provided class names.'
|
|
103
103
|
),
|
|
104
|
-
nargs=
|
|
105
|
-
action=
|
|
104
|
+
nargs='*',
|
|
105
|
+
action='append',
|
|
106
106
|
default=[],
|
|
107
107
|
type=str,
|
|
108
108
|
)
|
|
109
109
|
parser.add_argument(
|
|
110
|
-
|
|
110
|
+
'--ignore-definitions-if-decorated-with',
|
|
111
111
|
help=(
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
'Ignores definition (including name and body) of an expression, '
|
|
113
|
+
'which is decorated with any of the provided decorator names.'
|
|
114
114
|
),
|
|
115
|
-
nargs=
|
|
116
|
-
action=
|
|
115
|
+
nargs='*',
|
|
116
|
+
action='append',
|
|
117
117
|
default=[],
|
|
118
118
|
type=str,
|
|
119
119
|
)
|
|
120
120
|
|
|
121
121
|
parser.add_argument(
|
|
122
|
-
|
|
123
|
-
help=
|
|
124
|
-
nargs=
|
|
125
|
-
action=
|
|
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
126
|
default=[],
|
|
127
127
|
type=str,
|
|
128
128
|
)
|
|
129
129
|
parser.add_argument(
|
|
130
|
-
|
|
131
|
-
help=
|
|
132
|
-
nargs=
|
|
133
|
-
action=
|
|
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
134
|
default=[],
|
|
135
135
|
type=str,
|
|
136
136
|
)
|
|
137
137
|
|
|
138
138
|
parser.add_argument(
|
|
139
|
-
|
|
140
|
-
help=
|
|
141
|
-
nargs=
|
|
142
|
-
action=
|
|
139
|
+
'--ignore-names-if-inherits-from',
|
|
140
|
+
help='Ignores names of classes, which inherit from provided class names.',
|
|
141
|
+
nargs='*',
|
|
142
|
+
action='append',
|
|
143
143
|
default=[],
|
|
144
144
|
type=str,
|
|
145
145
|
)
|
|
146
146
|
parser.add_argument(
|
|
147
|
-
|
|
148
|
-
help=
|
|
149
|
-
nargs=
|
|
150
|
-
action=
|
|
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
151
|
default=[],
|
|
152
152
|
type=str,
|
|
153
153
|
)
|
|
154
154
|
|
|
155
155
|
parser.add_argument(
|
|
156
|
-
|
|
157
|
-
help=
|
|
158
|
-
nargs=
|
|
159
|
-
action=
|
|
156
|
+
'--ignore-names-in-files',
|
|
157
|
+
help='Ignores unused names in files, which filenames match provided path expressions.',
|
|
158
|
+
nargs='*',
|
|
159
|
+
action='append',
|
|
160
160
|
default=[],
|
|
161
161
|
type=str,
|
|
162
162
|
)
|
|
163
163
|
|
|
164
164
|
parser.add_argument(
|
|
165
|
-
|
|
166
|
-
help=
|
|
167
|
-
action=
|
|
165
|
+
'--no-color',
|
|
166
|
+
help='Turn off colors in the output',
|
|
167
|
+
action='store_true',
|
|
168
168
|
default=False,
|
|
169
169
|
)
|
|
170
170
|
|
|
171
171
|
parser.add_argument(
|
|
172
|
-
|
|
173
|
-
help=
|
|
174
|
-
action=
|
|
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
175
|
default=False,
|
|
176
176
|
)
|
|
177
177
|
|
|
178
178
|
parser.add_argument(
|
|
179
|
-
|
|
180
|
-
help=
|
|
181
|
-
action=
|
|
179
|
+
'--count',
|
|
180
|
+
help='Provides the count of the detected unused names instead of printing them all out.',
|
|
181
|
+
action='store_true',
|
|
182
182
|
default=False,
|
|
183
183
|
)
|
|
184
184
|
parser.add_argument(
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
help=
|
|
188
|
-
action=
|
|
185
|
+
'-v',
|
|
186
|
+
'--verbose',
|
|
187
|
+
help='Shows logs useful for debuging',
|
|
188
|
+
action='store_true',
|
|
189
189
|
default=False,
|
|
190
190
|
)
|
|
191
191
|
|
|
192
192
|
parsed_args = parser.parse_args(args).__dict__
|
|
193
193
|
|
|
194
194
|
for arg_name, arg_value in parsed_args.items():
|
|
195
|
-
if isinstance(arg_value, list) and arg_name !=
|
|
195
|
+
if isinstance(arg_value, list) and arg_name != 'paths':
|
|
196
196
|
parsed_args[arg_name] = flatten_lists_of_comma_separated_values(parsed_args.get(arg_name))
|
|
197
197
|
|
|
198
198
|
# Extend the Args with the values provided in the pyproject.toml
|
|
@@ -201,12 +201,12 @@ def parse_arguments(args: Optional[List[str]]) -> Args:
|
|
|
201
201
|
parsed_args[key].extend(item)
|
|
202
202
|
|
|
203
203
|
# Show changes for only provided files instead of all
|
|
204
|
-
if len(parsed_args[
|
|
205
|
-
parsed_args[
|
|
204
|
+
if len(parsed_args['dry']) > 1 or '--dry' not in args:
|
|
205
|
+
parsed_args['dry'].remove('__all_files__')
|
|
206
206
|
|
|
207
207
|
# Do not fix if dry option is provided:
|
|
208
|
-
if parsed_args[
|
|
209
|
-
parsed_args[
|
|
208
|
+
if parsed_args['dry']:
|
|
209
|
+
parsed_args['fix'] = False
|
|
210
210
|
|
|
211
211
|
return Args(**parsed_args)
|
|
212
212
|
|
|
@@ -217,13 +217,13 @@ def parse_pyproject_toml() -> Dict[str, Any]:
|
|
|
217
217
|
If parsing fails, will raise a tomllib.TOMLDecodeError.
|
|
218
218
|
Copied from: https://github.com/psf/black/blob/01b8d3d4095ebdb91d0d39012a517931625c63cb/src/black/files.py#LL113C15-L113C15
|
|
219
219
|
"""
|
|
220
|
-
pyproject_toml_filename =
|
|
220
|
+
pyproject_toml_filename = 'pyproject.toml'
|
|
221
221
|
if not os.path.isfile(pyproject_toml_filename):
|
|
222
222
|
return {}
|
|
223
223
|
|
|
224
|
-
with open(pyproject_toml_filename,
|
|
224
|
+
with open(pyproject_toml_filename, 'rb') as f:
|
|
225
225
|
pyproject_toml = tomllib.load(f)
|
|
226
226
|
|
|
227
|
-
config: Dict[str, Any] = pyproject_toml.get(
|
|
228
|
-
config = {k.replace(
|
|
227
|
+
config: Dict[str, Any] = pyproject_toml.get('tool', {}).get('deadcode', {})
|
|
228
|
+
config = {k.replace('--', '').replace('-', '_'): v for k, v in config.items()}
|
|
229
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
|
deadcode/cli.py
CHANGED
|
@@ -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()
|