openrewrite-migrate-python 0.16.0.dev20261009101056__tar.gz → 0.16.0.dev20261009131002__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 (197) hide show
  1. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/PKG-INFO +1 -1
  2. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/pyproject.toml +1 -1
  3. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/__init__.py +35 -0
  4. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/__init__.py +207 -0
  5. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/_literals.py +23 -0
  6. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/assign_return.py +153 -0
  7. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/attr_access.py +234 -0
  8. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/boolean_simplification.py +910 -0
  9. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/collection_literals.py +389 -0
  10. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/comparison_simplification.py +311 -0
  11. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/complex_transforms.py +278 -0
  12. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/comprehension_cleanup.py +953 -0
  13. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/conditionals.py +859 -0
  14. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/datetime_cleanup.py +88 -0
  15. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/dict_cleanup.py +589 -0
  16. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/exception_cleanup.py +279 -0
  17. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/expression_simplification.py +450 -0
  18. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/logger_warn.py +89 -0
  19. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/loop_cleanup.py +174 -0
  20. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/merge_nested_with.py +181 -0
  21. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/merge_startswith_endswith.py +199 -0
  22. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/naming_conventions.py +291 -0
  23. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/negated_operators.py +161 -0
  24. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/none_and_identity.py +322 -0
  25. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/object_inheritance.py +89 -0
  26. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/pandas_cleanup.py +213 -0
  27. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/python_best_practices.py +269 -0
  28. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/range_cleanup.py +142 -0
  29. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/redundant_code.py +180 -0
  30. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/remove_trailing_return_none.py +167 -0
  31. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/string_cleanup.py +958 -0
  32. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/unreachable_code.py +440 -0
  33. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/use_items.py +143 -0
  34. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/use_list_clear.py +129 -0
  35. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/cleanup/yoda_conditions.py +140 -0
  36. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_code_quality_python/codequality/_trivia.py +24 -1
  37. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_code_quality_python/codequality/_truth_value.py +83 -0
  38. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_code_quality_python/codequality/boolean_checks_not_inverted.py +27 -48
  39. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_code_quality_python/codequality/simplify_boolean_literal.py +23 -15
  40. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/__init__.py +3 -0
  41. openrewrite_migrate_python-0.16.0.dev20261009131002/src/openrewrite_migrate_python/migrate/upgrade_to_pandas.py +51 -0
  42. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/upgrade_to_python39.py +10 -1
  43. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python.egg-info/PKG-INFO +1 -1
  44. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python.egg-info/SOURCES.txt +34 -0
  45. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_upgrade_recipes.py +22 -0
  46. openrewrite_migrate_python-0.16.0.dev20261009101056/src/openrewrite_code_quality_python/__init__.py +0 -35
  47. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/setup.cfg +0 -0
  48. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_code_quality_python/codequality/__init__.py +0 -0
  49. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_code_quality_python/codequality/_reindent.py +0 -0
  50. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_code_quality_python/codequality/_semantically_equal.py +0 -0
  51. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_code_quality_python/codequality/_side_effects.py +0 -0
  52. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_code_quality_python/codequality/all_branches_identical.py +0 -0
  53. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_code_quality_python/codequality/code_quality.py +0 -0
  54. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_code_quality_python/codequality/collapsible_if_statements.py +0 -0
  55. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_code_quality_python/codequality/find_suspicious_chained_comparison.py +0 -0
  56. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_code_quality_python/codequality/merge_identical_branches.py +0 -0
  57. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_code_quality_python/codequality/remove_duplicate_conditions.py +0 -0
  58. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_code_quality_python/codequality/remove_self_assignment.py +0 -0
  59. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_code_quality_python/codequality/remove_unconditional_value_overwrite.py +0 -0
  60. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_code_quality_python/codequality/simplify_redundant_logical_expression.py +0 -0
  61. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/__init__.py +0 -0
  62. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/_decorators.py +0 -0
  63. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/_langchain_tables.py +0 -0
  64. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/_markers.py +0 -0
  65. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/_method_renames.py +0 -0
  66. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/_module_imports.py +0 -0
  67. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/_slots.py +0 -0
  68. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/aifc_migrations.py +0 -0
  69. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/array_deprecations.py +0 -0
  70. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/ast_deprecations.py +0 -0
  71. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/asyncio_coroutine_to_async.py +0 -0
  72. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/asyncio_deprecations.py +0 -0
  73. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/avro_migrations.py +0 -0
  74. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/backoff_to_tenacity.py +0 -0
  75. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/calendar_deprecations.py +0 -0
  76. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/cgi_migrations.py +0 -0
  77. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/cgi_parse_deprecations.py +0 -0
  78. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/collections_abc_migrations.py +0 -0
  79. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/configparser_deprecations.py +0 -0
  80. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/datetime_utc.py +0 -0
  81. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/distutils_deprecations.py +0 -0
  82. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/distutils_migrations.py +0 -0
  83. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/functools_deprecations.py +0 -0
  84. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/future_imports.py +0 -0
  85. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/gettext_deprecations.py +0 -0
  86. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/html_parser_deprecations.py +0 -0
  87. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/imp_migrations.py +0 -0
  88. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/langchain_classic_imports.py +0 -0
  89. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/langchain_community_imports.py +0 -0
  90. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/langchain_provider_imports.py +0 -0
  91. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/locale_deprecations.py +0 -0
  92. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/locale_getdefaultlocale_deprecation.py +0 -0
  93. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/macpath_deprecations.py +0 -0
  94. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/mailcap_migrations.py +0 -0
  95. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/nntplib_migrations.py +0 -0
  96. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/os_deprecations.py +0 -0
  97. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/pathlib_deprecations.py +0 -0
  98. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/pep594_system_migrations.py +0 -0
  99. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/pipes_migrations.py +0 -0
  100. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/pkgutil_deprecations.py +0 -0
  101. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/platform_deprecations.py +0 -0
  102. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/pydantic_deprecations.py +0 -0
  103. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/pydantic_fields.py +0 -0
  104. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/pydantic_model_fields.py +0 -0
  105. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/re_deprecations.py +0 -0
  106. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/removed_modules_312.py +0 -0
  107. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/shutil_deprecations.py +0 -0
  108. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/socket_deprecations.py +0 -0
  109. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/ssl_deprecations.py +0 -0
  110. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/string_formatting.py +0 -0
  111. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/sys_deprecations.py +0 -0
  112. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/sys_last_deprecations.py +0 -0
  113. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/tarfile_deprecations.py +0 -0
  114. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/telnetlib_migrations.py +0 -0
  115. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/tempfile_deprecations.py +0 -0
  116. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/threading_deprecations.py +0 -0
  117. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/threading_is_alive_deprecation.py +0 -0
  118. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/typing_callable.py +0 -0
  119. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/typing_deprecations.py +0 -0
  120. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/typing_union_to_pipe.py +0 -0
  121. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/unittest_deprecations.py +0 -0
  122. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/upgrade_to_langchain02.py +0 -0
  123. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/upgrade_to_langchain1.py +0 -0
  124. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/upgrade_to_pydantic.py +0 -0
  125. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/upgrade_to_python310.py +0 -0
  126. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/upgrade_to_python311.py +0 -0
  127. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/upgrade_to_python312.py +0 -0
  128. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/upgrade_to_python313.py +0 -0
  129. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/upgrade_to_python314.py +0 -0
  130. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/upgrade_to_python38.py +0 -0
  131. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/urllib_deprecations.py +0 -0
  132. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/uu_migrations.py +0 -0
  133. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/xdrlib_migrations.py +0 -0
  134. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python/migrate/xml_deprecations.py +0 -0
  135. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python.egg-info/dependency_links.txt +0 -0
  136. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python.egg-info/entry_points.txt +0 -0
  137. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python.egg-info/requires.txt +0 -0
  138. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/src/openrewrite_migrate_python.egg-info/top_level.txt +0 -0
  139. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_aifc_migrations.py +0 -0
  140. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_array_deprecations.py +0 -0
  141. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_ast_deprecations.py +0 -0
  142. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_asyncio_coroutine_to_async.py +0 -0
  143. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_asyncio_deprecations.py +0 -0
  144. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_avro_migrations.py +0 -0
  145. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_backoff_to_tenacity.py +0 -0
  146. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_calendar_deprecations.py +0 -0
  147. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_cgi_parse_deprecations.py +0 -0
  148. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_change_import_recipes.py +0 -0
  149. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_collections_abc_migrations.py +0 -0
  150. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_configparser_deprecations.py +0 -0
  151. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_datetime_utc.py +0 -0
  152. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_distutils_deprecations.py +0 -0
  153. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_distutils_migrations.py +0 -0
  154. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_functools_deprecations.py +0 -0
  155. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_future_imports.py +0 -0
  156. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_gettext_deprecations.py +0 -0
  157. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_html_parser_deprecations.py +0 -0
  158. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_imp_migrations.py +0 -0
  159. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_langchain_classic_imports.py +0 -0
  160. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_langchain_community_imports.py +0 -0
  161. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_langchain_provider_imports.py +0 -0
  162. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_locale_deprecations.py +0 -0
  163. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_locale_getdefaultlocale_deprecation.py +0 -0
  164. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_macpath_deprecations.py +0 -0
  165. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_mailcap_migrations.py +0 -0
  166. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_markers.py +0 -0
  167. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_os_deprecations.py +0 -0
  168. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_pathlib_deprecations.py +0 -0
  169. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_pep594_migrations.py +0 -0
  170. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_pep594_system_migrations.py +0 -0
  171. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_pkgutil_deprecations.py +0 -0
  172. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_platform_deprecations.py +0 -0
  173. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_pydantic_deprecations.py +0 -0
  174. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_pydantic_fields.py +0 -0
  175. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_pydantic_model_fields.py +0 -0
  176. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_re_deprecations.py +0 -0
  177. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_removed_modules_312.py +0 -0
  178. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_shutil_deprecations.py +0 -0
  179. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_socket_deprecations.py +0 -0
  180. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_ssl_deprecations.py +0 -0
  181. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_string_formatting.py +0 -0
  182. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_sys_deprecations.py +0 -0
  183. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_sys_last_deprecations.py +0 -0
  184. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_tarfile_deprecations.py +0 -0
  185. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_tempfile_deprecations.py +0 -0
  186. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_threading_deprecations.py +0 -0
  187. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_threading_extended.py +0 -0
  188. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_threading_is_alive_deprecation.py +0 -0
  189. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_typing_alias_moves.py +0 -0
  190. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_typing_callable.py +0 -0
  191. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_typing_deprecations.py +0 -0
  192. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_typing_union_to_pipe.py +0 -0
  193. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_unittest_deprecations.py +0 -0
  194. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_upgrade_to_pydantic.py +0 -0
  195. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_urllib_deprecations.py +0 -0
  196. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_xdrlib_migrations.py +0 -0
  197. {openrewrite_migrate_python-0.16.0.dev20261009101056 → openrewrite_migrate_python-0.16.0.dev20261009131002}/tests/test_xml_deprecations.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openrewrite-migrate-python
