openrewrite-migrate-python 0.12.0.dev20260811172040__tar.gz → 0.13.0__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 (144) hide show
  1. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/PKG-INFO +2 -2
  2. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/pyproject.toml +6 -7
  3. openrewrite_migrate_python-0.13.0/src/openrewrite_code_quality_python/codequality/find_suspicious_chained_comparison.py +122 -0
  4. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/typing_deprecations.py +5 -15
  5. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python.egg-info/PKG-INFO +2 -2
  6. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python.egg-info/SOURCES.txt +1 -0
  7. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python.egg-info/requires.txt +1 -1
  8. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_typing_alias_moves.py +32 -0
  9. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_typing_deprecations.py +93 -0
  10. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_upgrade_recipes.py +104 -0
  11. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/setup.cfg +0 -0
  12. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_code_quality_python/__init__.py +0 -0
  13. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_code_quality_python/codequality/__init__.py +0 -0
  14. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_code_quality_python/codequality/_semantically_equal.py +0 -0
  15. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_code_quality_python/codequality/all_branches_identical.py +0 -0
  16. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_code_quality_python/codequality/boolean_checks_not_inverted.py +0 -0
  17. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_code_quality_python/codequality/collapsible_if_statements.py +0 -0
  18. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_code_quality_python/codequality/merge_identical_branches.py +0 -0
  19. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_code_quality_python/codequality/remove_duplicate_conditions.py +0 -0
  20. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_code_quality_python/codequality/remove_self_assignment.py +0 -0
  21. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_code_quality_python/codequality/remove_unconditional_value_overwrite.py +0 -0
  22. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_code_quality_python/codequality/simplify_boolean_literal.py +0 -0
  23. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_code_quality_python/codequality/simplify_redundant_logical_expression.py +0 -0
  24. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/__init__.py +0 -0
  25. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/__init__.py +0 -0
  26. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/_import_hygiene.py +0 -0
  27. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/_markers.py +0 -0
  28. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/_typing_imports.py +0 -0
  29. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/aifc_migrations.py +0 -0
  30. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/array_deprecations.py +0 -0
  31. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/ast_deprecations.py +0 -0
  32. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/asyncio_coroutine_to_async.py +0 -0
  33. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/asyncio_deprecations.py +0 -0
  34. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/avro_migrations.py +0 -0
  35. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/calendar_deprecations.py +0 -0
  36. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/cgi_migrations.py +0 -0
  37. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/cgi_parse_deprecations.py +0 -0
  38. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/collections_abc_migrations.py +0 -0
  39. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/configparser_deprecations.py +0 -0
  40. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/datetime_utc.py +0 -0
  41. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/distutils_deprecations.py +0 -0
  42. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/distutils_migrations.py +0 -0
  43. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/functools_deprecations.py +0 -0
  44. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/future_imports.py +0 -0
  45. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/gettext_deprecations.py +0 -0
  46. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/html_parser_deprecations.py +0 -0
  47. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/imp_migrations.py +0 -0
  48. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/langchain_classic_imports.py +0 -0
  49. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/langchain_community_imports.py +0 -0
  50. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/langchain_provider_imports.py +0 -0
  51. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/locale_deprecations.py +0 -0
  52. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/locale_getdefaultlocale_deprecation.py +0 -0
  53. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/macpath_deprecations.py +0 -0
  54. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/mailcap_migrations.py +0 -0
  55. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/nntplib_migrations.py +0 -0
  56. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/os_deprecations.py +0 -0
  57. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/pathlib_deprecations.py +0 -0
  58. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/pep594_system_migrations.py +0 -0
  59. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/pipes_migrations.py +0 -0
  60. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/pkgutil_deprecations.py +0 -0
  61. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/platform_deprecations.py +0 -0
  62. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/pydantic_deprecations.py +0 -0
  63. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/pydantic_fields.py +0 -0
  64. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/pydantic_model_fields.py +0 -0
  65. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/re_deprecations.py +0 -0
  66. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/removed_modules_312.py +0 -0
  67. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/shutil_deprecations.py +0 -0
  68. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/socket_deprecations.py +0 -0
  69. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/ssl_deprecations.py +0 -0
  70. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/string_formatting.py +0 -0
  71. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/sys_deprecations.py +0 -0
  72. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/sys_last_deprecations.py +0 -0
  73. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/tarfile_deprecations.py +0 -0
  74. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/telnetlib_migrations.py +0 -0
  75. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/tempfile_deprecations.py +0 -0
  76. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/threading_deprecations.py +0 -0
  77. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/threading_is_alive_deprecation.py +0 -0
  78. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/typing_callable.py +0 -0
  79. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/typing_union_to_pipe.py +0 -0
  80. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/unittest_deprecations.py +0 -0
  81. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/upgrade_to_langchain02.py +0 -0
  82. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/upgrade_to_langchain1.py +0 -0
  83. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/upgrade_to_pydantic.py +0 -0
  84. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python310.py +0 -0
  85. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python311.py +0 -0
  86. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python312.py +0 -0
  87. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python313.py +0 -0
  88. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python314.py +0 -0
  89. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python38.py +0 -0
  90. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python39.py +0 -0
  91. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/urllib_deprecations.py +0 -0
  92. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/uu_migrations.py +0 -0
  93. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/xdrlib_migrations.py +0 -0
  94. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python/migrate/xml_deprecations.py +0 -0
  95. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python.egg-info/dependency_links.txt +0 -0
  96. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python.egg-info/entry_points.txt +0 -0
  97. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/src/openrewrite_migrate_python.egg-info/top_level.txt +0 -0
  98. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_aifc_migrations.py +0 -0
  99. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_array_deprecations.py +0 -0
  100. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_ast_deprecations.py +0 -0
  101. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_asyncio_coroutine_to_async.py +0 -0
  102. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_asyncio_deprecations.py +0 -0
  103. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_avro_migrations.py +0 -0
  104. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_calendar_deprecations.py +0 -0
  105. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_cgi_parse_deprecations.py +0 -0
  106. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_change_import_recipes.py +0 -0
  107. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_collections_abc_migrations.py +0 -0
  108. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_configparser_deprecations.py +0 -0
  109. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_datetime_utc.py +0 -0
  110. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_distutils_deprecations.py +0 -0
  111. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_future_imports.py +0 -0
  112. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_gettext_deprecations.py +0 -0
  113. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_html_parser_deprecations.py +0 -0
  114. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_imp_migrations.py +0 -0
  115. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_langchain_classic_imports.py +0 -0
  116. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_langchain_community_imports.py +0 -0
  117. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_langchain_provider_imports.py +0 -0
  118. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_locale_deprecations.py +0 -0
  119. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_locale_getdefaultlocale_deprecation.py +0 -0
  120. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_macpath_deprecations.py +0 -0
  121. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_os_deprecations.py +0 -0
  122. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_pep594_migrations.py +0 -0
  123. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_pep594_system_migrations.py +0 -0
  124. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_pkgutil_deprecations.py +0 -0
  125. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_platform_deprecations.py +0 -0
  126. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_pydantic_deprecations.py +0 -0
  127. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_pydantic_fields.py +0 -0
  128. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_pydantic_model_fields.py +0 -0
  129. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_re_deprecations.py +0 -0
  130. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_removed_modules_312.py +0 -0
  131. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_shutil_deprecations.py +0 -0
  132. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_ssl_deprecations.py +0 -0
  133. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_string_formatting.py +0 -0
  134. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_sys_deprecations.py +0 -0
  135. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_sys_last_deprecations.py +0 -0
  136. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_tarfile_deprecations.py +0 -0
  137. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_threading_deprecations.py +0 -0
  138. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_threading_extended.py +0 -0
  139. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_threading_is_alive_deprecation.py +0 -0
  140. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_typing_callable.py +0 -0
  141. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_typing_union_to_pipe.py +0 -0
  142. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_unittest_deprecations.py +0 -0
  143. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/tests/test_upgrade_to_pydantic.py +0 -0
  144. {openrewrite_migrate_python-0.12.0.dev20260811172040 → openrewrite_migrate_python-0.13.0}/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.12.0.dev20260811172040
