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.
Files changed (348) hide show
  1. {deadcode-2.3.0 → deadcode-2.3.1}/PKG-INFO +26 -9
  2. {deadcode-2.3.0 → deadcode-2.3.1}/README.md +13 -4
  3. {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/actions/find_python_filenames.py +6 -6
  4. {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/actions/fix_or_show_unused_code.py +16 -14
  5. {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/actions/get_unused_names_error_message.py +6 -6
  6. {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/actions/merge_overlaping_file_parts.py +2 -7
  7. {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/actions/parse_abstract_syntax_tree.py +1 -1
  8. deadcode-2.3.1/deadcode/actions/parse_arguments.py +229 -0
  9. {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/actions/remove_file_parts_from_content.py +36 -19
  10. {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/cli.py +3 -3
  11. deadcode-2.3.1/deadcode/constants.py +49 -0
  12. {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/data_types.py +1 -1
  13. deadcode-2.3.1/deadcode/utils/add_colors_to_diff.py +10 -0
  14. deadcode-2.3.0/deadcode/tests/base.py → deadcode-2.3.1/deadcode/utils/base_test_case.py +18 -18
  15. deadcode-2.3.1/deadcode/utils/fix_indent.py +69 -0
  16. {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/utils/flatten_lists.py +2 -2
  17. {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/utils/nested_scopes.py +2 -2
  18. deadcode-2.3.1/deadcode/utils/print_ast.py +5 -0
  19. {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/visitor/code_item.py +15 -28
  20. {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/visitor/dead_code_visitor.py +62 -65
  21. {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/visitor/ignore.py +29 -29
  22. {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/visitor/lines.py +3 -3
  23. {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/visitor/noqa.py +33 -33
  24. {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/visitor/utils.py +1 -1
  25. deadcode-2.3.1/pyproject.toml +208 -0
  26. deadcode-2.3.0/black/action/main.py +0 -176
  27. deadcode-2.3.0/black/docs/conf.py +0 -218
  28. deadcode-2.3.0/black/gallery/gallery.py +0 -294
  29. deadcode-2.3.0/black/profiling/dict_big.py +0 -8001
  30. deadcode-2.3.0/black/profiling/dict_huge.py +0 -41440
  31. deadcode-2.3.0/black/profiling/list_big.py +0 -4000
  32. deadcode-2.3.0/black/profiling/list_huge.py +0 -22431
  33. deadcode-2.3.0/black/profiling/mix_big.py +0 -1002
  34. deadcode-2.3.0/black/profiling/mix_huge.py +0 -7692
  35. deadcode-2.3.0/black/profiling/mix_small.py +0 -102
  36. deadcode-2.3.0/black/scripts/check_pre_commit_rev_in_example.py +0 -54
  37. deadcode-2.3.0/black/scripts/check_version_in_basics_example.py +0 -48
  38. deadcode-2.3.0/black/scripts/diff_shades_gha_helper.py +0 -236
  39. deadcode-2.3.0/black/scripts/fuzz.py +0 -92
  40. deadcode-2.3.0/black/scripts/generate_schema.py +0 -74
  41. deadcode-2.3.0/black/scripts/make_width_table.py +0 -66
  42. deadcode-2.3.0/black/scripts/migrate-black.py +0 -96
  43. deadcode-2.3.0/black/scripts/release.py +0 -245
  44. deadcode-2.3.0/black/scripts/release_tests.py +0 -69
  45. deadcode-2.3.0/black/src/black/__init__.py +0 -1605
  46. deadcode-2.3.0/black/src/black/__main__.py +0 -3
  47. deadcode-2.3.0/black/src/black/_width_table.py +0 -478
  48. deadcode-2.3.0/black/src/black/brackets.py +0 -382
  49. deadcode-2.3.0/black/src/black/cache.py +0 -150
  50. deadcode-2.3.0/black/src/black/comments.py +0 -415
  51. deadcode-2.3.0/black/src/black/concurrency.py +0 -190
  52. deadcode-2.3.0/black/src/black/const.py +0 -4
  53. deadcode-2.3.0/black/src/black/debug.py +0 -54
  54. deadcode-2.3.0/black/src/black/files.py +0 -433
  55. deadcode-2.3.0/black/src/black/handle_ipynb_magics.py +0 -452
  56. deadcode-2.3.0/black/src/black/linegen.py +0 -1745
  57. deadcode-2.3.0/black/src/black/lines.py +0 -1073
  58. deadcode-2.3.0/black/src/black/mode.py +0 -265
  59. deadcode-2.3.0/black/src/black/nodes.py +0 -1007
  60. deadcode-2.3.0/black/src/black/numerics.py +0 -61
  61. deadcode-2.3.0/black/src/black/output.py +0 -122
  62. deadcode-2.3.0/black/src/black/parsing.py +0 -244
  63. deadcode-2.3.0/black/src/black/ranges.py +0 -521
  64. deadcode-2.3.0/black/src/black/report.py +0 -107
  65. deadcode-2.3.0/black/src/black/rusty.py +0 -28
  66. deadcode-2.3.0/black/src/black/schema.py +0 -20
  67. deadcode-2.3.0/black/src/black/strings.py +0 -325
  68. deadcode-2.3.0/black/src/black/trans.py +0 -2534
  69. deadcode-2.3.0/black/src/blackd/__init__.py +0 -259
  70. deadcode-2.3.0/black/src/blackd/__main__.py +0 -3
  71. deadcode-2.3.0/black/src/blackd/middlewares.py +0 -45
  72. deadcode-2.3.0/black/src/blib2to3/__init__.py +0 -1
  73. deadcode-2.3.0/black/src/blib2to3/pgen2/__init__.py +0 -4
  74. deadcode-2.3.0/black/src/blib2to3/pgen2/conv.py +0 -256
  75. deadcode-2.3.0/black/src/blib2to3/pgen2/driver.py +0 -316
  76. deadcode-2.3.0/black/src/blib2to3/pgen2/grammar.py +0 -227
  77. deadcode-2.3.0/black/src/blib2to3/pgen2/literals.py +0 -66
  78. deadcode-2.3.0/black/src/blib2to3/pgen2/parse.py +0 -411
  79. deadcode-2.3.0/black/src/blib2to3/pgen2/pgen.py +0 -428
  80. deadcode-2.3.0/black/src/blib2to3/pgen2/token.py +0 -88
  81. deadcode-2.3.0/black/src/blib2to3/pgen2/tokenize.py +0 -698
  82. deadcode-2.3.0/black/src/blib2to3/pygram.py +0 -200
  83. deadcode-2.3.0/black/src/blib2to3/pytree.py +0 -986
  84. deadcode-2.3.0/black/tests/conftest.py +0 -28
  85. deadcode-2.3.0/black/tests/data/cases/allow_empty_first_line.py +0 -166
  86. deadcode-2.3.0/black/tests/data/cases/async_stmts.py +0 -27
  87. deadcode-2.3.0/black/tests/data/cases/attribute_access_on_number_literals.py +0 -47
  88. deadcode-2.3.0/black/tests/data/cases/beginning_backslash.py +0 -12
  89. deadcode-2.3.0/black/tests/data/cases/bracketmatch.py +0 -15
  90. deadcode-2.3.0/black/tests/data/cases/bytes_docstring.py +0 -34
  91. deadcode-2.3.0/black/tests/data/cases/class_blank_parentheses.py +0 -59
  92. deadcode-2.3.0/black/tests/data/cases/class_methods_new_line.py +0 -270
  93. deadcode-2.3.0/black/tests/data/cases/collections.py +0 -174
  94. deadcode-2.3.0/black/tests/data/cases/comment_after_escaped_newline.py +0 -18
  95. deadcode-2.3.0/black/tests/data/cases/comment_type_hint.py +0 -3
  96. deadcode-2.3.0/black/tests/data/cases/comments.py +0 -96
  97. deadcode-2.3.0/black/tests/data/cases/comments2.py +0 -344
  98. deadcode-2.3.0/black/tests/data/cases/comments3.py +0 -48
  99. deadcode-2.3.0/black/tests/data/cases/comments4.py +0 -94
  100. deadcode-2.3.0/black/tests/data/cases/comments5.py +0 -70
  101. deadcode-2.3.0/black/tests/data/cases/comments6.py +0 -118
  102. deadcode-2.3.0/black/tests/data/cases/comments8.py +0 -15
  103. deadcode-2.3.0/black/tests/data/cases/comments9.py +0 -305
  104. deadcode-2.3.0/black/tests/data/cases/comments_in_blocks.py +0 -111
  105. deadcode-2.3.0/black/tests/data/cases/comments_in_double_parens.py +0 -113
  106. deadcode-2.3.0/black/tests/data/cases/comments_non_breaking_space.py +0 -44
  107. deadcode-2.3.0/black/tests/data/cases/composition.py +0 -181
  108. deadcode-2.3.0/black/tests/data/cases/composition_no_trailing_comma.py +0 -367
  109. deadcode-2.3.0/black/tests/data/cases/conditional_expression.py +0 -204
  110. deadcode-2.3.0/black/tests/data/cases/context_managers_38.py +0 -55
  111. deadcode-2.3.0/black/tests/data/cases/context_managers_39.py +0 -175
  112. deadcode-2.3.0/black/tests/data/cases/context_managers_autodetect_310.py +0 -36
  113. deadcode-2.3.0/black/tests/data/cases/context_managers_autodetect_311.py +0 -38
  114. deadcode-2.3.0/black/tests/data/cases/context_managers_autodetect_38.py +0 -46
  115. deadcode-2.3.0/black/tests/data/cases/context_managers_autodetect_39.py +0 -35
  116. deadcode-2.3.0/black/tests/data/cases/docstring.py +0 -457
  117. deadcode-2.3.0/black/tests/data/cases/docstring_newline_preview.py +0 -4
  118. deadcode-2.3.0/black/tests/data/cases/docstring_no_extra_empty_line_before_eof.py +0 -4
  119. deadcode-2.3.0/black/tests/data/cases/docstring_no_string_normalization.py +0 -250
  120. deadcode-2.3.0/black/tests/data/cases/docstring_preview.py +0 -104
  121. deadcode-2.3.0/black/tests/data/cases/dummy_implementations.py +0 -144
  122. deadcode-2.3.0/black/tests/data/cases/empty_lines.py +0 -187
  123. deadcode-2.3.0/black/tests/data/cases/expression.py +0 -630
  124. deadcode-2.3.0/black/tests/data/cases/f_docstring.py +0 -20
  125. deadcode-2.3.0/black/tests/data/cases/fmtonoff.py +0 -409
  126. deadcode-2.3.0/black/tests/data/cases/fmtonoff2.py +0 -40
  127. deadcode-2.3.0/black/tests/data/cases/fmtonoff3.py +0 -35
  128. deadcode-2.3.0/black/tests/data/cases/fmtonoff4.py +0 -36
  129. deadcode-2.3.0/black/tests/data/cases/fmtonoff5.py +0 -175
  130. deadcode-2.3.0/black/tests/data/cases/fmtpass_imports.py +0 -19
  131. deadcode-2.3.0/black/tests/data/cases/fmtskip.py +0 -3
  132. deadcode-2.3.0/black/tests/data/cases/fmtskip2.py +0 -20
  133. deadcode-2.3.0/black/tests/data/cases/fmtskip3.py +0 -20
  134. deadcode-2.3.0/black/tests/data/cases/fmtskip4.py +0 -13
  135. deadcode-2.3.0/black/tests/data/cases/fmtskip5.py +0 -22
  136. deadcode-2.3.0/black/tests/data/cases/fmtskip6.py +0 -13
  137. deadcode-2.3.0/black/tests/data/cases/fmtskip7.py +0 -11
  138. deadcode-2.3.0/black/tests/data/cases/fmtskip8.py +0 -62
  139. deadcode-2.3.0/black/tests/data/cases/fmtskip9.py +0 -9
  140. deadcode-2.3.0/black/tests/data/cases/form_feeds.py +0 -226
  141. deadcode-2.3.0/black/tests/data/cases/fstring.py +0 -25
  142. deadcode-2.3.0/black/tests/data/cases/funcdef_return_type_trailing_comma.py +0 -301
  143. deadcode-2.3.0/black/tests/data/cases/function.py +0 -244
  144. deadcode-2.3.0/black/tests/data/cases/function2.py +0 -121
  145. deadcode-2.3.0/black/tests/data/cases/function_trailing_comma.py +0 -178
  146. deadcode-2.3.0/black/tests/data/cases/ignore_pyi.py +0 -42
  147. deadcode-2.3.0/black/tests/data/cases/import_spacing.py +0 -118
  148. deadcode-2.3.0/black/tests/data/cases/is_simple_lookup_for_doublestar_expression.py +0 -14
  149. deadcode-2.3.0/black/tests/data/cases/keep_newline_after_match.py +0 -41
  150. deadcode-2.3.0/black/tests/data/cases/line_ranges_basic.py +0 -107
  151. deadcode-2.3.0/black/tests/data/cases/line_ranges_diff_edge_case.py +0 -28
  152. deadcode-2.3.0/black/tests/data/cases/line_ranges_exceeding_end.py +0 -36
  153. deadcode-2.3.0/black/tests/data/cases/line_ranges_fmt_off.py +0 -49
  154. deadcode-2.3.0/black/tests/data/cases/line_ranges_fmt_off_decorator.py +0 -47
  155. deadcode-2.3.0/black/tests/data/cases/line_ranges_fmt_off_overlap.py +0 -37
  156. deadcode-2.3.0/black/tests/data/cases/line_ranges_imports.py +0 -9
  157. deadcode-2.3.0/black/tests/data/cases/line_ranges_indentation.py +0 -27
  158. deadcode-2.3.0/black/tests/data/cases/line_ranges_outside_source.py +0 -7
  159. deadcode-2.3.0/black/tests/data/cases/line_ranges_two_passes.py +0 -27
  160. deadcode-2.3.0/black/tests/data/cases/line_ranges_unwrapping.py +0 -25
  161. deadcode-2.3.0/black/tests/data/cases/linelength6.py +0 -6
  162. deadcode-2.3.0/black/tests/data/cases/long_strings_flag_disabled.py +0 -296
  163. deadcode-2.3.0/black/tests/data/cases/module_docstring_1.py +0 -25
  164. deadcode-2.3.0/black/tests/data/cases/module_docstring_2.py +0 -70
  165. deadcode-2.3.0/black/tests/data/cases/module_docstring_3.py +0 -7
  166. deadcode-2.3.0/black/tests/data/cases/module_docstring_4.py +0 -8
  167. deadcode-2.3.0/black/tests/data/cases/module_docstring_followed_by_class.py +0 -10
  168. deadcode-2.3.0/black/tests/data/cases/module_docstring_followed_by_function.py +0 -10
  169. deadcode-2.3.0/black/tests/data/cases/multiline_consecutive_open_parentheses_ignore.py +0 -41
  170. deadcode-2.3.0/black/tests/data/cases/nested_stub.py +0 -69
  171. deadcode-2.3.0/black/tests/data/cases/no_blank_line_before_docstring.py +0 -66
  172. deadcode-2.3.0/black/tests/data/cases/numeric_literals.py +0 -39
  173. deadcode-2.3.0/black/tests/data/cases/numeric_literals_skip_underscores.py +0 -19
  174. deadcode-2.3.0/black/tests/data/cases/one_element_subscript.py +0 -36
  175. deadcode-2.3.0/black/tests/data/cases/parenthesized_context_managers.py +0 -46
  176. deadcode-2.3.0/black/tests/data/cases/pattern_matching_complex.py +0 -155
  177. deadcode-2.3.0/black/tests/data/cases/pattern_matching_extras.py +0 -102
  178. deadcode-2.3.0/black/tests/data/cases/pattern_matching_generic.py +0 -108
  179. deadcode-2.3.0/black/tests/data/cases/pattern_matching_long.py +0 -34
  180. deadcode-2.3.0/black/tests/data/cases/pattern_matching_simple.py +0 -93
  181. deadcode-2.3.0/black/tests/data/cases/pattern_matching_style.py +0 -92
  182. deadcode-2.3.0/black/tests/data/cases/pattern_matching_trailing_comma.py +0 -39
  183. deadcode-2.3.0/black/tests/data/cases/pattern_matching_with_if_stmt.py +0 -72
  184. deadcode-2.3.0/black/tests/data/cases/pep604_union_types_line_breaks.py +0 -188
  185. deadcode-2.3.0/black/tests/data/cases/pep_570.py +0 -45
  186. deadcode-2.3.0/black/tests/data/cases/pep_572.py +0 -48
  187. deadcode-2.3.0/black/tests/data/cases/pep_572_do_not_remove_parens.py +0 -26
  188. deadcode-2.3.0/black/tests/data/cases/pep_572_py310.py +0 -16
  189. deadcode-2.3.0/black/tests/data/cases/pep_572_py39.py +0 -8
  190. deadcode-2.3.0/black/tests/data/cases/pep_572_remove_parens.py +0 -142
  191. deadcode-2.3.0/black/tests/data/cases/pep_572_slices.py +0 -6
  192. deadcode-2.3.0/black/tests/data/cases/pep_604.py +0 -25
  193. deadcode-2.3.0/black/tests/data/cases/pep_646.py +0 -195
  194. deadcode-2.3.0/black/tests/data/cases/pep_654.py +0 -54
  195. deadcode-2.3.0/black/tests/data/cases/pep_654_style.py +0 -112
  196. deadcode-2.3.0/black/tests/data/cases/percent_precedence.py +0 -41
  197. deadcode-2.3.0/black/tests/data/cases/power_op_newline.py +0 -11
  198. deadcode-2.3.0/black/tests/data/cases/power_op_spacing.py +0 -149
  199. deadcode-2.3.0/black/tests/data/cases/power_op_spacing_long.py +0 -96
  200. deadcode-2.3.0/black/tests/data/cases/prefer_rhs_split.py +0 -106
  201. deadcode-2.3.0/black/tests/data/cases/prefer_rhs_split_reformatted.py +0 -38
  202. deadcode-2.3.0/black/tests/data/cases/preview_cantfit.py +0 -94
  203. deadcode-2.3.0/black/tests/data/cases/preview_cantfit_string.py +0 -18
  204. deadcode-2.3.0/black/tests/data/cases/preview_comments7.py +0 -309
  205. deadcode-2.3.0/black/tests/data/cases/preview_format_unicode_escape_seq.py +0 -34
  206. deadcode-2.3.0/black/tests/data/cases/preview_hug_parens_with_braces_and_square_brackets.py +0 -347
  207. deadcode-2.3.0/black/tests/data/cases/preview_hug_parens_with_braces_and_square_brackets_no_ll1.py +0 -106
  208. deadcode-2.3.0/black/tests/data/cases/preview_long_dict_values.py +0 -129
  209. deadcode-2.3.0/black/tests/data/cases/preview_long_strings.py +0 -928
  210. deadcode-2.3.0/black/tests/data/cases/preview_long_strings__east_asian_width.py +0 -26
  211. deadcode-2.3.0/black/tests/data/cases/preview_long_strings__edge_case.py +0 -141
  212. deadcode-2.3.0/black/tests/data/cases/preview_long_strings__regression.py +0 -1247
  213. deadcode-2.3.0/black/tests/data/cases/preview_long_strings__type_annotations.py +0 -60
  214. deadcode-2.3.0/black/tests/data/cases/preview_multiline_strings.py +0 -401
  215. deadcode-2.3.0/black/tests/data/cases/preview_return_annotation_brackets_string.py +0 -24
  216. deadcode-2.3.0/black/tests/data/cases/py310_pep572.py +0 -13
  217. deadcode-2.3.0/black/tests/data/cases/python37.py +0 -62
  218. deadcode-2.3.0/black/tests/data/cases/python38.py +0 -42
  219. deadcode-2.3.0/black/tests/data/cases/python39.py +0 -30
  220. deadcode-2.3.0/black/tests/data/cases/raw_docstring.py +0 -32
  221. deadcode-2.3.0/black/tests/data/cases/raw_docstring_no_string_normalization.py +0 -11
  222. deadcode-2.3.0/black/tests/data/cases/remove_await_parens.py +0 -195
  223. deadcode-2.3.0/black/tests/data/cases/remove_except_parens.py +0 -79
  224. deadcode-2.3.0/black/tests/data/cases/remove_for_brackets.py +0 -48
  225. deadcode-2.3.0/black/tests/data/cases/remove_newline_after_code_block_open.py +0 -212
  226. deadcode-2.3.0/black/tests/data/cases/remove_parens.py +0 -142
  227. deadcode-2.3.0/black/tests/data/cases/remove_redundant_parens_in_case_guard.py +0 -114
  228. deadcode-2.3.0/black/tests/data/cases/remove_with_brackets.py +0 -120
  229. deadcode-2.3.0/black/tests/data/cases/return_annotation_brackets.py +0 -219
  230. deadcode-2.3.0/black/tests/data/cases/single_line_format_skip_with_multiple_comments.py +0 -19
  231. deadcode-2.3.0/black/tests/data/cases/skip_magic_trailing_comma.py +0 -75
  232. deadcode-2.3.0/black/tests/data/cases/slices.py +0 -31
  233. deadcode-2.3.0/black/tests/data/cases/split_delimiter_comments.py +0 -51
  234. deadcode-2.3.0/black/tests/data/cases/starred_for_target.py +0 -28
  235. deadcode-2.3.0/black/tests/data/cases/string_prefixes.py +0 -45
  236. deadcode-2.3.0/black/tests/data/cases/stub.py +0 -152
  237. deadcode-2.3.0/black/tests/data/cases/torture.py +0 -91
  238. deadcode-2.3.0/black/tests/data/cases/trailing_comma.py +0 -55
  239. deadcode-2.3.0/black/tests/data/cases/trailing_comma_optional_parens1.py +0 -63
  240. deadcode-2.3.0/black/tests/data/cases/trailing_comma_optional_parens2.py +0 -12
  241. deadcode-2.3.0/black/tests/data/cases/trailing_comma_optional_parens3.py +0 -21
  242. deadcode-2.3.0/black/tests/data/cases/trailing_commas_in_leading_parts.py +0 -88
  243. deadcode-2.3.0/black/tests/data/cases/tricky_unicode_symbols.py +0 -9
  244. deadcode-2.3.0/black/tests/data/cases/tupleassign.py +0 -23
  245. deadcode-2.3.0/black/tests/data/cases/type_aliases.py +0 -30
  246. deadcode-2.3.0/black/tests/data/cases/type_comment_syntax_error.py +0 -11
  247. deadcode-2.3.0/black/tests/data/cases/type_params.py +0 -58
  248. deadcode-2.3.0/black/tests/data/cases/typed_params_trailing_comma.py +0 -24
  249. deadcode-2.3.0/black/tests/data/cases/walrus_in_dict.py +0 -9
  250. deadcode-2.3.0/black/tests/data/cases/whitespace.py +0 -6
  251. deadcode-2.3.0/black/tests/data/gitignore_used_on_multiple_sources/dir1/a.py +0 -0
  252. deadcode-2.3.0/black/tests/data/gitignore_used_on_multiple_sources/dir1/b.py +0 -0
  253. deadcode-2.3.0/black/tests/data/gitignore_used_on_multiple_sources/dir2/a.py +0 -0
  254. deadcode-2.3.0/black/tests/data/gitignore_used_on_multiple_sources/dir2/b.py +0 -0
  255. deadcode-2.3.0/black/tests/data/ignore_subfolders_gitignore_tests/a.py +0 -0
  256. deadcode-2.3.0/black/tests/data/ignore_subfolders_gitignore_tests/subdir/b.py +0 -0
  257. deadcode-2.3.0/black/tests/data/ignore_subfolders_gitignore_tests/subdir/subdir/c.py +0 -0
  258. deadcode-2.3.0/black/tests/data/include_exclude_tests/b/.definitely_exclude/a.py +0 -0
  259. deadcode-2.3.0/black/tests/data/include_exclude_tests/b/dont_exclude/a.py +0 -0
  260. deadcode-2.3.0/black/tests/data/include_exclude_tests/b/exclude/a.py +0 -0
  261. deadcode-2.3.0/black/tests/data/invalid_gitignore_tests/a.py +0 -0
  262. deadcode-2.3.0/black/tests/data/invalid_nested_gitignore_tests/a/a.py +0 -0
  263. deadcode-2.3.0/black/tests/data/invalid_nested_gitignore_tests/a.py +0 -0
  264. deadcode-2.3.0/black/tests/data/line_ranges_formatted/basic.py +0 -50
  265. deadcode-2.3.0/black/tests/data/line_ranges_formatted/pattern_matching.py +0 -25
  266. deadcode-2.3.0/black/tests/data/miscellaneous/async_as_identifier.py +0 -49
  267. deadcode-2.3.0/black/tests/data/miscellaneous/blackd_diff.py +0 -6
  268. deadcode-2.3.0/black/tests/data/miscellaneous/debug_visitor.py +0 -32
  269. deadcode-2.3.0/black/tests/data/miscellaneous/decorators.py +0 -182
  270. deadcode-2.3.0/black/tests/data/miscellaneous/force_py36.py +0 -16
  271. deadcode-2.3.0/black/tests/data/miscellaneous/force_pyi.py +0 -66
  272. deadcode-2.3.0/black/tests/data/miscellaneous/invalid_header.py +0 -2
  273. deadcode-2.3.0/black/tests/data/miscellaneous/missing_final_newline.py +0 -3
  274. deadcode-2.3.0/black/tests/data/miscellaneous/pattern_matching_invalid.py +0 -18
  275. deadcode-2.3.0/black/tests/data/miscellaneous/python2_detection.py +0 -90
  276. deadcode-2.3.0/black/tests/data/miscellaneous/string_quotes.py +0 -114
  277. deadcode-2.3.0/black/tests/data/nested_gitignore_tests/root/a.py +0 -1
  278. deadcode-2.3.0/black/tests/data/nested_gitignore_tests/root/b.py +0 -1
  279. deadcode-2.3.0/black/tests/data/nested_gitignore_tests/root/c.py +0 -1
  280. deadcode-2.3.0/black/tests/data/nested_gitignore_tests/root/child/a.py +0 -1
  281. deadcode-2.3.0/black/tests/data/nested_gitignore_tests/root/child/b.py +0 -1
  282. deadcode-2.3.0/black/tests/data/nested_gitignore_tests/root/child/c.py +0 -1
  283. deadcode-2.3.0/black/tests/data/nested_gitignore_tests/x.py +0 -0
  284. deadcode-2.3.0/black/tests/optional.py +0 -132
  285. deadcode-2.3.0/black/tests/test_black.py +0 -2980
  286. deadcode-2.3.0/black/tests/test_blackd.py +0 -248
  287. deadcode-2.3.0/black/tests/test_docs.py +0 -74
  288. deadcode-2.3.0/black/tests/test_format.py +0 -90
  289. deadcode-2.3.0/black/tests/test_ipynb.py +0 -517
  290. deadcode-2.3.0/black/tests/test_no_ipynb.py +0 -36
  291. deadcode-2.3.0/black/tests/test_ranges.py +0 -249
  292. deadcode-2.3.0/black/tests/test_schema.py +0 -17
  293. deadcode-2.3.0/black/tests/test_trans.py +0 -51
  294. deadcode-2.3.0/black/tests/util.py +0 -354
  295. deadcode-2.3.0/call_arg_map_to_parameters_poc.py +0 -173
  296. deadcode-2.3.0/deadcode/actions/__init__.py +0 -0
  297. deadcode-2.3.0/deadcode/actions/parse_arguments.py +0 -229
  298. deadcode-2.3.0/deadcode/constants.py +0 -49
  299. deadcode-2.3.0/deadcode/tests/actions/test_find_python_filenames.py +0 -36
  300. deadcode-2.3.0/deadcode/tests/actions/test_merge_overlaping_file_parts.py +0 -62
  301. deadcode-2.3.0/deadcode/tests/cli_args/test_count.py +0 -0
  302. deadcode-2.3.0/deadcode/tests/cli_args/test_dry.py +0 -318
  303. deadcode-2.3.0/deadcode/tests/cli_args/test_exclude.py +0 -24
  304. deadcode-2.3.0/deadcode/tests/cli_args/test_fix.py +0 -528
  305. deadcode-2.3.0/deadcode/tests/cli_args/test_ignore_bodies_if_inherits_from.py +0 -46
  306. deadcode-2.3.0/deadcode/tests/cli_args/test_ignore_definitions.py +0 -106
  307. deadcode-2.3.0/deadcode/tests/cli_args/test_ignore_definitions_if_inherits_from.py +0 -125
  308. deadcode-2.3.0/deadcode/tests/cli_args/test_ignore_names.py +0 -79
  309. deadcode-2.3.0/deadcode/tests/cli_args/test_ignore_names_in_files.py +0 -0
  310. deadcode-2.3.0/deadcode/tests/cli_args/test_no_color.py +0 -0
  311. deadcode-2.3.0/deadcode/tests/cli_args/test_parsing.py +0 -113
  312. deadcode-2.3.0/deadcode/tests/cli_args/test_quiet.py +0 -0
  313. deadcode-2.3.0/deadcode/tests/cli_args/test_verbose.py +0 -0
  314. deadcode-2.3.0/deadcode/tests/code_item/test_code_item.py +0 -16
  315. deadcode-2.3.0/deadcode/tests/files/classes.py +0 -15
  316. deadcode-2.3.0/deadcode/tests/files/functions.py +0 -21
  317. deadcode-2.3.0/deadcode/tests/files/subdir/another_subdir/__init__.py +0 -1
  318. deadcode-2.3.0/deadcode/tests/files/subdir/one_more_file.py +0 -2
  319. deadcode-2.3.0/deadcode/tests/files/variables.py +0 -8
  320. deadcode-2.3.0/deadcode/tests/fix/test_assign.py +0 -92
  321. deadcode-2.3.0/deadcode/tests/fix/test_class_def.py +0 -116
  322. deadcode-2.3.0/deadcode/tests/fix/test_empty_files.py +0 -36
  323. deadcode-2.3.0/deadcode/tests/fix/test_method_def.py +0 -66
  324. deadcode-2.3.0/deadcode/tests/fix/test_scope.py +0 -243
  325. deadcode-2.3.0/deadcode/tests/fix/test_unreachable_code.py +0 -100
  326. deadcode-2.3.0/deadcode/tests/nested_scope/test_nested_scope.py +0 -180
  327. deadcode-2.3.0/deadcode/tests/noqa/test_noqa_comments.py +0 -329
  328. deadcode-2.3.0/deadcode/tests/test_accurate_usage_detection.py +0 -49
  329. deadcode-2.3.0/deadcode/tests/test_deadcode.py +0 -68
  330. deadcode-2.3.0/deadcode/tests/test_imports.py +0 -101
  331. deadcode-2.3.0/deadcode/tests/test_line_number_detection.py +0 -97
  332. deadcode-2.3.0/deadcode/tests/test_output.py +0 -137
  333. deadcode-2.3.0/deadcode/tests/test_variable_parsing_from_ast_dump.py +0 -12
  334. deadcode-2.3.0/deadcode/tests/utils/test_add_colors_to_diff.py +0 -38
  335. deadcode-2.3.0/deadcode/tests/utils/test_fix_indent.py +0 -10
  336. deadcode-2.3.0/deadcode/utils/__init__.py +0 -0
  337. deadcode-2.3.0/deadcode/utils/add_colors_to_diff.py +0 -10
  338. deadcode-2.3.0/deadcode/utils/fix_indent.py +0 -36
  339. deadcode-2.3.0/deadcode/utils/print_ast.py +0 -5
  340. deadcode-2.3.0/deadcode/visitor/__init__.py +0 -0
  341. deadcode-2.3.0/pyproject.toml +0 -94
  342. {deadcode-2.3.0 → deadcode-2.3.1}/.gitignore +0 -0
  343. {deadcode-2.3.0 → deadcode-2.3.1}/LICENSE +0 -0
  344. {deadcode-2.3.0/black/scripts → deadcode-2.3.1/deadcode}/__init__.py +0 -0
  345. {deadcode-2.3.0/black/src/black/resources → deadcode-2.3.1/deadcode/actions}/__init__.py +0 -0
  346. {deadcode-2.3.0 → deadcode-2.3.1}/deadcode/actions/find_unused_names.py +0 -0
  347. {deadcode-2.3.0/black/tests → deadcode-2.3.1/deadcode/utils}/__init__.py +0 -0
  348. {deadcode-2.3.0/deadcode → deadcode-2.3.1/deadcode/visitor}/__init__.py +0 -0
@@ -1,9 +1,9 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: deadcode
3
- Version: 2.3.0
3
+ Version: 2.3.1
4
4
  Summary: Find and remove dead code.
5
- Project-URL: Homepage, https://github.com/albertas/deadcode
6
- Project-URL: Documentation, https://deadcode.readthedocs.io/
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==2.0.1
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
  [![Deadcode Logo](https://raw.githubusercontent.com/albertas/deadcode/main/docs/_static/deadcode-logo-readme.png)](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 only `foo.py` file:
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
- ### Command line options
80
+ ## Command line options
73
81
 
74
82
  | Option&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | 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
- - [ ] `--fix --dry [filenames]` - only show whats about to change in the listed filenames.
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
- - [ ] Use only two digits for error codes instead of 3. Two is plenty and it simplifies usage a bit
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 only `foo.py` file:
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
- ### Command line options
51
+ ## Command line options
52
52
 
53
53
  | Option&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | 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
- - [ ] `--fix --dry [filenames]` - only show whats about to change in the listed filenames.
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
- - [ ] Use only two digits for error codes instead of 3. Two is plenty and it simplifies usage a bit
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"Ignoring: {path}")
19
+ logger.info(f'Ignoring: {path}')
20
20
  continue
21
21
 
22
- if path.is_file() and path.suffix == ".py":
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"Error: {path} could not be found.")
29
+ logger.error(f'Error: {path} could not be found.')
30
30
 
31
31
  if args.verbose:
32
- sep = "\n - "
33
- logger.info(f"Files to be checked for dead code: {sep.join(filenames)}")
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, unused_items in filename_to_unused_items.items():
31
- file_parts = flatten_list([item.code_parts for item in unused_items])
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 = "".join(updated_file_content_lines)
39
+ updated_file_content = b''.join(updated_file_content_lines)
40
40
  if updated_file_content.strip():
41
- if args.dry and ("__all_files__" in args.dry or _match(filename, args.dry)):
42
- with open(filename, "r") as f:
43
- diff = unified_diff(f.readlines(), updated_file_content_lines, fromfile=filename, tofile=filename)
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
- diff_str = "".join(diff)
47
+ result_chunk = b''.join(diff)
46
48
  if args.no_color:
47
- result.append(diff_str)
49
+ result.append(result_chunk)
48
50
  else:
49
- result.append(add_colors_to_diff(diff_str))
51
+ result.append(add_colors_to_diff(result_chunk))
50
52
 
51
53
  elif args.fix:
52
- with open(filename, "w") as f:
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 "\n".join(result)
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"{len(unused_names)}"
17
+ return f'{len(unused_names)}'
18
18
 
19
19
  messages = []
20
20
  for item in unused_names:
21
- message = f"{item.filename_with_position} \033[91m{item.error_code}\033[0m "
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("\033[91m", "").replace("\033[1m", "").replace("\033[0m", "")
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("\x1b[1m", "").replace("\x1b[0m", "")
32
+ message = message.replace('\x1b[1m', '').replace('\x1b[0m', '')
33
33
  messages.append(message)
34
34
 
35
- return "\n".join(messages)
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
- if starts_later and ends_faster:
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
- if (line_end_b > line_start_s) or ((line_end_b == line_start_s) and (col_end_b > col_start_s)):
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"Error: Failed to parse {filename} file, ignoring it.")
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("T")
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: str) -> bool:
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: str, current_line: str) -> bool:
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: str) -> str:
24
- return str(re.findall("^\s*", line)[0])
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: str) -> str:
28
- if not (line_rstrip := line.rstrip()).endswith("as"):
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 remove_file_parts_from_content(content_lines: List[str], unused_file_parts: List[Part]) -> List[str]:
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[str] = []
50
- empty_lines_before_removed_block_list: List[str] = []
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
- if (line[:from_col] + line[to_col:]).strip().startswith("="):
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
- line = remove_as_from_end(line[:from_col]) + line[to_col:]
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(f"{indentation_of_first_removed_line}pass\n")
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(f"{indentation_of_first_removed_line}pass\n")
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 + ("\n\n" + file_diff if file_diff else "")
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("\033[1mWell done!\033[0m ✨ 🚀 ✨")
30
+ print('\033[1mWell done!\033[0m ✨ 🚀 ✨')
31
31
  return None
32
32
 
33
33
 
34
- if __name__ == "__main__":
34
+ if __name__ == '__main__':
35
35
  main()