openrewrite-migrate-python 0.16.0.dev20261007190022__tar.gz → 0.16.0.dev20261008024228__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 (187) hide show
  1. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/PKG-INFO +2 -2
  2. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/pyproject.toml +2 -2
  3. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_code_quality_python/codequality/_reindent.py +4 -3
  4. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_code_quality_python/codequality/_semantically_equal.py +38 -0
  5. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_code_quality_python/codequality/_trivia.py +6 -3
  6. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_code_quality_python/codequality/all_branches_identical.py +17 -11
  7. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_code_quality_python/codequality/boolean_checks_not_inverted.py +7 -6
  8. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_code_quality_python/codequality/collapsible_if_statements.py +16 -47
  9. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_code_quality_python/codequality/find_suspicious_chained_comparison.py +14 -21
  10. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_code_quality_python/codequality/merge_identical_branches.py +21 -48
  11. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_code_quality_python/codequality/remove_duplicate_conditions.py +6 -5
  12. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_code_quality_python/codequality/remove_self_assignment.py +8 -4
  13. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_code_quality_python/codequality/remove_unconditional_value_overwrite.py +6 -5
  14. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_code_quality_python/codequality/simplify_boolean_literal.py +23 -33
  15. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_code_quality_python/codequality/simplify_redundant_logical_expression.py +8 -7
  16. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/_decorators.py +24 -0
  17. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/_method_renames.py +37 -0
  18. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/_module_imports.py +50 -0
  19. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/aifc_migrations.py +271 -0
  20. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/array_deprecations.py +9 -50
  21. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/ast_deprecations.py +13 -110
  22. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/asyncio_coroutine_to_async.py +30 -53
  23. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/asyncio_deprecations.py +26 -25
  24. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/calendar_deprecations.py +8 -38
  25. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/cgi_migrations.py +115 -0
  26. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/cgi_parse_deprecations.py +109 -0
  27. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/collections_abc_migrations.py +6 -11
  28. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/configparser_deprecations.py +115 -0
  29. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/datetime_utc.py +23 -41
  30. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/distutils_deprecations.py +9 -28
  31. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/distutils_migrations.py +7 -3
  32. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/functools_deprecations.py +17 -23
  33. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/future_imports.py +111 -0
  34. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/gettext_deprecations.py +80 -0
  35. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/html_parser_deprecations.py +89 -0
  36. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/imp_migrations.py +76 -0
  37. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/langchain_classic_imports.py +29 -48
  38. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/langchain_community_imports.py +9 -4
  39. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/langchain_provider_imports.py +10 -107
  40. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/locale_deprecations.py +85 -0
  41. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/locale_getdefaultlocale_deprecation.py +8 -7
  42. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/macpath_deprecations.py +66 -0
  43. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/mailcap_migrations.py +70 -0
  44. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/nntplib_migrations.py +68 -0
  45. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/os_deprecations.py +29 -48
  46. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/pathlib_deprecations.py +11 -14
  47. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/pep594_system_migrations.py +230 -0
  48. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/pipes_migrations.py +71 -0
  49. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/pkgutil_deprecations.py +30 -40
  50. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/platform_deprecations.py +91 -0
  51. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/pydantic_deprecations.py +85 -85
  52. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/pydantic_fields.py +9 -21
  53. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/pydantic_model_fields.py +5 -5
  54. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/re_deprecations.py +57 -54
  55. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/removed_modules_312.py +81 -0
  56. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/shutil_deprecations.py +8 -4
  57. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/socket_deprecations.py +8 -4
  58. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/ssl_deprecations.py +13 -42
  59. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/string_formatting.py +18 -17
  60. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/sys_deprecations.py +17 -27
  61. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/sys_last_deprecations.py +41 -21
  62. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/tarfile_deprecations.py +64 -0
  63. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/telnetlib_migrations.py +74 -0
  64. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/tempfile_deprecations.py +12 -20
  65. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/threading_deprecations.py +67 -172
  66. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/threading_is_alive_deprecation.py +6 -28
  67. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/typing_deprecations.py +25 -45
  68. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/typing_union_to_pipe.py +52 -41
  69. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/unittest_deprecations.py +6 -45
  70. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/upgrade_to_python39.py +0 -2
  71. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/urllib_deprecations.py +22 -51
  72. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/uu_migrations.py +70 -0
  73. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/xdrlib_migrations.py +70 -0
  74. openrewrite_migrate_python-0.16.0.dev20261008024228/src/openrewrite_migrate_python/migrate/xml_deprecations.py +131 -0
  75. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python.egg-info/PKG-INFO +2 -2
  76. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python.egg-info/SOURCES.txt +3 -3
  77. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python.egg-info/requires.txt +1 -1
  78. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_ast_deprecations.py +15 -0
  79. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_asyncio_coroutine_to_async.py +33 -2
  80. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_asyncio_deprecations.py +37 -0
  81. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_backoff_to_tenacity.py +0 -3
  82. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_calendar_deprecations.py +15 -0
  83. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_cgi_parse_deprecations.py +17 -2
  84. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_configparser_deprecations.py +25 -0
  85. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_datetime_utc.py +31 -0
  86. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_distutils_deprecations.py +15 -0
  87. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_functools_deprecations.py +34 -0
  88. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_gettext_deprecations.py +9 -2
  89. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_html_parser_deprecations.py +56 -0
  90. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_langchain_classic_imports.py +11 -0
  91. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_langchain_provider_imports.py +19 -4
  92. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_locale_deprecations.py +21 -0
  93. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_os_deprecations.py +32 -2
  94. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_pathlib_deprecations.py +21 -0
  95. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_pep594_migrations.py +12 -0
  96. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_pkgutil_deprecations.py +44 -0
  97. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_platform_deprecations.py +47 -2
  98. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_pydantic_deprecations.py +146 -0
  99. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_re_deprecations.py +57 -0
  100. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_removed_modules_312.py +13 -0
  101. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_ssl_deprecations.py +22 -0
  102. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_string_formatting.py +51 -2
  103. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_sys_deprecations.py +9 -0
  104. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_sys_last_deprecations.py +44 -0
  105. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_tarfile_deprecations.py +29 -2
  106. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_tempfile_deprecations.py +21 -0
  107. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_threading_deprecations.py +27 -0
  108. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_typing_alias_moves.py +0 -23
  109. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_typing_deprecations.py +32 -0
  110. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_typing_union_to_pipe.py +68 -1
  111. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_unittest_deprecations.py +35 -0
  112. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_urllib_deprecations.py +20 -0
  113. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_xml_deprecations.py +19 -0
  114. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_code_quality_python/codequality/_semantically_equal.py +0 -32
  115. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/_from_imports.py +0 -68
  116. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/_import_hygiene.py +0 -55
  117. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/_typing_imports.py +0 -71
  118. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/aifc_migrations.py +0 -508
  119. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/cgi_migrations.py +0 -204
  120. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/cgi_parse_deprecations.py +0 -205
  121. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/configparser_deprecations.py +0 -254
  122. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/future_imports.py +0 -155
  123. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/gettext_deprecations.py +0 -148
  124. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/html_parser_deprecations.py +0 -106
  125. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/imp_migrations.py +0 -125
  126. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/locale_deprecations.py +0 -190
  127. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/macpath_deprecations.py +0 -116
  128. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/mailcap_migrations.py +0 -120
  129. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/nntplib_migrations.py +0 -118
  130. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/pep594_system_migrations.py +0 -420
  131. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/pipes_migrations.py +0 -121
  132. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/platform_deprecations.py +0 -173
  133. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/removed_modules_312.py +0 -145
  134. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/tarfile_deprecations.py +0 -113
  135. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/telnetlib_migrations.py +0 -123
  136. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/uu_migrations.py +0 -120
  137. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/xdrlib_migrations.py +0 -120
  138. openrewrite_migrate_python-0.16.0.dev20261007190022/src/openrewrite_migrate_python/migrate/xml_deprecations.py +0 -188
  139. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/setup.cfg +0 -0
  140. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_code_quality_python/__init__.py +0 -0
  141. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_code_quality_python/codequality/__init__.py +0 -0
  142. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_code_quality_python/codequality/_side_effects.py +0 -0
  143. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_code_quality_python/codequality/code_quality.py +0 -0
  144. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/__init__.py +0 -0
  145. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/__init__.py +0 -0
  146. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/_langchain_tables.py +0 -0
  147. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/_markers.py +0 -0
  148. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/_slots.py +0 -0
  149. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/avro_migrations.py +0 -0
  150. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/backoff_to_tenacity.py +0 -0
  151. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/typing_callable.py +0 -0
  152. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/upgrade_to_langchain02.py +0 -0
  153. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/upgrade_to_langchain1.py +0 -0
  154. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/upgrade_to_pydantic.py +0 -0
  155. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/upgrade_to_python310.py +0 -0
  156. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/upgrade_to_python311.py +0 -0
  157. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/upgrade_to_python312.py +0 -0
  158. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/upgrade_to_python313.py +0 -0
  159. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/upgrade_to_python314.py +0 -0
  160. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python/migrate/upgrade_to_python38.py +0 -0
  161. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python.egg-info/dependency_links.txt +0 -0
  162. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python.egg-info/entry_points.txt +0 -0
  163. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/src/openrewrite_migrate_python.egg-info/top_level.txt +0 -0
  164. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_aifc_migrations.py +0 -0
  165. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_array_deprecations.py +0 -0
  166. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_avro_migrations.py +0 -0
  167. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_change_import_recipes.py +0 -0
  168. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_collections_abc_migrations.py +0 -0
  169. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_distutils_migrations.py +0 -0
  170. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_future_imports.py +0 -0
  171. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_imp_migrations.py +0 -0
  172. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_langchain_community_imports.py +0 -0
  173. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_locale_getdefaultlocale_deprecation.py +0 -0
  174. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_macpath_deprecations.py +0 -0
  175. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_mailcap_migrations.py +0 -0
  176. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_markers.py +0 -0
  177. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_pep594_system_migrations.py +0 -0
  178. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_pydantic_fields.py +0 -0
  179. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_pydantic_model_fields.py +0 -0
  180. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_shutil_deprecations.py +0 -0
  181. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_socket_deprecations.py +0 -0
  182. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_threading_extended.py +0 -0
  183. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_threading_is_alive_deprecation.py +0 -0
  184. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_typing_callable.py +0 -0
  185. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_upgrade_recipes.py +0 -0
  186. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_upgrade_to_pydantic.py +0 -0
  187. {openrewrite_migrate_python-0.16.0.dev20261007190022 → openrewrite_migrate_python-0.16.0.dev20261008024228}/tests/test_xdrlib_migrations.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openrewrite-migrate-python