3
+ Version: 0.13.0
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
@@ -21,7 +21,7 @@ Classifier: Typing :: Typed
21
21
  Requires-Python: >=3.10
22
22
  Description-Content-Type: text/markdown
23
23
  Provides-Extra: dev
24
- Requires-Dist: openrewrite>=8.84.3; extra == "dev"
24
+ Requires-Dist: openrewrite>=8.89.1; extra == "dev"
25
25
  Requires-Dist: pydantic>=2.11; extra == "dev"
26
26
  Requires-Dist: pytest>=8.0.0; extra == "dev"
27
27
  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.12.0.dev20260811172040" # Updated dynamically during release
8
+ version = "0.13.0" # 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"
@@ -30,12 +30,11 @@ dependencies = []
30
30
 
31
31
  [project.optional-dependencies]
32
32
  dev = [
33
- # 8.84.3 brings ty external-type resolution (cross-package supertype chains),
34
- # J.MethodInvocation.type, sorted insertion in maybe_add_import, and the
35
- # type_utils comparison helpers all of which the recipes rely on for
36
- # type-aware matching. openrewrite is host-provided at runtime, so this floor
37
- # only affects dev/CI.
38
- "openrewrite>=8.84.3",
33
+ # 8.89.1 for `python.scope_utils.LocalBindings`, which tells a local apart from a
34
+ # reference to an import: the PEP 585 recipes use it directly, and `ChangeImport`
35
+ # and `RemoveImport` need it to see references inside functions. openrewrite is
36
+ # host-provided at runtime, so this floor only affects dev/CI.
37
+ "openrewrite>=8.89.1",
39
38
  # Needed so type-attribution tests can resolve `pydantic` types.
40
39
  "pydantic>=2.11",
41
40
  "pytest>=8.0.0",
@@ -0,0 +1,122 @@
1
+ """
2
+ Recipe to find suspicious chained comparisons with conflicting direction.
3
+
4
+ Python evaluates ``a < b < c`` as ``(a < b) and (b < c)``. When the two
5
+ links point in opposite directions--one of ``<``/``<=`` and the other of
6
+ ``>``/``>=``--the chain is almost always a mistake, e.g. ``0 <= x >= 10``
7
+ was likely meant to be ``0 <= x <= 10``. This is a search recipe: the
8
+ intent is ambiguous, so it flags the expression rather than rewriting it.
9
+ """
10
+
11
+ from typing import Any, List, Optional
12
+
13
+ from rewrite import ExecutionContext, Recipe, TreeVisitor
14
+ from rewrite.category import CategoryDescriptor
15
+ from rewrite.decorators import categorize
16
+ from rewrite.marketplace import Python
17
+ from rewrite.markers import Markers, SearchResult
18
+ from rewrite.python.visitor import PythonVisitor
19
+ from rewrite.java.tree import Binary as JBinary, Expression
20
+ from rewrite.utils import random_id
21
+
22
+ _CodeQuality = [
23
+ *Python,
24
+ CategoryDescriptor(display_name="Code quality"),
25
+ ]
26
+
27
+ _LESS = (JBinary.Type.LessThan, JBinary.Type.LessThanOrEqual)
28
+ _GREATER = (JBinary.Type.GreaterThan, JBinary.Type.GreaterThanOrEqual)
29
+
30
+
31
+ def _direction(operator: JBinary.Type) -> Optional[str]:
32
+ """Classify an ordering operator as ``"less"``, ``"greater"``, or None."""
33
+ if operator in _LESS:
34
+ return "less"
35
+ if operator in _GREATER:
36
+ return "greater"
37
+ return None
38
+
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
+ )
52
+
53
+
54
+ @categorize(_CodeQuality)
55
+ class FindSuspiciousChainedComparison(Recipe):
56
+ """
57
+ Find chained comparisons whose links point in opposite directions.
58
+
59
+ A chain such as ``0 <= x >= 10`` reads as ``0 <= x and x >= 10``, which
60
+ is a needlessly convoluted way to say ``x >= 10`` and is almost always a
61
+ typo for ``0 <= x <= 10``. Mixing ``<``/``<=`` with ``>``/``>=`` in a
62
+ single chain is the tell-tale sign.
63
+
64
+ Example:
65
+ Flagged:
66
+ if 0 <= x >= 10:
67
+ pass
68
+
69
+ Not flagged (monotonic):
70
+ if 0 <= x <= 10:
71
+ pass
72
+ """
73
+
74
+ @property
75
+ def name(self) -> str:
76
+ return "org.openrewrite.python.codequality.FindSuspiciousChainedComparison"
77
+
78
+ @property
79
+ def display_name(self) -> str:
80
+ return "Find suspicious chained comparisons"
81
+
82
+ @property
83
+ def description(self) -> str:
84
+ return (
85
+ "Find chained comparisons that mix `<`/`<=` with `>`/`>=` (for "
86
+ "example `0 <= x >= 10`), where the links point in opposite "
87
+ "directions and the chain is almost always a mistake."
88
+ )
89
+
90
+ @property
91
+ def tags(self) -> List[str]:
92
+ return ["python", "code-quality"]
93
+
94
+ @property
95
+ def estimated_effort_per_occurrence(self) -> int:
96
+ return 5
97
+
98
+ def editor(self) -> TreeVisitor[Any, ExecutionContext]:
99
+ class Visitor(PythonVisitor[ExecutionContext]):
100
+ def visit_binary(
101
+ 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
107
+
108
+ outer = _direction(binary.operator)
109
+ if outer is None:
110
+ return binary
111
+
112
+ inner = binary.left
113
+ if not isinstance(inner, JBinary):
114
+ return binary
115
+
116
+ left = _direction(inner.operator)
117
+ if left is None or left == outer:
118
+ return binary
119
+
120
+ return _mark(binary)
121
+
122
+ return Visitor()
@@ -29,6 +29,7 @@ from rewrite.decorators import categorize
29
29
  from rewrite.marketplace import Python
30
30
  from rewrite.python.import_utils import get_alias_name, get_name_string, get_qualid_name
31
31
  from rewrite.python.remove_import import RemoveImportOptions, maybe_remove_import
32
+ from rewrite.python.scope_utils import LocalBindings
32
33
 
33
34
  from ._typing_imports import maybe_remove_typing_module_import
34
35
  from rewrite.python.tree import CompilationUnit, MultiImport, NamedArgument
@@ -39,8 +40,6 @@ from rewrite.java.tree import (
39
40
  Import,
40
41
  J,
41
42
  Literal,
42
- MethodDeclaration,
43
- VariableDeclarations,
44
43
  )
45
44
 
46
45
  # Define category paths
@@ -81,6 +80,7 @@ def _make_builtin_alias_editor(old_name: str, new_name: str) -> "TreeVisitor[Any
81
80
  self._module_refs: Set[str] = set()
82
81
  self._keep_from_import: bool = False
83
82
  self._rewrote_qualified: bool = False
83
+ self._local_bindings = LocalBindings()
84
84
 
85
85
  def visit_compilation_unit(
86
86
  self, cu: CompilationUnit, p: ExecutionContext
@@ -88,6 +88,7 @@ def _make_builtin_alias_editor(old_name: str, new_name: str) -> "TreeVisitor[Any
88
88
  self._bare_ref = None
89
89
  self._module_refs = set()
90
90
  self._rewrote_qualified = False
91
+ self._local_bindings = LocalBindings()
91
92
 
92
93
  for stmt in cu.statements:
93
94
  if isinstance(stmt, MultiImport):
@@ -172,19 +173,8 @@ def _make_builtin_alias_editor(old_name: str, new_name: str) -> "TreeVisitor[Any
172
173
  # A keyword-argument name (`f(List=...)`) names a parameter.
173
174
  if isinstance(parent, NamedArgument) and parent.name.id == ident.id:
174
175
  return ident
175
- # A declaration target (`List = ...`, `def f(List): ...`) binds a
176
- # new name rather than referencing the import.
177
- if (
178
- isinstance(parent, VariableDeclarations.NamedVariable)
179
- and parent.name.id == ident.id
180
- ):
181
- return ident
182
- # Inside function scopes, type attribution marks shadowed locals
183
- # with a field type; module-level references never carry one.
184
- if (
185
- self.cursor.first_enclosing(MethodDeclaration) is not None
186
- and ident.field_type is not None
187
- ):
176
+ # A name bound by an enclosing scope is that local, not the import.
177
+ if self._local_bindings.is_bound(self.cursor, self._bare_ref):
188
178
  return ident
189
179
 
190
180
  return ident.replace(_simple_name=new_name)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openrewrite-migrate-python
3
- Version: 0.12.0.dev20260811172040
3
+ Version: 0.13.0
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
@@ -21,7 +21,7 @@ Classifier: Typing :: Typed
21
21
  Requires-Python: >=3.10
22
22
  Description-Content-Type: text/markdown
23
23
  Provides-Extra: dev
24
- Requires-Dist: openrewrite>=8.84.3; extra == "dev"
24
+ Requires-Dist: openrewrite>=8.89.1; extra == "dev"
25
25
  Requires-Dist: pydantic>=2.11; extra == "dev"
26
26
  Requires-Dist: pytest>=8.0.0; extra == "dev"
27
27
  Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
@@ -5,6 +5,7 @@ src/openrewrite_code_quality_python/codequality/_semantically_equal.py
5
5
  src/openrewrite_code_quality_python/codequality/all_branches_identical.py
6
6
  src/openrewrite_code_quality_python/codequality/boolean_checks_not_inverted.py
7
7
  src/openrewrite_code_quality_python/codequality/collapsible_if_statements.py
8
+ src/openrewrite_code_quality_python/codequality/find_suspicious_chained_comparison.py
8
9
  src/openrewrite_code_quality_python/codequality/merge_identical_branches.py
9
10
  src/openrewrite_code_quality_python/codequality/remove_duplicate_conditions.py
10
11
  src/openrewrite_code_quality_python/codequality/remove_self_assignment.py
@@ -1,6 +1,6 @@
1
1
 
2
2
  [dev]
3
- openrewrite>=8.84.3
3
+ openrewrite>=8.89.1
4
4
  pydantic>=2.11
5
5
  pytest>=8.0.0
6
6
  pytest-cov>=4.0.0
@@ -120,6 +120,38 @@ class TestTypingAliasMoves:
120
120
  )
121
121
  )