3
- Version: 0.16.0.dev20261009101056
3
+ Version: 0.16.0.dev20261009131002
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
@@ -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.dev20261009101056" # Updated dynamically during release
8
+ version = "0.16.0.dev20261009131002" # 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"
@@ -0,0 +1,35 @@
1
+ """OpenRewrite recipes for Python code quality improvements."""
2
+
3
+ import importlib
4
+ import inspect
5
+ import pkgutil
6
+
7
+ from rewrite import Recipe, RecipeMarketplace
8
+
9
+ __all__ = ["activate"]
10
+
11
+
12
+ def activate(marketplace: RecipeMarketplace) -> None:
13
+ """
14
+ Install all code quality recipes into the marketplace.
15
+
16
+ This function is called by the OpenRewrite discovery mechanism when the
17
+ openrewrite-code-quality-python package is found via entry points.
18
+
19
+ Args:
20
+ marketplace: The RecipeMarketplace to install recipes into
21
+ """
22
+ from rewrite.decorators import get_recipe_category
23
+
24
+ from . import cleanup as cleanup_pkg
25
+ from . import codequality as codequality_pkg
26
+
27
+ # Auto-discover all Recipe subclasses from the codequality and cleanup packages
28
+ for pkg in (codequality_pkg, cleanup_pkg):
29
+ for module_info in pkgutil.walk_packages(pkg.__path__, prefix=pkg.__name__ + "."):
30
+ module = importlib.import_module(module_info.name)
31
+ for _name, obj in inspect.getmembers(module, inspect.isclass):
32
+ if issubclass(obj, Recipe) and obj is not Recipe and obj.__module__ == module.__name__:
33
+ category = get_recipe_category(obj)
34
+ if category is not None:
35
+ marketplace.install(obj, category)
@@ -0,0 +1,207 @@
1
+ """Python cleanup recipes."""
2
+
3
+ from .assign_return import RemoveUnnecessaryAssign
4
+ from .attr_access import (
5
+ ReplaceGetAttrWithConstant,
6
+ ReplaceSetAttrWithConstant,
7
+ )
8
+ from .boolean_simplification import (
9
+ BooleanIfExpIdentity,
10
+ CollectionToBool,
11
+ DeMorgan,
12
+ RemoveRedundantBoolean,
13
+ SimplifyBooleanReturn,
14
+ SimplifyLenComparison,
15
+ )
16
+ from .collection_literals import (
17
+ CollectionIntoSet,
18
+ DictLiteral,
19
+ ListLiteral,
20
+ TupleLiteral,
21
+ UnwrapIterableConstruction,
22
+ )
23
+ from .comparison_simplification import (
24
+ ChainCompares,
25
+ MergeComparisons,
26
+ SimplifySubstringSearch,
27
+ )
28
+ from .complex_transforms import (
29
+ SwapVariable,
30
+ TernaryToIfExpression,
31
+ )
32
+ from .comprehension_cleanup import (
33
+ CollectionBuiltinToComprehension,
34
+ ComprehensionToGenerator,
35
+ ConvertAnyToIn,
36
+ IdentityComprehension,
37
+ InvertAnyAll,
38
+ InvertAnyAllBody,
39
+ SimplifyConstantSum,
40
+ SimplifyGenerator,
41
+ )
42
+ from .conditionals import (
43
+ AssignIfExp,
44
+ MergeElseIfIntoElif,
45
+ MergeIsinstance,
46
+ RemovePassElif,
47
+ RemoveRedundantIf,
48
+ RemoveUnnecessaryElse,
49
+ SwapIfElseBranches,
50
+ )
51
+ from .datetime_cleanup import UseDatetimeNowNotToday
52
+ from .dict_cleanup import (
53
+ RemoveDictKeys,
54
+ RemoveDuplicateDictKey,
55
+ RemoveDuplicateSetKey,
56
+ RemoveRedundantConstructorInDictUnion,
57
+ SimplifyDictionaryUpdate,
58
+ UseDictionaryUnion,
59
+ )
60
+ from .exception_cleanup import (
61
+ RaiseFromPreviousError,
62
+ SimplifySingleExceptionTuple,
63
+ )
64
+ from .expression_simplification import (
65
+ AugAssign,
66
+ OrIfExpIdentity,
67
+ RemoveRedundantSliceIndex,
68
+ SimplifyNegativeIndex,
69
+ SwapIfExpression,
70
+ )
71
+ from .logger_warn import ReplaceLoggerWarn
72
+ from .loop_cleanup import UselessElseOnLoop
73
+ from .merge_nested_with import MergeNestedWithStatements
74
+ from .merge_startswith_endswith import MergeStartswithEndswith
75
+ from .naming_conventions import (
76
+ ClassMethodFirstArgName,
77
+ InstanceMethodFirstArgName,
78
+ )
79
+ from .negated_operators import (
80
+ ReplaceNotInTest,
81
+ ReplaceNotIsTest,
82
+ )
83
+ from .none_and_identity import (
84
+ BinOpIdentity,
85
+ EqualityIdentity,
86
+ NoneCompare,
87
+ SquareIdentity,
88
+ )
89
+ from .object_inheritance import RemoveUselessObjectInheritance
90
+ from .pandas_cleanup import (
91
+ DataframeAppendToConcat,
92
+ ReplaceApplyWithMethodCall,
93
+ )
94
+ from .python_best_practices import PythonBestPractices
95
+ from .range_cleanup import (
96
+ RemoveUnitStepFromRange,
97
+ RemoveZeroFromRange,
98
+ )
99
+ from .redundant_code import (
100
+ RemoveRedundantContinue,
101
+ RemoveRedundantPathExists,
102
+ )
103
+ from .remove_trailing_return_none import RemoveTrailingReturnNone
104
+ from .string_cleanup import (
105
+ RemoveNoneFromDefaultGet,
106
+ RemoveRedundantFstring,
107
+ RemoveStrFromFstring,
108
+ RemoveStrFromPrint,
109
+ SimplifyFstringFormatting,
110
+ StrPrefixSuffix,
111
+ UseGetitemForReMatchGroups,
112
+ UseStringRemoveAffix,
113
+ )
114
+ from .unreachable_code import (
115
+ RemoveAssertTrue,
116
+ RemoveEmptyNestedBlock,
117
+ RemoveUnreachableCode,
118
+ )
119
+ from .use_items import UseItemsForKeyValueIteration
120
+ from .use_list_clear import UseListClear
121
+ from .yoda_conditions import ReplaceYodaConditions
122
+
123
+ __all__ = [
124
+ "AssignIfExp",
125
+ "AugAssign",
126
+ "BinOpIdentity",
127
+ "BooleanIfExpIdentity",
128
+ "ChainCompares",
129
+ "ClassMethodFirstArgName",
130
+ "CollectionBuiltinToComprehension",
131
+ "CollectionIntoSet",
132
+ "CollectionToBool",
133
+ "ComprehensionToGenerator",
134
+ "ConvertAnyToIn",
135
+ "DataframeAppendToConcat",
136
+ "DeMorgan",
137
+ "DictLiteral",
138
+ "EqualityIdentity",
139
+ "IdentityComprehension",
140
+ "InstanceMethodFirstArgName",
141
+ "InvertAnyAll",
142
+ "InvertAnyAllBody",
143
+ "ListLiteral",
144
+ "MergeComparisons",
145
+ "MergeElseIfIntoElif",
146
+ "MergeIsinstance",
147
+ "MergeNestedWithStatements",
148
+ "MergeStartswithEndswith",
149
+ "NoneCompare",
150
+ "OrIfExpIdentity",
151
+ "PythonBestPractices",
152
+ "RaiseFromPreviousError",
153
+ "RemoveAssertTrue",
154
+ "RemoveDictKeys",
155
+ "RemoveDuplicateDictKey",
156
+ "RemoveDuplicateSetKey",
157
+ "RemoveEmptyNestedBlock",
158
+ "RemoveNoneFromDefaultGet",
159
+ "RemovePassElif",
160
+ "RemoveRedundantBoolean",
161
+ "RemoveRedundantConstructorInDictUnion",
162
+ "RemoveRedundantContinue",
163
+ "RemoveRedundantFstring",
164
+ "RemoveRedundantIf",
165
+ "RemoveRedundantPathExists",
166
+ "RemoveRedundantSliceIndex",
167
+ "RemoveStrFromFstring",
168
+ "RemoveStrFromPrint",
169
+ "RemoveTrailingReturnNone",
170
+ "RemoveUnitStepFromRange",
171
+ "RemoveUnnecessaryAssign",
172
+ "RemoveUnnecessaryElse",
173
+ "RemoveUnreachableCode",
174
+ "RemoveUselessObjectInheritance",
175
+ "RemoveZeroFromRange",
176
+ "ReplaceApplyWithMethodCall",
177
+ "ReplaceGetAttrWithConstant",
178
+ "ReplaceLoggerWarn",
179
+ "ReplaceNotInTest",
180
+ "ReplaceNotIsTest",
181
+ "ReplaceSetAttrWithConstant",
182
+ "ReplaceYodaConditions",
183
+ "SimplifyBooleanReturn",
184
+ "SimplifyConstantSum",
185
+ "SimplifyDictionaryUpdate",
186
+ "SimplifyFstringFormatting",
187
+ "SimplifyGenerator",
188
+ "SimplifyLenComparison",
189
+ "SimplifyNegativeIndex",
190
+ "SimplifySingleExceptionTuple",
191
+ "SimplifySubstringSearch",
192
+ "SquareIdentity",
193
+ "StrPrefixSuffix",
194
+ "SwapIfElseBranches",
195
+ "SwapIfExpression",
196
+ "SwapVariable",
197
+ "TernaryToIfExpression",
198
+ "TupleLiteral",
199
+ "UnwrapIterableConstruction",
200
+ "UseDatetimeNowNotToday",
201
+ "UseDictionaryUnion",
202
+ "UseGetitemForReMatchGroups",
203
+ "UseItemsForKeyValueIteration",
204
+ "UseListClear",
205
+ "UseStringRemoveAffix",
206
+ "UselessElseOnLoop",
207
+ ]
@@ -0,0 +1,23 @@
1
+ """Classify literals by their source text, which tells `str` from `bytes` where the type does not."""
2
+
3
+ from typing import Any
4
+
5
+ from rewrite.java.tree import Literal
6
+
7
+
8
+ def _prefix(source: str) -> str:
9
+ return source[:len(source) - len(source.lstrip("bBrRuU"))]
10
+
11
+
12
+ def is_string_literal(expr: Any) -> bool:
13
+ """Whether ``expr`` is a ``str`` or ``bytes`` literal, prefixed or not."""
14
+ if not isinstance(expr, Literal) or not expr.value_source:
15
+ return False
16
+ source = expr.value_source
17
+ prefix = _prefix(source)
18
+ return len(prefix) <= 2 and source[len(prefix):len(prefix) + 1] in ('"', "'")
19
+
20
+
21
+ def is_bytes_literal(expr: Literal) -> bool:
22
+ """Whether ``expr`` is a ``b``-prefixed literal, which the parser types as ``str``."""
23
+ return "b" in _prefix(expr.value_source or "").lower()
@@ -0,0 +1,153 @@
1
+ """Recipe for RET504: Remove unnecessary assignment before return.
2
+
3
+ Detects the pattern where a variable is assigned and then immediately
4
+ returned, replacing it with a direct return of the expression.
5
+
6
+ Example:
7
+ Before:
8
+ def foo():
9
+ x = expr
10
+ return x
11
+
12
+ After:
13
+ def foo():
14
+ return expr
15
+
16
+ See: https://docs.astral.sh/ruff/rules/unnecessary-assign/
17
+ """
18
+
19
+ from typing import Any, List
20
+
21
+ from rewrite import ExecutionContext, Recipe, TreeVisitor
22
+ from rewrite.category import CategoryDescriptor
23
+ from rewrite.decorators import categorize
24
+ from rewrite.execution import InMemoryExecutionContext
25
+ from rewrite.marketplace import Python
26
+ from rewrite.python.tree import StatementExpression
27
+ from rewrite.python.visitor import PythonVisitor
28
+ from rewrite.java.tree import Assignment, Block, Identifier, J, MethodDeclaration, Return
29
+
30
+
31
+ _Cleanup = [*Python, CategoryDescriptor(display_name="Cleanup")]
32
+
33
+
34
+ @categorize(_Cleanup)
35
+ class RemoveUnnecessaryAssign(Recipe):
36
+ """
37
+ Remove unnecessary variable assignment before return.
38
+
39
+ When a variable is assigned a value and then immediately returned
40
+ with no other uses, the assignment is unnecessary and the expression
41
+ can be returned directly.
42
+
43
+ Example:
44
+ Before:
45
+ def foo():
46
+ result = compute()
47
+ return result
48
+
49
+ After:
50
+ def foo():
51
+ return compute()
52
+ """
53
+
54
+ @property
55
+ def name(self) -> str:
56
+ return "org.openrewrite.python.cleanup.RemoveUnnecessaryAssign"
57
+
58
+ @property
59
+ def display_name(self) -> str:
60
+ return "Remove unnecessary assignment before return"
61
+
62
+ @property
63
+ def description(self) -> str:
64
+ return (
65
+ "Return the value directly where a variable is assigned and then "
66
+ "immediately returned. A name that appears anywhere else in "
67
+ "the function, a `yield` value, and a comment before the `return` are left alone."
68
+ )
69
+
70
+ @property
71
+ def tags(self) -> List[str]:
72
+ return ["python", "cleanup", "ruff", "RET504"]
73
+
74
+ def editor(self) -> TreeVisitor[Any, ExecutionContext]:
75
+ class Visitor(PythonVisitor[ExecutionContext]):
76
+ def visit_block(self, block: Block, p: ExecutionContext) -> J:
77
+ visited = super().visit_block(block, p)
78
+ if not isinstance(visited, Block):
79
+ return visited
80
+ block = visited
81
+
82
+ stmts = block.statements
83
+ if len(stmts) < 2:
84
+ return block
85
+
86
+ # Only check the last two statements in the block
87
+ i = len(stmts) - 2
88
+ assign_stmt = stmts[i]
89
+ return_stmt = stmts[i + 1]
90
+
91
+ if not isinstance(assign_stmt, Assignment):
92
+ return block
93
+ if not isinstance(return_stmt, Return):
94
+ return block
95
+
96
+ # Check that the assignment target is a simple identifier
97
+ if not isinstance(assign_stmt.variable, Identifier):
98
+ return block
99
+ assign_name = assign_stmt.variable.simple_name
100
+
101
+ # Check that the return expression is the same identifier
102
+ returned = return_stmt.expression
103
+ if not isinstance(returned, Identifier) or returned.simple_name != assign_name:
104
+ return block
105
+
106
+ # A handler, a closure or a global/nonlocal binding may read the value,
107
+ # so only the assignment and the return may name it.
108
+ method = self.cursor.first_enclosing(MethodDeclaration)
109
+ if method is None or count_mentions(method, assign_name) != 2:
110
+ return block
111
+ if isinstance(assign_stmt.assignment, StatementExpression):
112
+ return block
113
+ if return_stmt.prefix.comments:
114
+ return block
115
+
116
+ # Build the new return statement with the assignment's RHS
117
+ # Preserve the prefix (whitespace) from the assignment statement
118
+ rhs = assign_stmt.assignment
119
+ new_return = return_stmt.replace(
120
+ _prefix=assign_stmt.prefix,
121
+ _expression=rhs,
122
+ )
123
+
124
+ # Build new padded statement list: remove assignment, replace return
125
+ padded_stmts = block.padding.statements
126
+ new_padded = []
127
+ for j, ps in enumerate(padded_stmts):
128
+ if j == i:
129
+ continue
130
+ elif j == i + 1:
131
+ new_padded.append(ps.replace(element=new_return))
132
+ else:
133
+ new_padded.append(ps)
134
+
135
+ return block.padding.replace(_statements=new_padded)
136
+
137
+ return Visitor()
138
+
139
+
140
+ def count_mentions(tree: J, name: str) -> int:
141
+ """How many identifiers in ``tree`` spell ``name``."""
142
+
143
+ class NameCounter(PythonVisitor[ExecutionContext]):
144
+ count = 0
145
+
146
+ def visit_identifier(self, ident: Identifier, p: ExecutionContext) -> J:
147
+ if ident.simple_name == name:
148
+ self.count += 1
149
+ return ident
150
+
151
+ counter = NameCounter()
152
+ counter.visit(tree, InMemoryExecutionContext())
153
+ return counter.count
@@ -0,0 +1,234 @@
1
+ """
2
+ Recipes that replace ``getattr()`` / ``setattr()`` calls with direct attribute
3
+ access or assignment when the attribute name is a constant valid identifier.
4
+
5
+ - ``getattr(x, "attr")`` becomes ``x.attr`` (B009)
6
+ - ``setattr(x, "attr", val)`` becomes ``x.attr = val`` (B010)
7
+
8
+ See:
9
+ - https://docs.astral.sh/ruff/rules/getattr-with-constant/
10
+ - https://docs.astral.sh/ruff/rules/set-attr-with-constant/
11
+ """
12
+
13
+ import keyword
14
+ from functools import lru_cache
15
+ from typing import Any, List, Optional
16
+
17
+ from rewrite import ExecutionContext, Preconditions, Recipe, TreeVisitor
18
+ from rewrite.category import CategoryDescriptor
19
+ from rewrite.decorators import categorize
20
+ from rewrite.markers import Markers
21
+ from rewrite.marketplace import Python
22
+ from rewrite.python.method_matcher import MethodMatcher
23
+ from rewrite.python.preconditions import uses_method
24
+ from rewrite.python.visitor import PythonVisitor
25
+ from rewrite.python.template import Template, template, capture
26
+ from rewrite.java.support_types import JLeftPadded, Space
27
+ from rewrite.java.tree import (
28
+ ArrayAccess,
29
+ Block,
30
+ FieldAccess,
31
+ Identifier,
32
+ J,
33
+ Literal,
34
+ MethodInvocation,
35
+ Parentheses,
36
+ )
37
+ from rewrite.python.tree import CompilationUnit
38
+ from rewrite.utils import random_id
39
+
40
+ from openrewrite_code_quality_python.codequality._side_effects import is_side_effect_free
41
+ from openrewrite_code_quality_python.codequality._trivia import has_comments
42
+
43
+ _Cleanup = [*Python, CategoryDescriptor(display_name="Cleanup")]
44
+
45
+ _GETATTR_PATTERN = "builtins getattr(..)"
46
+ _SETATTR_PATTERN = "builtins setattr(..)"
47
+ _GETATTR = MethodMatcher.create(_GETATTR_PATTERN)
48
+ _SETATTR = MethodMatcher.create(_SETATTR_PATTERN)
49
+
50
+ _obj = capture('obj')
51
+ _val = capture('val')
52
+
53
+
54
+ @lru_cache(maxsize=None)
55
+ def _assignment_template(attr_name: str) -> Template:
56
+ return template(f"{_obj}.{attr_name} = {_val}")
57
+
58
+
59
+ def _constant_attribute_name(method: MethodInvocation) -> Optional[str]:
60
+ """The attribute name a builtin ``getattr``/``setattr`` call spells as a literal,
61
+ when attribute syntax reads the same attribute."""
62
+ attr_arg = method.arguments[1]
63
+ attr_name = attr_arg.value if isinstance(attr_arg, Literal) else None
64
+ if (
65
+ not isinstance(attr_name, str)
66
+ or not attr_name.isidentifier()
67
+ or keyword.iskeyword(attr_name)
68
+ # Attribute syntax NFKC-normalizes a non-ASCII name, `getattr` does not.
69
+ or not attr_name.isascii()
70
+ # Inside a class `self.__x` is mangled to `self._Class__x`, but
71
+ # `getattr(self, "__x")` looks up the literal `__x`.
72
+ or (attr_name.startswith('__') and not attr_name.endswith('__'))
73
+ or has_comments(method.replace(_prefix=Space.EMPTY))
74
+ ):
75
+ return None
76
+ return attr_name
77
+
78
+
79
+ @categorize(_Cleanup)
80
+ class ReplaceGetAttrWithConstant(Recipe):
81
+ """
82
+ Replace `getattr(x, "attr")` with `x.attr`.
83
+
84
+ The `getattr()` builtin with a constant string attribute name that is a
85
+ valid Python identifier can be replaced with direct attribute access for
86
+ clarity and brevity.
87
+
88
+ Only applies when:
89
+ - There are exactly 2 arguments (no default value)
90
+ - The second argument is a string literal
91
+ - The string value is an ASCII Python identifier (not a keyword)
92
+ - The object is a name, attribute, call, subscript or parenthesized expression
93
+
94
+ Example:
95
+ Before:
96
+ result = getattr(obj, "name")
97
+
98
+ After:
99
+ result = obj.name
100
+ """
101
+
102
+ @property
103
+ def name(self) -> str:
104
+ return "org.openrewrite.python.cleanup.ReplaceGetAttrWithConstant"
105
+
106
+ @property
107
+ def display_name(self) -> str:
108
+ return "Replace `getattr(x, 'attr')` with `x.attr`"
109
+
110
+ @property
111
+ def description(self) -> str:
112
+ return (
113
+ "Replace `getattr(x, \"attr\")` calls with `x.attr` when the attribute "
114
+ "name is a constant string that is a valid Python identifier. "
115
+ "It leaves alone a shadowed `getattr`, a non-ASCII or name-mangled name, "
116
+ "an object that would need parentheses, and a call holding comments."
117
+ )
118
+
119
+ @property
120
+ def tags(self) -> List[str]:
121
+ return ["python", "cleanup", "ruff", "B009"]
122
+
123
+ def editor(self) -> TreeVisitor[Any, ExecutionContext]:
124
+ class Visitor(PythonVisitor[ExecutionContext]):
125
+ def visit_method_invocation(
126
+ self, method: MethodInvocation, p: ExecutionContext
127
+ ) -> J:
128
+ m = super().visit_method_invocation(method, p)
129
+ if (
130
+ not isinstance(m, MethodInvocation)
131
+ or not _GETATTR.matches(m, cursor=self.cursor)
132
+ or len(m.arguments) != 2
133
+ ):
134
+ return m
135
+ attr_name = _constant_attribute_name(m)
136
+ obj_expr = m.arguments[0]
137
+ if attr_name is None or not isinstance(
138
+ obj_expr, (Identifier, FieldAccess, MethodInvocation, ArrayAccess, Parentheses)
139
+ ):
140
+ return m
141
+
142
+ attr_identifier = Identifier(
143
+ _id=random_id(),
144
+ _prefix=Space.EMPTY,
145
+ _markers=Markers.EMPTY,
146
+ _annotations=[],
147
+ _simple_name=attr_name,
148
+ _type=None,
149
+ _field_type=None,
150
+ )
151
+ return FieldAccess(
152
+ _id=random_id(),
153
+ _prefix=m.prefix,
154
+ _markers=Markers.EMPTY,
155
+ _target=obj_expr.replace(_prefix=Space.EMPTY),
156
+ _name=JLeftPadded(
157
+ _before=Space.EMPTY,
158
+ _element=attr_identifier,
159
+ _markers=Markers.EMPTY,
160
+ ),
161
+ _type=None,
162
+ )
163
+
164
+ return Preconditions.check(uses_method(_GETATTR_PATTERN), Visitor())
165
+
166
+
167
+ @categorize(_Cleanup)
168
+ class ReplaceSetAttrWithConstant(Recipe):
169
+ """
170
+ Replace `setattr(x, "attr", value)` with `x.attr = value`.
171
+
172
+ When `setattr()` is called as a statement with a constant string attribute
173
+ name that is a valid Python identifier, it can be replaced with a direct
174
+ attribute assignment for better readability.
175
+
176
+ Example:
177
+ Before:
178
+ setattr(obj, "name", value)
179
+
180
+ After:
181
+ obj.name = value
182
+ """
183
+
184
+ @property
185
+ def name(self) -> str:
186
+ return "org.openrewrite.python.cleanup.ReplaceSetAttrWithConstant"
187
+
188
+ @property
189
+ def display_name(self) -> str:
190
+ return "Replace `setattr()` with constant attribute assignment"
191
+
192
+ @property
193
+ def description(self) -> str:
194
+ return (
195
+ "Replace a `setattr(x, \"attr\", value)` statement with `x.attr = value` "
196
+ "when the attribute name is a constant valid Python identifier. "
197
+ "It leaves alone a shadowed `setattr`, a non-ASCII or name-mangled name, "
198
+ "a call used as an expression, a call holding comments, and an object or value "
199
+ "that may have side effects, since the assignment evaluates the value first."
200
+ )
201
+
202
+ @property
203
+ def tags(self) -> List[str]:
204
+ return ["python", "cleanup", "ruff", "B010"]
205
+
206
+ def editor(self) -> TreeVisitor[Any, ExecutionContext]:
207
+ class Visitor(PythonVisitor[ExecutionContext]):
208
+ def visit_method_invocation(
209
+ self, method: MethodInvocation, p: ExecutionContext
210
+ ) -> J:
211
+ m = super().visit_method_invocation(method, p)
212
+ if (
213
+ not isinstance(m, MethodInvocation)
214
+ or not _SETATTR.matches(m, cursor=self.cursor)
215
+ or len(m.arguments) != 3
216
+ or not isinstance(
217
+ self.cursor.parent_tree_cursor().value, (Block, CompilationUnit)
218
+ )
219
+ ):
220
+ return m
221
+ attr_name = _constant_attribute_name(m)
222
+ obj_expr, _, val_expr = m.arguments
223
+ if (
224
+ attr_name is None
225
+ or not is_side_effect_free(obj_expr)
226
+ or not is_side_effect_free(val_expr)
227
+ ):
228
+ return m
229
+
230
+ return _assignment_template(attr_name).apply(
231
+ self.cursor, values={'obj': obj_expr, 'val': val_expr}
232
+ ) or m
233
+
234
+ return Preconditions.check(uses_method(_SETATTR_PATTERN), Visitor())