3
- Version: 0.16.0.dev20261007190022
3
+ Version: 0.16.0.dev20261008024228
4
4
  Summary: OpenRewrite recipes for migrating Python codebases to newer Python versions.
5
5
  Author-email: "Moderne Inc." <support@moderne.io>
6
6
  License: Moderne Proprietary
@@ -19,7 +19,7 @@ Classifier: Typing :: Typed
19
19
  Requires-Python: >=3.12
20
20
  Description-Content-Type: text/markdown
21
21
  Provides-Extra: dev
22
- Requires-Dist: openrewrite>=8.92.3; extra == "dev"
22
+ Requires-Dist: openrewrite>=8.92.18; extra == "dev"
23
23
  Requires-Dist: pydantic>=2.11; extra == "dev"
24
24
  Requires-Dist: pytest>=8.0.0; extra == "dev"
25
25
  Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
  [project]
6
6
  name = "openrewrite-migrate-python"
7
7
  description = "OpenRewrite recipes for migrating Python codebases to newer Python versions."
8
- version = "0.16.0.dev20261007190022" # Updated dynamically during release
8
+ version = "0.16.0.dev20261008024228" # Updated dynamically during release
9
9
  authors = [{ name = "Moderne Inc.", email = "support@moderne.io" }]
10
10
  license = { text = "Moderne Proprietary" }