122
122
 
123
+ @pytest.mark.parametrize("alias", sorted(a for a in EXPECTED_MOVES if EXPECTED_MOVES[a][1]))
124
+ def test_migrates_alias_referenced_inside_a_function(self, alias):
125
+ module, new_name = EXPECTED_MOVES[alias]
126
+ spec = RecipeSpec(
127
+ recipe=ChangeImport(
128
+ old_module="typing",
129
+ old_name=alias,
130
+ new_module=module,
131
+ new_name=new_name,
132
+ )
133
+ )
134
+ spec.rewrite_run(
135
+ python(
136
+ f"""
137
+ from typing import {alias}
138
+
139
+
140
+ def f(q: {alias}) -> {alias}:
141
+ local: {alias} = q
142
+ return local
143
+ """,
144
+ f"""
145
+ from {module} import {new_name}
146
+
147
+
148
+ def f(q: {new_name}) -> {new_name}:
149
+ local: {new_name} = q
150
+ return local
151
+ """,
152
+ )
153
+ )
154
+
123
155
  def test_migrating_all_names_of_an_import_leaves_no_blank_line(self):
124
156
  spec = RecipeSpec().with_recipes(
125
157
  ChangeImport(old_module="typing", old_name="Iterable", new_module="collections.abc"),
@@ -317,6 +317,99 @@ class TestPep585CornerCases:
317
317
  )