11
11
  readme = "README.md"
@@ -28,7 +28,7 @@ dependencies = []
28
28
 
29
29
  [project.optional-dependencies]
30
30
  dev = [
31
- "openrewrite>=8.92.3",
31
+ "openrewrite>=8.92.18",
32
32
  # Needed so type-attribution tests can resolve `pydantic` types.
33
33
  "pydantic>=2.11",
34
34
  "pytest>=8.0.0",
@@ -4,14 +4,15 @@ Python indentation lives in the ``Space`` before each token, so moving a block
4
4
  to a shallower nesting level means rewriting every line it spans.
5
5
  """
6
6
 
7
- from typing import Optional, TypeVar
7
+ from typing import Optional, TypeVar, cast
8
8
 
9
9
  from rewrite.java.markers import TrailingComma
10
10
  from rewrite.java.support_types import Space
11
+ from rewrite.java.tree import J
11
12
  from rewrite.markers import Marker
12
13
  from rewrite.python.visitor import PythonVisitor
13
14
 
14
- T = TypeVar("T")
15
+ T = TypeVar("T", bound=J)
15
16
 
16
17
 
17
18
  def inherited_prefix(dropped: Space, body: Space) -> Space:
@@ -90,4 +91,4 @@ def reindent(tree: T, old_base: str, new_base: str) -> T:
90
91
  """
91
92
  if old_base == new_base:
92
93
  return tree
93
- return _Reindent(old_base, new_base).visit(tree, None)
94
+ return cast(T, _Reindent(old_base, new_base).visit(tree, None))
@@ -0,0 +1,38 @@
1
+ """Semantic equality of LST nodes, for recipes that keep one of two equal subtrees."""
2
+
3
+ from typing import List, Optional
4
+
5
+ from rewrite.java.support_types import J, Space
6
+ from rewrite.python.template.comparator import PythonComparatorVisitor
7
+ from rewrite.python.visitor import PythonVisitor
8
+ from rewrite.visitor import Cursor
9
+
10
+
11
+ class _CommentTexts(PythonVisitor[List[str]]):
12
+ def visit_space(self, space: Optional[Space], p: List[str]) -> Space:
13
+ if space is not None:
14
+ p.extend(comment.text for comment in space.comments)
15
+ return super().visit_space(space, p)
16
+
17
+
18
+ def _comment_texts(tree: J) -> List[str]:
19
+ texts: List[str] = []
20
+ _CommentTexts().visit(tree, texts)
21
+ return texts
22
+
23
+
24
+ class SemanticallyEqual:
25
+ """Compare two LST nodes for structural equality."""
26
+
27
+ @staticmethod
28
+ def are_equal(a: Optional[J], b: Optional[J]) -> bool:
29
+ """Whether *a* and *b* are the same code carrying the same comments.
30
+
31
+ Whitespace is ignored. Comments must match, so a recipe dropping either copy loses none.
32
+ """
33
+ if a is None or b is None:
34
+ return a is b
35
+ return (
36
+ PythonComparatorVisitor().compare(a, b, Cursor(None, Cursor.ROOT_VALUE))
37
+ and _comment_texts(a) == _comment_texts(b)
38
+ )
@@ -12,7 +12,7 @@ from typing import Optional, Tuple
12
12
 
13
13
  from rewrite import Cursor
14
14
  from rewrite.java.support_types import Space
15
- from rewrite.java.tree import Block, ClassDeclaration, If, MethodDeclaration
15
+ from rewrite.java.tree import Block, ClassDeclaration, If, J, MethodDeclaration
16
16
  from rewrite.python.tree import CompilationUnit
17
17
 
18
18
 
@@ -81,9 +81,11 @@ def space_after_block(cursor: Cursor) -> Optional[Space]:
81
81
  know how to look past.
82
82
  """
83
83
  child = cursor.value
84
+ if not isinstance(child, J):
85
+ return None
84
86
  for parent in islice(cursor.get_path(), 1, None):
85
87
  if isinstance(parent, (Block, CompilationUnit)):
86
- statements = parent._statements
88
+ statements = parent.padding.statements
87
89
  index = next(
88
90
  (i for i, s in enumerate(statements) if s.element.id == child.id),
89
91
  None,
@@ -125,7 +127,8 @@ def splice_out(
125
127
  continue
126
128
  if pending is not None:
127
129
  head, line = pending
128
- _, tail = split_line(padded.element.prefix)
130
+ prefix = padded.element.prefix
131
+ _, tail = split_line(prefix) or (Space.EMPTY, prefix)
129
132
  padded = padded.replace(
130
133
  _element=padded.element.replace(
131
134
  _prefix=concat(
@@ -15,7 +15,9 @@ from rewrite import ExecutionContext, Recipe, TreeVisitor
15
15
  from rewrite.category import CategoryDescriptor
16
16
  from rewrite.decorators import categorize
17
17
  from rewrite.marketplace import Python
18
+ from rewrite.python.tree import CompilationUnit
18
19
  from rewrite.python.visitor import PythonVisitor
20
+ from rewrite.java.tree import J
19
21
  from rewrite.java.tree import (
20
22
  Block,
21
23
  If,
@@ -144,19 +146,23 @@ class AllBranchesIdentical(Recipe):
144
146
  def editor(self) -> TreeVisitor[Any, ExecutionContext]:
145
147
  class Visitor(PythonVisitor[ExecutionContext]):
146
148
  def visit_compilation_unit(self, cu, p):
147
- cu = super().visit_compilation_unit(cu, p)
148
- new_stmts = _replace_identical_ifs_padded(cu._statements)
149
+ visited = super().visit_compilation_unit(cu, p)
150
+ if not isinstance(visited, CompilationUnit):
151
+ return visited
152
+ cu = visited
153
+ new_stmts = _replace_identical_ifs_padded(cu.padding.statements)
149
154
  if new_stmts is not None:
150
155
  return cu.replace(_statements=new_stmts)
151
156
  return cu
152
157
 
153
158
  def visit_block(
154
159
  self, block: Block, p: ExecutionContext
155
- ) -> Optional[Block]:
156
- block = super().visit_block(block, p)
157
- if not isinstance(block, Block):
158
- return block
159
- new_stmts = _replace_identical_ifs_padded(block._statements)
160
+ ) -> J:
161
+ visited = super().visit_block(block, p)
162
+ if not isinstance(visited, Block):
163
+ return visited
164
+ block = visited
165
+ new_stmts = _replace_identical_ifs_padded(block.padding.statements)
160
166
  if new_stmts is not None:
161
167
  return block.replace(_statements=new_stmts)
162
168
  return block
@@ -186,12 +192,12 @@ def _replace_identical_ifs_padded(padded_stmts) -> Optional[list]:
186
192
  continue
187
193
 
188
194
  body = s.then_part
189
- if not isinstance(body, Block) or not body._statements:
195
+ if not isinstance(body, Block) or not body.padding.statements:
190
196
  result.append(rp)
191
197
  continue
192
198
 
193
199
  if_indent = line_indent(s.prefix)
194
- body_indent = line_indent(body._statements[0].element.prefix)
200
+ body_indent = line_indent(body.padding.statements[0].element.prefix)
195
201
  if (
196
202
  if_indent is None
197
203
  or body_indent is None
@@ -201,7 +207,7 @@ def _replace_identical_ifs_padded(padded_stmts) -> Optional[list]:
201
207
  continue
202
208
 
203
209
  body = reindent(body, body_indent, if_indent)
204
- first = body._statements[0]
210
+ first = body.padding.statements[0]
205
211
  # Each lifted statement keeps its own padding, which is where a `;`
206
212
  # separating it from the next one is recorded.
207
213
  result.append(
@@ -211,7 +217,7 @@ def _replace_identical_ifs_padded(padded_stmts) -> Optional[list]:
211
217
  )
212
218
  )
213
219
  )
214
- result.extend(body._statements[1:])
220
+ result.extend(body.padding.statements[1:])
215
221
  changed = True
216
222
 
217
223
  if not changed:
@@ -8,7 +8,7 @@ when written as ``a != b``, and ``not (not x)`` is just ``x``.
8
8
  See: https://rules.sonarsource.com/python/RSPEC-S1940/
9
9
  """
10
10
 
11
- from typing import Any, List, Optional
11
+ from typing import Any, List
12
12
 
13
13
  from rewrite import Cursor, ExecutionContext, Recipe, TreeVisitor
14
14
  from rewrite.category import CategoryDescriptor
@@ -16,6 +16,7 @@ from rewrite.decorators import categorize
16
16
  from rewrite.marketplace import Python
17
17
  from rewrite.python.tree import Binary as PyBinary
18
18
  from rewrite.python.visitor import PythonVisitor
19
+ from rewrite.java.tree import J
19
20
  from rewrite.java.support_types import JavaType, JLeftPadded
20
21
  from rewrite.java.tree import (
21
22
  Assert,
@@ -146,11 +147,11 @@ class BooleanChecksNotInverted(Recipe):
146
147
  class Visitor(PythonVisitor[ExecutionContext]):
147
148
  def visit_unary(
148
149
  self, unary: Unary, p: ExecutionContext
149
- ) -> Optional[Expression]:
150
- unary = super().visit_unary(unary, p)
151
-
152
- if not isinstance(unary, Unary):
153
- return unary
150
+ ) -> J:
151
+ visited = super().visit_unary(unary, p)
152
+ if not isinstance(visited, Unary):
153
+ return visited
154
+ unary = visited
154
155
 
155
156
  if unary.operator != Unary.Type.Not:
156
157
  return unary
@@ -9,27 +9,22 @@ easier to follow.
9
9
  See: https://rules.sonarsource.com/python/RSPEC-S1066/
10
10
  """
11
11
 
12
- from typing import Any, List, Optional
12
+ from typing import Any, List
13
13
 
14
14
  from rewrite import ExecutionContext, Recipe, TreeVisitor
15
15
  from rewrite.category import CategoryDescriptor
16
16
  from rewrite.decorators import categorize
17
17
  from rewrite.marketplace import Python
18
18
  from rewrite.markers import Markers
19
- from rewrite.python.tree import StatementExpression
19
+ from rewrite.python.template.precedence import maybe_parenthesize
20
20
  from rewrite.python.visitor import PythonVisitor
21
21
  from rewrite.java.support_types import Comment, JLeftPadded, JRightPadded, Space
22
22
  from rewrite.java.tree import (
23
- Assignment,
24
23
  Binary as JBinary,
25
24
  Block,
26
25
  ControlParentheses,
27
- Expression,
28
26
  If,
29
27
  J,
30
- Lambda,
31
- Parentheses,
32
- Ternary,
33
28
  )
34
29
  from rewrite.utils import random_id
35
30
 
@@ -48,18 +43,6 @@ _CodeQuality = [
48
43
  ]
49
44
 
50
45
 
51
- def _binds_looser_than_and(expr: Expression) -> bool:
52
- """Return True for the operand forms that ``and`` would capture.
53
-
54
- Everything below ``and`` in Python's precedence table: ``or``, the
55
- conditional expression, ``lambda``, ``:=`` (a ``J.Assignment`` here) and
56
- ``yield`` (a ``Py.StatementExpression``).
57
- """
58
- if isinstance(expr, JBinary):
59
- return expr.operator == JBinary.Type.Or
60
- return isinstance(expr, (Ternary, Lambda, Assignment, StatementExpression))
61
-
62
-
63
46
  def _with_comments_above(prefix: Space, comments: List[Comment]) -> Space:
64
47
  """*prefix* with *comments* on their own lines just before the token it
65
48
  leads into. Each comment's suffix must already end at that token's indent."""
@@ -68,23 +51,6 @@ def _with_comments_above(prefix: Space, comments: List[Comment]) -> Space:
68
51
  return Space(_comments=[*prefix.comments, *comments], _whitespace=prefix.whitespace)
69
52
 
70
53
 
71
- def _operand(expr: Expression, prefix: Space) -> Expression:
72
- """Prepare *expr* as an operand of the merged ``and``, parenthesizing it
73
- when its own operator would otherwise be captured."""
74
- if _binds_looser_than_and(expr):
75
- return Parentheses(
76
- _id=random_id(),
77
- _prefix=prefix,
78
- _markers=Markers.EMPTY,
79
- _tree=JRightPadded(
80
- _element=expr.replace(_prefix=Space.EMPTY),
81
- _after=Space.EMPTY,
82
- _markers=Markers.EMPTY,
83
- ),
84
- )
85
- return expr.replace(_prefix=prefix)
86
-
87
-
88
54
  @categorize(_CodeQuality)
89
55
  class CollapsibleIfStatements(Recipe):
90
56
  """
@@ -140,11 +106,11 @@ class CollapsibleIfStatements(Recipe):
140
106
 
141
107
  def visit_if(
142
108
  self, if_: If, p: ExecutionContext
143
- ) -> Optional[If]:
144
- if_ = super().visit_if(if_, p)
145
-
146
- if not isinstance(if_, If):
147
- return if_
109
+ ) -> J:
110
+ visited = super().visit_if(if_, p)
111
+ if not isinstance(visited, If):
112
+ return visited
113
+ if_ = visited
148
114
 