318
318
  )
319
319
 
320
+ def test_renames_usages_inside_functions(self):
321
+ spec = RecipeSpec(recipe=ReplaceTypingListWithList())
322
+ spec.rewrite_run(
323
+ python(
324
+ """
325
+ from typing import List
326
+
327
+
328
+ def collect(items: List[str]) -> List[int]:
329
+ order: List[int] = []
330
+ for item in items:
331
+ order.append(len(item))
332
+ return order
333
+ """,
334
+ """
335
+ def collect(items: list[str]) -> list[int]:
336
+ order: list[int] = []
337
+ for item in items:
338
+ order.append(len(item))
339
+ return order
340
+ """,
341
+ )
342
+ )
343
+
344
+ def test_narrows_import_to_names_without_builtin_equivalents(self):
345
+ spec = RecipeSpec(recipe=ReplaceTypingListWithList())
346
+ spec.rewrite_run(
347
+ python(
348
+ """
349
+ from typing import Dict, List, Optional
350
+
351
+
352
+ def resolve(names: List[str], mapping: Dict[str, str]) -> Optional[str]:
353
+ return mapping.get(names[0])
354
+ """,
355
+ """
356
+ from typing import Dict, Optional
357
+
358
+
359
+ def resolve(names: list[str], mapping: Dict[str, str]) -> Optional[str]:
360
+ return mapping.get(names[0])
361
+ """,
362
+ )
363
+ )
364
+
365
+ def test_leaves_a_local_that_shadows_the_import(self):
366
+ spec = RecipeSpec(recipe=ReplaceTypingListWithList())
367
+ spec.rewrite_run(
368
+ python(
369
+ """
370
+ from typing import List
371
+
372
+ x: List[int] = []
373
+
374
+
375
+ def render():
376
+ List = ", ".join(str(i) for i in x)
377
+ return List
378
+ """,
379
+ """
380
+ x: list[int] = []
381
+
382
+
383
+ def render():
384
+ List = ", ".join(str(i) for i in x)
385
+ return List
386
+ """,
387
+ )
388
+ )
389
+
390
+ def test_leaves_a_parameter_that_shadows_the_import(self):
391
+ spec = RecipeSpec(recipe=ReplaceTypingListWithList())
392
+ spec.rewrite_run(
393
+ python(
394
+ """
395
+ from typing import List
396
+
397
+ x: List[int] = []
398
+
399
+
400
+ def render(List):
401
+ return List
402
+ """,
403
+ """
404
+ x: list[int] = []
405
+
406
+
407
+ def render(List):
408
+ return List
409
+ """,
410
+ )
411
+ )
412
+
320
413
  def test_keeps_import_used_by_string_annotation(self):