149
115
  # Outer if must have no else/elif
150
116
  if if_.else_part is not None:
@@ -212,18 +178,21 @@ class CollapsibleIfStatements(Recipe):
212
178
  _id=random_id(),
213
179
  _prefix=if_.if_condition.tree.prefix,
214
180
  _markers=Markers.EMPTY,
215
- _left=_operand(if_.if_condition.tree, Space.EMPTY),
181
+ _left=if_.if_condition.tree.replace(_prefix=Space.EMPTY),
216
182
  _operator=JLeftPadded(
217
183
  _before=Space.SINGLE_SPACE,
218
184
  _element=JBinary.Type.And,
219
185
  _markers=Markers.EMPTY,
220
186
  ),
221
- _right=_operand(
222
- reindent(inner.if_condition.tree, header_indent, outer_indent),
223
- Space.SINGLE_SPACE,
187
+ _right=reindent(inner.if_condition.tree, header_indent, outer_indent).replace(
188
+ _prefix=Space.SINGLE_SPACE
224
189
  ),
225
190
  _type=None,
226
191
  )
192
+ combined = combined.replace(
193
+ _left=maybe_parenthesize(combined, combined.left.id, combined.left),
194
+ _right=maybe_parenthesize(combined, combined.right.id, combined.right),
195
+ )
227
196
 
228
197
  new_condition = ControlParentheses(
229
198
  _id=if_.if_condition.id,
@@ -240,7 +209,7 @@ class CollapsibleIfStatements(Recipe):
240
209
  # level at a time, and each pass rebases the comments the
241
210
  # previous one left at the level it dropped.
242
211
  inner_body = reindent(inner_body, body_indent, header_indent)
243
- first = inner_body._statements[0]
212
+ first = inner_body.padding.statements[0]
244
213
  inner_body = inner_body.replace(
245
214
  _statements=[
246
215
  first.replace(
@@ -248,7 +217,7 @@ class CollapsibleIfStatements(Recipe):
248
217
  _prefix=concat(header_trailer, first.element.prefix)
249
218
  )
250
219
  ),
251
- *inner_body._statements[1:],
220
+ *inner_body.padding.statements[1:],
252
221
  ]
253
222
  )
254
223
 
@@ -14,10 +14,10 @@ from rewrite import ExecutionContext, Recipe, TreeVisitor
14
14
  from rewrite.category import CategoryDescriptor
15
15
  from rewrite.decorators import categorize
16
16
  from rewrite.marketplace import Python
17
- from rewrite.markers import Markers, SearchResult
17
+ from rewrite.markers import SearchResult
18
18
  from rewrite.python.visitor import PythonVisitor