321
414
  """The import stays while a string annotation still references it."""
322
415
  spec = RecipeSpec(recipe=ReplaceTypingListWithList())
@@ -9,7 +9,9 @@ from openrewrite_migrate_python.migrate import (
9
9
  UpgradeToPython313,
10
10
  UpgradeToPython314,
11
11
  )
12
+ from rewrite import Recipe
12
13
  from rewrite.rpc import RpcRecipe
14
+ from rewrite.test import RecipeSpec, python
13
15
 
14
16
  class TestUpgradeRecipeChaining:
15
17
  """Tests for verifying upgrade recipe chaining."""
@@ -203,3 +205,105 @@ class TestPydanticUpgradeChaining:
203
205
  recipe = UpgradeToPydantic211()
204
206
  assert recipe.name == "org.openrewrite.python.migrate.pydantic.UpgradeToPydantic211"
205
207
  assert "pydantic" in recipe.tags
208
+
209
+
210
+ class _NativeUpgradeToPython313(Recipe):
211
+ """`UpgradeToPython313` without its `RpcRecipe` steps, which need a Java host."""
212
+
213
+ @property
214
+ def name(self) -> str:
215
+ return "test.NativeUpgradeToPython313"
216
+
217
+ @property
218
+ def display_name(self) -> str:
219
+ return "Upgrade to Python 3.13 (native steps only)"
220
+
221
+ @property
222
+ def description(self) -> str:
223
+ return "Runs the in-process steps of `UpgradeToPython313` in composite order."
224
+
225
+ def recipe_list(self):
226
+ def leaves(recipe):
227
+ for sub in recipe.recipe_list():
228
+ if isinstance(sub, RpcRecipe):
229
+ continue
230
+ nested = sub.recipe_list()
231
+ if nested:
232
+ yield from leaves(sub)
233
+ else:
234
+ yield sub
235
+
236
+ return list(leaves(UpgradeToPython313()))
237
+
238
+
239
+ class TestUpgradeToPython313TypingConsistency:
240
+ """The typing imports a file keeps must match the names it still uses."""
241
+
242
+ def test_migrates_imports_and_usages_together(self):
243
+ spec = RecipeSpec(recipe=_NativeUpgradeToPython313())
244
+ spec.rewrite_run(
245
+ python(
246
+ """
247
+ from typing import List, Dict, Set, Tuple, Optional, Callable, Iterable
248
+
249
+
250
+ def collect(items: List[str], index: Dict[str, int]) -> Tuple[Set[str], List[int]]:
251
+ seen: Set[str] = set()
252
+ order: List[int] = []
253
+ for item in items:
254
+ if item not in seen:
255
+ seen.add(item)
256
+ order.append(index.get(item, -1))
257
+ return seen, order
258
+
259
+
260
+ def apply_all(fns: Iterable[Callable[[int], int]], value: int) -> Optional[int]:
261
+ for fn in fns:
262
+ value = fn(value)
263
+ return value
264
+ """,
265
+ """
266
+ from collections.abc import Callable, Iterable
267
+
268
+
269
+ def collect(items: list[str], index: dict[str, int]) -> tuple[set[str], list[int]]:
270
+ seen: set[str] = set()
271
+ order: list[int] = []
272
+ for item in items:
273
+ if item not in seen:
274
+ seen.add(item)
275
+ order.append(index.get(item, -1))
276
+ return seen, order
277
+
278
+
279
+ def apply_all(fns: Iterable[Callable[[int], int]], value: int) -> int | None:
280
+ for fn in fns:
281
+ value = fn(value)
282
+ return value
283
+ """,
284
+ )
285
+ )
286
+
287
+ def test_migrates_imports_and_usages_together_in_a_smaller_file(self):
288
+ spec = RecipeSpec(recipe=_NativeUpgradeToPython313())
289
+ spec.rewrite_run(
290
+ python(
291
+ """
292
+ from typing import List, Dict, Optional
293
+
294
+
295
+ def resolve(names: List[str], mapping: Dict[str, str]) -> Optional[str]:
296
+ for name in names:
297
+ if name in mapping:
298
+ return mapping[name]
299
+ return None
300
+ """,
301
+ """
302
+ def resolve(names: list[str], mapping: dict[str, str]) -> str | None:
303
+ for name in names:
304
+ if name in mapping:
305
+ return mapping[name]
306
+ return None
307
+ """,
308
+ )
309
+ )