19
- from rewrite.java.tree import Binary as JBinary, Expression
20
- from rewrite.utils import random_id
19
+ from rewrite.java.tree import J
20
+ from rewrite.java.tree import Binary as JBinary
21
21
 
22
22
  _CodeQuality = [
23
23
  *Python,
@@ -37,18 +37,11 @@ def _direction(operator: JBinary.Type) -> Optional[str]:
37
37
  return None
38
38
 
39
39
 
40
- def _mark(tree: Expression) -> Expression:
41
- """Attach a SearchResult flagging the conflicting chained comparison."""
42
- message = (
43
- "Suspicious chained comparison: the two comparisons point in "
44
- "opposite directions, so the chain narrows to a surprising range. "
45
- "Did you mean to keep both comparisons in the same direction?"
46
- )
47
- marker = SearchResult(random_id(), message)
48
- current = tree.markers
49
- return tree.replace(
50
- _markers=Markers(current.id, list(current.markers) + [marker])
51
- )
40
+ _MESSAGE = (
41
+ "Suspicious chained comparison: the two comparisons point in "
42
+ "opposite directions, so the chain narrows to a surprising range. "
43
+ "Did you mean to keep both comparisons in the same direction?"
44
+ )
52
45
 
53
46
 
54
47
  @categorize(_CodeQuality)
@@ -99,11 +92,11 @@ class FindSuspiciousChainedComparison(Recipe):
99
92
  class Visitor(PythonVisitor[ExecutionContext]):
100
93
  def visit_binary(
101
94
  self, binary: JBinary, p: ExecutionContext
102
- ) -> Optional[Expression]:
103
- binary = super().visit_binary(binary, p)
104
-
105
- if not isinstance(binary, JBinary):
106
- return binary
95
+ ) -> J:
96
+ visited = super().visit_binary(binary, p)
97
+ if not isinstance(visited, JBinary):
98
+ return visited
99
+ binary = visited
107
100
 
108
101
  outer = _direction(binary.operator)
109
102
  if outer is None:
@@ -117,6 +110,6 @@ class FindSuspiciousChainedComparison(Recipe):
117
110
  if left is None or left == outer:
118
111
  return binary
119
112
 
120
- return _mark(binary)
113
+ return SearchResult.found(binary, _MESSAGE)
121
114
 
122
115
  return Visitor()
@@ -9,26 +9,23 @@ multiple conditions.
9
9
  See: https://rules.sonarsource.com/python/RSPEC-S1871/
10
10
  """
11
11
 
12
- from typing import Any, List, Optional
12
+ from typing import Any, List
13
13
 
14
14
  from rewrite import ExecutionContext, Recipe, TreeVisitor
15
15
  from rewrite.category import CategoryDescriptor
16
16
  from rewrite.decorators import categorize
17
17
  from rewrite.marketplace import Python
18
18
  from rewrite.markers import Markers
19
+ from rewrite.python.template.precedence import maybe_parenthesize, parenthesize
19
20
  from rewrite.python.visitor import PythonVisitor
21
+ from rewrite.java.tree import J
20
22
  from rewrite.java.support_types import JLeftPadded, JRightPadded, Space
21
23
  from rewrite.java.tree import (
22
- Assignment,
23
24
  Binary as JBinary,
24
- Block,
25
25
  ControlParentheses,
26
26
  Expression,
27
27
  If,
28
- Lambda,
29
- Parentheses,
30
28
  Statement,
31
- Ternary,
32
29
  )
33
30
  from openrewrite_code_quality_python.codequality._semantically_equal import SemanticallyEqual
34
31
  from rewrite.utils import random_id
@@ -39,12 +36,12 @@ _CodeQuality = [
39
36
  ]
40
37
 
41
38
 
42
- def _needs_parens_as_or_operand(expr: Expression) -> bool:
43
- # A walrus, ternary or lambda binds looser than `or`. An `and` does not,
44
- # and is parenthesized for readability.
45
- if isinstance(expr, (Assignment, Ternary, Lambda)):
46
- return True
47
- return isinstance(expr, JBinary) and expr.operator == JBinary.Type.And
39
+ def _or_operand(expr: Expression, prefix: Space) -> Expression:
40
+ # An `and` binds tighter than `or` and is parenthesized for readability.
41
+ expr = expr.replace(_prefix=prefix)
42
+ if isinstance(expr, JBinary) and expr.operator == JBinary.Type.And:
43
+ return parenthesize(expr)
44
+ return expr
48
45
 
49
46
 
50
47
  def _bodies_equal(a: Statement, b: Statement) -> bool:
@@ -106,11 +103,11 @@ class MergeIdenticalBranches(Recipe):
106
103
  class Visitor(PythonVisitor[ExecutionContext]):
107
104
  def visit_if(
108
105
  self, if_: If, p: ExecutionContext
109
- ) -> Optional[If]:
110
- if_ = super().visit_if(if_, p)
111
-
112
- if not isinstance(if_, If):
113
- return if_
106
+ ) -> J:
107
+ visited = super().visit_if(if_, p)
108
+ if not isinstance(visited, If):
109
+ return visited
110
+ if_ = visited
114
111
 
115
112
  # Only process top-level if in a chain
116
113
  try:
@@ -166,47 +163,23 @@ def _merge_conditions(first: If, second: If) -> If:
166
163
  first_cond = first.if_condition.tree
167
164
  second_cond = second.if_condition.tree
168
165
 
169
- if _needs_parens_as_or_operand(first_cond):
170
- left = Parentheses(
171
- _id=random_id(),
172
- _prefix=first_cond.prefix,
173
- _markers=Markers.EMPTY,
174
- _tree=JRightPadded(
175
- _element=first_cond.replace(_prefix=Space.EMPTY),
176
- _after=Space.EMPTY,
177
- _markers=Markers.EMPTY,
178
- ),
179
- )
180
- else:
181
- left = first_cond
182
-
183
- if _needs_parens_as_or_operand(second_cond):
184
- right = Parentheses(
185
- _id=random_id(),
186
- _prefix=Space.SINGLE_SPACE,
187
- _markers=Markers.EMPTY,
188
- _tree=JRightPadded(
189
- _element=second_cond.replace(_prefix=Space.EMPTY),
190
- _after=Space.EMPTY,
191
- _markers=Markers.EMPTY,
192
- ),
193
- )
194
- else:
195
- right = second_cond.replace(_prefix=Space.SINGLE_SPACE)
196
-
197
166
  combined = JBinary(
198
167
  _id=random_id(),
199
- _prefix=left.prefix,
168
+ _prefix=first_cond.prefix,
200
169
  _markers=Markers.EMPTY,
201
- _left=left.replace(_prefix=Space.EMPTY),
170
+ _left=_or_operand(first_cond, Space.EMPTY),
202
171
  _operator=JLeftPadded(
203
172
  _before=Space.SINGLE_SPACE,
204
173
  _element=JBinary.Type.Or,
205
174
  _markers=Markers.EMPTY,
206
175
  ),
207
- _right=right,
176
+ _right=_or_operand(second_cond, Space.SINGLE_SPACE),
208
177
  _type=None,
209
178
  )
179
+ combined = combined.replace(
180
+ _left=maybe_parenthesize(combined, combined.left.id, combined.left),
181
+ _right=maybe_parenthesize(combined, combined.right.id, combined.right),
182
+ )
210
183
 
211
184
  new_condition = ControlParentheses(
212
185
  _id=first.if_condition.id,
@@ -16,6 +16,7 @@ from rewrite.category import CategoryDescriptor
16
16
  from rewrite.decorators import categorize
17
17
  from rewrite.marketplace import Python
18
18
  from rewrite.python.visitor import PythonVisitor
19
+ from rewrite.java.tree import J
19
20
  from rewrite.java.tree import If, Expression
20
21
  from openrewrite_code_quality_python.codequality._semantically_equal import SemanticallyEqual
21
22
  from openrewrite_code_quality_python.codequality._side_effects import is_side_effect_free
@@ -97,11 +98,11 @@ class RemoveDuplicateConditions(Recipe):
97
98
  class Visitor(PythonVisitor[ExecutionContext]):
98
99
  def visit_if(
99
100
  self, if_: If, p: ExecutionContext
100
- ) -> Optional[If]:
101
- if_ = super().visit_if(if_, p)
102
-
103
- if not isinstance(if_, If):
104
- return if_
101
+ ) -> J:
102
+ visited = super().visit_if(if_, p)
103
+ if not isinstance(visited, If):
104
+ return visited
105
+ if_ = visited
105
106
 
106
107
  # Only process top-level if (not elif branches visited
107
108
  # as children -- those are handled by walking the chain)
@@ -19,6 +19,7 @@ from rewrite.marketplace import Python
19
19
  from rewrite.java.support_types import Space
20
20
  from rewrite.python.tree import CompilationUnit
21
21
  from rewrite.python.visitor import PythonVisitor
22
+ from rewrite.java.tree import J
22
23
  from rewrite.java.tree import (
23
24
  Assignment,
24
25
  Block,
@@ -158,12 +159,15 @@ class RemoveSelfAssignment(Recipe):
158
159
  class Visitor(PythonVisitor[ExecutionContext]):
159
160
  def visit_block(
160
161
  self, block: Block, p: ExecutionContext
161
- ) -> Optional[Block]:
162
- block = super().visit_block(block, p)
163
- if not isinstance(block, Block) or not _in_function_scope(self.cursor):
162
+ ) -> J:
163
+ visited = super().visit_block(block, p)
164
+ if not isinstance(visited, Block):
165
+ return visited
166
+ block = visited
167
+ if not _in_function_scope(self.cursor):
164
168
  return block
165
169
  removed = _remove_self_assignments(
166
- block._statements, block.end, space_after_block(self.cursor)
170
+ block.padding.statements, block.end, space_after_block(self.cursor)
167
171
  )
168
172
  if removed is not None:
169
173
  return block.replace(_statements=removed[0], _end=removed[1])
@@ -289,14 +289,15 @@ class RemoveUnconditionalValueOverwrite(Recipe):
289
289
  class Visitor(PythonVisitor[ExecutionContext]):
290
290
  def visit_block(
291
291
  self, block: Block, p: ExecutionContext
292
- ) -> Optional[Block]:
293
- block = super().visit_block(block, p)
294
- if not isinstance(block, Block):
295
- return block
292
+ ) -> J:
293
+ visited = super().visit_block(block, p)
294
+ if not isinstance(visited, Block):
295
+ return visited
296
+ block = visited
296
297
  function = _enclosing_function(self.cursor)
297
298
  if function is None:
298
299
  return block
299
- removed = _remove_overwrites(block._statements, block.end, function)
300
+ removed = _remove_overwrites(block.padding.statements, block.end, function)
300
301
  if removed is not None:
301
302
  return block.replace(_statements=removed[0], _end=removed[1])
302
303
  return block