openrewrite-migrate-python 0.6.0.dev20260418171218__tar.gz → 0.6.0.dev20260420171522__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 (134) hide show
  1. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/PKG-INFO +1 -1
  2. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/pyproject.toml +1 -1
  3. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/__init__.py +12 -0
  4. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/pkgutil_deprecations.py +34 -46
  5. openrewrite_migrate_python-0.6.0.dev20260420171522/src/openrewrite_migrate_python/migrate/typing_callable.py +62 -0
  6. openrewrite_migrate_python-0.6.0.dev20260420171522/src/openrewrite_migrate_python/migrate/typing_deprecations.py +406 -0
  7. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python.egg-info/PKG-INFO +1 -1
  8. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_pkgutil_deprecations.py +8 -10
  9. openrewrite_migrate_python-0.6.0.dev20260420171522/tests/test_typing_callable.py +34 -0
  10. openrewrite_migrate_python-0.6.0.dev20260420171522/tests/test_typing_deprecations.py +236 -0
  11. openrewrite_migrate_python-0.6.0.dev20260418171218/src/openrewrite_migrate_python/migrate/typing_callable.py +0 -142
  12. openrewrite_migrate_python-0.6.0.dev20260418171218/src/openrewrite_migrate_python/migrate/typing_deprecations.py +0 -326
  13. openrewrite_migrate_python-0.6.0.dev20260418171218/tests/test_typing_callable.py +0 -57
  14. openrewrite_migrate_python-0.6.0.dev20260418171218/tests/test_typing_deprecations.py +0 -36
  15. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/setup.cfg +0 -0
  16. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_code_quality_python/__init__.py +0 -0
  17. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_code_quality_python/codequality/__init__.py +0 -0
  18. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_code_quality_python/codequality/_semantically_equal.py +0 -0
  19. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_code_quality_python/codequality/all_branches_identical.py +0 -0
  20. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_code_quality_python/codequality/boolean_checks_not_inverted.py +0 -0
  21. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_code_quality_python/codequality/collapsible_if_statements.py +0 -0
  22. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_code_quality_python/codequality/merge_identical_branches.py +0 -0
  23. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_code_quality_python/codequality/remove_duplicate_conditions.py +0 -0
  24. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_code_quality_python/codequality/remove_self_assignment.py +0 -0
  25. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_code_quality_python/codequality/remove_unconditional_value_overwrite.py +0 -0
  26. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_code_quality_python/codequality/simplify_boolean_literal.py +0 -0
  27. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_code_quality_python/codequality/simplify_redundant_logical_expression.py +0 -0
  28. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/__init__.py +0 -0
  29. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/_markers.py +0 -0
  30. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/aifc_migrations.py +0 -0
  31. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/array_deprecations.py +0 -0
  32. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/ast_deprecations.py +0 -0
  33. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/asyncio_coroutine_to_async.py +0 -0
  34. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/asyncio_deprecations.py +0 -0
  35. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/calendar_deprecations.py +0 -0
  36. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/cgi_migrations.py +0 -0
  37. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/cgi_parse_deprecations.py +0 -0
  38. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/collections_abc_migrations.py +0 -0
  39. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/configparser_deprecations.py +0 -0
  40. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/datetime_utc.py +0 -0
  41. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/distutils_deprecations.py +0 -0
  42. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/distutils_migrations.py +0 -0
  43. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/functools_deprecations.py +0 -0
  44. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/future_imports.py +0 -0
  45. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/gettext_deprecations.py +0 -0
  46. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/html_parser_deprecations.py +0 -0
  47. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/imp_migrations.py +0 -0
  48. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/langchain_classic_imports.py +0 -0
  49. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/langchain_community_imports.py +0 -0
  50. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/langchain_provider_imports.py +0 -0
  51. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/locale_deprecations.py +0 -0
  52. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/locale_getdefaultlocale_deprecation.py +0 -0
  53. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/macpath_deprecations.py +0 -0
  54. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/mailcap_migrations.py +0 -0
  55. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/nntplib_migrations.py +0 -0
  56. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/os_deprecations.py +0 -0
  57. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/pathlib_deprecations.py +0 -0
  58. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/pep594_system_migrations.py +0 -0
  59. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/pipes_migrations.py +0 -0
  60. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/platform_deprecations.py +0 -0
  61. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/re_deprecations.py +0 -0
  62. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/removed_modules_312.py +0 -0
  63. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/shutil_deprecations.py +0 -0
  64. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/socket_deprecations.py +0 -0
  65. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/ssl_deprecations.py +0 -0
  66. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/string_formatting.py +0 -0
  67. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/sys_deprecations.py +0 -0
  68. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/sys_last_deprecations.py +0 -0
  69. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/tarfile_deprecations.py +0 -0
  70. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/telnetlib_migrations.py +0 -0
  71. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/tempfile_deprecations.py +0 -0
  72. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/threading_deprecations.py +0 -0
  73. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/threading_is_alive_deprecation.py +0 -0
  74. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/typing_union_to_pipe.py +0 -0
  75. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/unittest_deprecations.py +0 -0
  76. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/upgrade_to_langchain02.py +0 -0
  77. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/upgrade_to_langchain1.py +0 -0
  78. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/upgrade_to_python310.py +0 -0
  79. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/upgrade_to_python311.py +0 -0
  80. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/upgrade_to_python312.py +0 -0
  81. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/upgrade_to_python313.py +0 -0
  82. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/upgrade_to_python314.py +0 -0
  83. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/upgrade_to_python38.py +0 -0
  84. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/upgrade_to_python39.py +0 -0
  85. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/urllib_deprecations.py +0 -0
  86. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/uu_migrations.py +0 -0
  87. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/xdrlib_migrations.py +0 -0
  88. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python/migrate/xml_deprecations.py +0 -0
  89. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python.egg-info/SOURCES.txt +0 -0
  90. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python.egg-info/dependency_links.txt +0 -0
  91. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python.egg-info/entry_points.txt +0 -0
  92. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python.egg-info/requires.txt +0 -0
  93. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/src/openrewrite_migrate_python.egg-info/top_level.txt +0 -0
  94. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_aifc_migrations.py +0 -0
  95. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_array_deprecations.py +0 -0
  96. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_ast_deprecations.py +0 -0
  97. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_asyncio_coroutine_to_async.py +0 -0
  98. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_asyncio_deprecations.py +0 -0
  99. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_calendar_deprecations.py +0 -0
  100. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_cgi_parse_deprecations.py +0 -0
  101. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_change_import_recipes.py +0 -0
  102. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_collections_abc_migrations.py +0 -0
  103. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_configparser_deprecations.py +0 -0
  104. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_datetime_utc.py +0 -0
  105. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_distutils_deprecations.py +0 -0
  106. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_future_imports.py +0 -0
  107. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_gettext_deprecations.py +0 -0
  108. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_html_parser_deprecations.py +0 -0
  109. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_imp_migrations.py +0 -0
  110. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_langchain_classic_imports.py +0 -0
  111. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_langchain_community_imports.py +0 -0
  112. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_langchain_provider_imports.py +0 -0
  113. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_locale_deprecations.py +0 -0
  114. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_locale_getdefaultlocale_deprecation.py +0 -0
  115. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_macpath_deprecations.py +0 -0
  116. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_os_deprecations.py +0 -0
  117. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_pep594_migrations.py +0 -0
  118. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_pep594_system_migrations.py +0 -0
  119. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_platform_deprecations.py +0 -0
  120. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_re_deprecations.py +0 -0
  121. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_removed_modules_312.py +0 -0
  122. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_shutil_deprecations.py +0 -0
  123. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_ssl_deprecations.py +0 -0
  124. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_string_formatting.py +0 -0
  125. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_sys_deprecations.py +0 -0
  126. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_sys_last_deprecations.py +0 -0
  127. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_tarfile_deprecations.py +0 -0
  128. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_threading_deprecations.py +0 -0
  129. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_threading_extended.py +0 -0
  130. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_threading_is_alive_deprecation.py +0 -0
  131. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_typing_union_to_pipe.py +0 -0
  132. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_unittest_deprecations.py +0 -0
  133. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/tests/test_upgrade_recipes.py +0 -0
  134. {openrewrite_migrate_python-0.6.0.dev20260418171218 → openrewrite_migrate_python-0.6.0.dev20260420171522}/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.6.0.dev20260418171218
3
+ Version: 0.6.0.dev20260420171522
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.6.0.dev20260418171218" # Updated dynamically during release
8
+ version = "0.6.0.dev20260420171522" # 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"
@@ -86,6 +86,13 @@ from .threading_deprecations import (
86
86
  ReplaceThreadingCurrentThread,
87
87
  )
88
88
  from .typing_callable import ReplaceTypingCallableWithCollectionsAbcCallable
89
+ from .typing_deprecations import (
90
+ ReplaceTypingDictWithDict,
91
+ ReplaceTypingListWithList,
92
+ ReplaceTypingSetWithSet,
93
+ ReplaceTypingText,
94
+ ReplaceTypingTupleWithTuple,
95
+ )
89
96
  from .typing_union_to_pipe import (
90
97
  ReplaceTypingOptionalWithUnion,
91
98
  ReplaceTypingUnionWithPipe,
@@ -194,7 +201,12 @@ __all__ = [
194
201
  "ReplaceThreadingCurrentThread",
195
202
  # Auto-fix: Typing
196
203
  "ReplaceTypingCallableWithCollectionsAbcCallable",
204
+ "ReplaceTypingDictWithDict",
205
+ "ReplaceTypingListWithList",
197
206
  "ReplaceTypingOptionalWithUnion",
207
+ "ReplaceTypingSetWithSet",
208
+ "ReplaceTypingText",
209
+ "ReplaceTypingTupleWithTuple",
198
210
  "ReplaceTypingUnionWithPipe",
199
211
  # Auto-fix: Unittest
200
212
  "ReplaceUnittestDeprecatedAliases",
@@ -9,15 +9,17 @@ Several pkgutil functions were deprecated in Python 3.12:
9
9
  See: https://docs.python.org/3/library/pkgutil.html
10
10
  """
11
11
 
12
- from typing import Any, Optional
12
+ from typing import Any, Optional, cast
13
13
 
14
14
  from rewrite import ExecutionContext, Recipe, TreeVisitor
15
15
  from rewrite.category import CategoryDescriptor
16
16
  from rewrite.decorators import categorize
17
17
  from rewrite.marketplace import Python
18
18
  from rewrite.python.visitor import PythonVisitor
19
- from rewrite.java.tree import Identifier, MethodInvocation
20
- from ._markers import mark_deprecated
19
+ from rewrite.python.template import pattern, template, capture
20
+ from rewrite.python.add_import import AddImportOptions, maybe_add_import
21
+ from rewrite.python.remove_import import RemoveImportOptions, maybe_remove_import
22
+ from rewrite.java.tree import J, MethodInvocation
21
23
 
22
24
  # Define category path: Python > Migrate > Python 3.12
23
25
  _Python312 = [
@@ -26,29 +28,17 @@ _Python312 = [
26
28
  CategoryDescriptor(display_name="Python 3.12"),
27
29
  ]
28
30
 
29
-
30
- def _is_pkgutil_method(method: MethodInvocation, method_name: str) -> bool:
31
- """
32
- Check if this is a pkgutil.method_name() call using type attribution.
33
- """
34
- if not isinstance(method.name, Identifier):
35
- return False
36
- if method.name.simple_name != method_name:
37
- return False
38
-
39
- if not method.method_type or not method.method_type.declaring_type:
40
- return False
41
- dt = method.method_type.declaring_type
42
- if not hasattr(dt, '_fully_qualified_name'):
43
- return False
44
- fqn = str(dt._fully_qualified_name)
45
- return 'pkgutil' in fqn
31
+ # Pattern/template pairs
32
+ _mod = capture('mod')
33
+ _find_loader_pattern = pattern("pkgutil.find_loader({mod})", mod=_mod)
34
+ _get_loader_pattern = pattern("pkgutil.get_loader({mod})", mod=_mod)
35
+ _find_spec_template = template("importlib.util.find_spec({mod})", mod=_mod)
46
36
 
47
37
 
48
38
  @categorize(_Python312)
49
39
  class ReplacePkgutilFindLoader(Recipe):
50
40
  """
51
- Find and migrate `pkgutil.find_loader()` calls to `importlib.util.find_spec()`.
41
+ Replace `pkgutil.find_loader()` with `importlib.util.find_spec()`.
52
42
 
53
43
  The `pkgutil.find_loader()` function was deprecated in Python 3.12.
54
44
  The recommended replacement is `importlib.util.find_spec()`.
@@ -64,7 +54,6 @@ class ReplacePkgutilFindLoader(Recipe):
64
54
  After:
65
55
  import importlib.util
66
56
  spec = importlib.util.find_spec('mymodule')
67
- loader = spec.loader if spec else None
68
57
  """
69
58
 
70
59
  @property
@@ -84,19 +73,19 @@ class ReplacePkgutilFindLoader(Recipe):
84
73
 
85
74
  def editor(self) -> TreeVisitor[Any, ExecutionContext]:
86
75
  class Visitor(PythonVisitor[ExecutionContext]):
87
- def visit_method_invocation(
76
+ def visit_method_invocation( # type: ignore[override]
88
77
  self, method: MethodInvocation, p: ExecutionContext
89
- ) -> Optional[MethodInvocation]:
90
- method = super().visit_method_invocation(method, p)
91
-
92
- if _is_pkgutil_method(method, "find_loader"):
93
- return mark_deprecated(
94
- method,
95
- "pkgutil.find_loader() is deprecated",
96
- "Replace with importlib.util.find_spec() (Python 3.12+)"
78
+ ) -> Optional[J]:
79
+ m = cast(MethodInvocation, super().visit_method_invocation(method, p))
80
+ match = _find_loader_pattern.match(m, self.cursor)
81
+ if match:
82
+ maybe_add_import(
83
+ self,
84
+ AddImportOptions(module="importlib.util", only_if_referenced=False),
97
85
  )
98
-
99
- return method
86
+ maybe_remove_import(self, RemoveImportOptions(module="pkgutil"))
87
+ return _find_spec_template.apply(self.cursor, values=match)
88
+ return m
100
89
 
101
90
  return Visitor()
102
91
 
@@ -104,7 +93,7 @@ class ReplacePkgutilFindLoader(Recipe):
104
93
  @categorize(_Python312)
105
94
  class ReplacePkgutilGetLoader(Recipe):
106
95
  """
107
- Find and migrate `pkgutil.get_loader()` calls to `importlib.util.find_spec()`.
96
+ Replace `pkgutil.get_loader()` with `importlib.util.find_spec()`.
108
97
 
109
98
  The `pkgutil.get_loader()` function was deprecated in Python 3.12.
110
99
  The recommended replacement is `importlib.util.find_spec()`.
@@ -117,7 +106,6 @@ class ReplacePkgutilGetLoader(Recipe):
117
106
  After:
118
107
  import importlib.util
119
108
  spec = importlib.util.find_spec('mymodule')
120
- loader = spec.loader if spec else None
121
109
  """
122
110
 
123
111
  @property
@@ -137,18 +125,18 @@ class ReplacePkgutilGetLoader(Recipe):
137
125
 
138
126
  def editor(self) -> TreeVisitor[Any, ExecutionContext]:
139
127
  class Visitor(PythonVisitor[ExecutionContext]):
140
- def visit_method_invocation(
128
+ def visit_method_invocation( # type: ignore[override]
141
129
  self, method: MethodInvocation, p: ExecutionContext
142
- ) -> Optional[MethodInvocation]:
143
- method = super().visit_method_invocation(method, p)
144
-
145
- if _is_pkgutil_method(method, "get_loader"):
146
- return mark_deprecated(
147
- method,
148
- "pkgutil.get_loader() is deprecated",
149
- "Replace with importlib.util.find_spec() (Python 3.12+)"
130
+ ) -> Optional[J]:
131
+ m = cast(MethodInvocation, super().visit_method_invocation(method, p))
132
+ match = _get_loader_pattern.match(m, self.cursor)
133
+ if match:
134
+ maybe_add_import(
135
+ self,
136
+ AddImportOptions(module="importlib.util", only_if_referenced=False),
150
137
  )
151
-
152
- return method
138
+ maybe_remove_import(self, RemoveImportOptions(module="pkgutil"))
139
+ return _find_spec_template.apply(self.cursor, values=match)
140
+ return m
153
141
 
154
142
  return Visitor()
@@ -0,0 +1,62 @@
1
+ """
2
+ Recipe for migrating typing.Callable to collections.abc.Callable.
3
+
4
+ PEP 585 (Python 3.9+) deprecated typing.Callable in favor of
5
+ collections.abc.Callable:
6
+
7
+ - typing.Callable[[int], str] -> collections.abc.Callable[[int], str]
8
+
9
+ See: https://peps.python.org/pep-0585/
10
+ """
11
+
12
+ from typing import List
13
+
14
+ from rewrite import Recipe
15
+ from rewrite.category import CategoryDescriptor
16
+ from rewrite.decorators import categorize
17
+ from rewrite.marketplace import Python
18
+ from rewrite.python.recipes import ChangeImport
19
+
20
+ # Define category path
21
+ _Python39 = [
22
+ *Python,
23
+ CategoryDescriptor(display_name="Migrate"),
24
+ CategoryDescriptor(display_name="Python 3.9"),
25
+ ]
26
+
27
+
28
+ @categorize(_Python39)
29
+ class ReplaceTypingCallableWithCollectionsAbcCallable(Recipe):
30
+ """
31
+ Replace `typing.Callable` with `collections.abc.Callable`.
32
+
33
+ PEP 585 deprecated `typing.Callable` in Python 3.9. Use
34
+ `collections.abc.Callable` instead for type annotations.
35
+
36
+ Example:
37
+ Before:
38
+ from typing import Callable
39
+ handler: Callable[[int], str] = lambda x: str(x)
40
+
41
+ After:
42
+ from collections.abc import Callable
43
+ handler: Callable[[int], str] = lambda x: str(x)
44
+ """
45
+
46
+ @property
47
+ def name(self) -> str:
48
+ return "org.openrewrite.python.migrate.ReplaceTypingCallableWithCollectionsAbcCallable"
49
+
50
+ @property
51
+ def display_name(self) -> str:
52
+ return "Replace `typing.Callable` with `collections.abc.Callable`"
53
+
54
+ @property
55
+ def description(self) -> str:
56
+ return (
57
+ "PEP 585 deprecated `typing.Callable` in Python 3.9. "
58
+ "Replace with `collections.abc.Callable` for type annotations."
59
+ )
60
+
61
+ def recipe_list(self) -> List[Recipe]:
62
+ return [ChangeImport(old_module="typing", old_name="Callable", new_module="collections.abc")]
@@ -0,0 +1,406 @@
1
+ """
2
+ Recipes for migrating deprecated typing module aliases to built-in generics.
3
+
4
+ PEP 585 (Python 3.9+) deprecated many typing module aliases in favor of
5
+ using built-in types directly as generics:
6
+
7
+ - typing.List[X] -> list[X]
8
+ - typing.Dict[K, V] -> dict[K, V]
9
+ - typing.Set[X] -> set[X]
10
+ - typing.FrozenSet[X] -> frozenset[X]
11
+ - typing.Tuple[X, ...] -> tuple[X, ...]
12
+ - typing.Type[X] -> type[X]
13
+
14
+ Additionally, typing.Text is deprecated (alias for str since Python 3.11).
15
+
16
+ See: https://peps.python.org/pep-0585/
17
+ """
18
+
19
+ from typing import Any, Dict, List, Optional, cast
20
+
21
+ from rewrite import ExecutionContext, Recipe, TreeVisitor
22
+ from rewrite.category import CategoryDescriptor
23
+ from rewrite.decorators import categorize
24
+ from rewrite.marketplace import Python
25
+ from rewrite.python.remove_import import RemoveImportOptions, maybe_remove_import
26
+ from rewrite.python.visitor import PythonVisitor
27
+ from rewrite.java.tree import Identifier, J
28
+
29
+ # Define category paths
30
+ _Python39 = [
31
+ *Python,
32
+ CategoryDescriptor(display_name="Migrate"),
33
+ CategoryDescriptor(display_name="Python 3.9"),
34
+ ]
35
+
36
+ _Python311 = [
37
+ *Python,
38
+ CategoryDescriptor(display_name="Migrate"),
39
+ CategoryDescriptor(display_name="Python 3.11"),
40
+ ]
41
+
42
+
43
+ # PEP 585 deprecated typing aliases -> built-in replacements
44
+ PEP585_DEPRECATIONS: Dict[str, str] = {
45
+ "List": "list",
46
+ "Dict": "dict",
47
+ "Set": "set",
48
+ "FrozenSet": "frozenset",
49
+ "Tuple": "tuple",
50
+ "Type": "type",
51
+ }
52
+
53
+
54
+ def _make_pep585_editor(old_name: str, new_name: str) -> "TreeVisitor[Any, ExecutionContext]":
55
+ """Create a visitor that renames a typing alias to its built-in equivalent.
56
+
57
+ The visitor:
58
+ 1. Checks whether ``from typing import <old_name>`` is present. If not,
59
+ returns the compilation unit unchanged (fast-path).
60
+ 2. Renames every occurrence of the identifier outside of import statements.
61
+ 3. Removes the ``<old_name>`` entry from the ``from typing import …``
62
+ statement (deleting the whole statement when it becomes empty).
63
+ """
64
+ from rewrite.python.tree import CompilationUnit, MultiImport
65
+ from rewrite.java.support_types import JContainer
66
+ from rewrite.java.tree import FieldAccess, Space
67
+
68
+ class Pep585Visitor(PythonVisitor[ExecutionContext]):
69
+ def __init__(self) -> None:
70
+ super().__init__()
71
+ self._has_import: bool = False
72
+
73
+ # ------------------------------------------------------------------
74
+ # Helpers
75
+ # ------------------------------------------------------------------
76
+
77
+ @staticmethod
78
+ def _get_qualid_name(node: Any) -> str:
79
+ """Get string representation of a qualified name (FieldAccess or Identifier)."""
80
+ if isinstance(node, Identifier):
81
+ return node.simple_name
82
+ if isinstance(node, FieldAccess):
83
+ target = Pep585Visitor._get_qualid_name(node.target)
84
+ name = node.name.simple_name
85
+ return f"{target}.{name}" if target else name
86
+ # Empty or unknown
87
+ return ""
88
+
89
+ @staticmethod
90
+ def _import_names(multi: MultiImport) -> list:
91
+ """Return the list of name strings imported by a MultiImport."""
92
+ return [
93
+ Pep585Visitor._get_qualid_name(imp.qualid)
94
+ for imp in multi.names
95
+ ]
96
+
97
+ @staticmethod
98
+ def _is_typing_import(multi: MultiImport) -> bool:
99
+ return (
100
+ multi.from_ is not None
101
+ and Pep585Visitor._get_qualid_name(multi.from_) == "typing"
102
+ )
103
+
104
+ # ------------------------------------------------------------------
105
+ # Pre-scan: detect whether the import is present
106
+ # ------------------------------------------------------------------
107
+
108
+ def visit_compilation_unit(
109
+ self, cu: CompilationUnit, p: ExecutionContext
110
+ ) -> CompilationUnit:
111
+ self._has_import = any(
112
+ self._is_typing_import(stmt) and old_name in self._import_names(stmt)
113
+ for stmt in cu.statements
114
+ if isinstance(stmt, MultiImport)
115
+ )
116
+ if not self._has_import:
117
+ return cu
118
+
119
+ result = cast(CompilationUnit, super().visit_compilation_unit(cu, p))
120
+
121
+ # After import removal, the first remaining statement may have an
122
+ # unwanted leading newline in its prefix (the newline that
123
+ # previously separated it from the removed import). Strip it.
124
+ from rewrite.java.support_types import JRightPadded
125
+
126
+ padded_stmts = list(result.padding.statements)
127
+ if padded_stmts:
128
+ first_padded = padded_stmts[0]
129
+ first_stmt = first_padded.element
130
+ prefix = first_stmt.prefix
131
+ if prefix.whitespace and prefix.whitespace.startswith('\n'):
132
+ new_ws = prefix.whitespace[1:]
133
+ new_prefix = prefix.replace(_whitespace=new_ws)
134
+ padded_stmts[0] = JRightPadded(
135
+ first_stmt.replace(prefix=new_prefix),
136
+ first_padded.after,
137
+ first_padded.markers,
138
+ )
139
+ result = result.padding.replace(_statements=padded_stmts)
140
+
141
+ return result
142
+
143
+ # ------------------------------------------------------------------
144
+ # Import removal
145
+ # ------------------------------------------------------------------
146
+
147
+ def visit_multi_import( # type: ignore[override]
148
+ self, multi: MultiImport, p: ExecutionContext
149
+ ) -> Optional[J]:
150
+ if not self._has_import:
151
+ return multi
152
+ if not self._is_typing_import(multi):
153
+ return multi
154
+ if old_name not in self._import_names(multi):
155
+ return multi
156
+
157
+ # Remove old_name from the import list
158
+ existing_padded = multi.padding.names.padding.elements
159
+ new_padded = [
160
+ ep for ep in existing_padded
161
+ if self._get_qualid_name(ep.element.qualid) != old_name
162
+ ]
163
+
164
+ if len(new_padded) == 0:
165
+ # All names removed — delete the statement
166
+ return None
167
+
168
+ # Fix prefix on the first remaining element
169
+ if new_padded:
170
+ first = new_padded[0]
171
+ if first.element.prefix != Space.EMPTY:
172
+ new_padded[0] = first.replace(
173
+ _element=first.element.replace(prefix=Space.EMPTY)
174
+ )
175
+
176
+ return multi.padding.replace(
177
+ _names=JContainer(
178
+ multi.padding.names.before,
179
+ new_padded,
180
+ multi.padding.names.markers,
181
+ )
182
+ )
183
+
184
+ # ------------------------------------------------------------------
185
+ # Identifier renaming (outside imports)
186
+ # ------------------------------------------------------------------
187
+
188
+ def visit_identifier(
189
+ self, ident: Identifier, p: ExecutionContext
190
+ ) -> Identifier:
191
+ ident = cast(Identifier, super().visit_identifier(ident, p))
192
+
193
+ if ident.simple_name != old_name:
194
+ return ident
195
+
196
+ # Skip identifiers that are part of import statements
197
+ if self.cursor.first_enclosing(MultiImport) is not None:
198
+ return ident
199
+
200
+ return ident.replace(_simple_name=new_name)
201
+
202
+ return Pep585Visitor()
203
+
204
+
205
+ @categorize(_Python39)
206
+ class ReplaceTypingListWithList(Recipe):
207
+ """
208
+ Find and migrate `typing.List` to built-in `list`.
209
+
210
+ PEP 585 deprecated `typing.List` in Python 3.9. The built-in `list` type
211
+ can now be used directly as a generic type.
212
+
213
+ Example:
214
+ Before:
215
+ from typing import List
216
+ items: List[str] = []
217
+
218
+ After:
219
+ items: list[str] = []
220
+ """
221
+
222
+ @property
223
+ def name(self) -> str:
224
+ return "org.openrewrite.python.migrate.ReplaceTypingListWithList"
225
+
226
+ @property
227
+ def display_name(self) -> str:
228
+ return "Replace `typing.List` with `list`"
229
+
230
+ @property
231
+ def description(self) -> str:
232
+ return (
233
+ "PEP 585 deprecated `typing.List` in Python 3.9. "
234
+ "Replace with the built-in `list` type for generic annotations."
235
+ )
236
+
237
+ def editor(self) -> TreeVisitor[Any, ExecutionContext]:
238
+ return _make_pep585_editor("List", "list")
239
+
240
+
241
+ @categorize(_Python39)
242
+ class ReplaceTypingDictWithDict(Recipe):
243
+ """
244
+ Find and migrate `typing.Dict` to built-in `dict`.
245
+
246
+ PEP 585 deprecated `typing.Dict` in Python 3.9. The built-in `dict` type
247
+ can now be used directly as a generic type.
248
+
249
+ Example:
250
+ Before:
251
+ from typing import Dict
252
+ mapping: Dict[str, int] = {}
253
+
254
+ After:
255
+ mapping: dict[str, int] = {}
256
+ """
257
+
258
+ @property
259
+ def name(self) -> str:
260
+ return "org.openrewrite.python.migrate.ReplaceTypingDictWithDict"
261
+
262
+ @property
263
+ def display_name(self) -> str:
264
+ return "Replace `typing.Dict` with `dict`"
265
+
266
+ @property
267
+ def description(self) -> str:
268
+ return (
269
+ "PEP 585 deprecated `typing.Dict` in Python 3.9. "
270
+ "Replace with the built-in `dict` type for generic annotations."
271
+ )
272
+
273
+ def editor(self) -> TreeVisitor[Any, ExecutionContext]:
274
+ return _make_pep585_editor("Dict", "dict")
275
+
276
+
277
+ @categorize(_Python39)
278
+ class ReplaceTypingSetWithSet(Recipe):
279
+ """
280
+ Find and migrate `typing.Set` to built-in `set`.
281
+
282
+ PEP 585 deprecated `typing.Set` in Python 3.9. The built-in `set` type
283
+ can now be used directly as a generic type.
284
+
285
+ Example:
286
+ Before:
287
+ from typing import Set
288
+ items: Set[int] = set()
289
+
290
+ After:
291
+ items: set[int] = set()
292
+ """
293
+
294
+ @property
295
+ def name(self) -> str:
296
+ return "org.openrewrite.python.migrate.ReplaceTypingSetWithSet"
297
+
298
+ @property
299
+ def display_name(self) -> str:
300
+ return "Replace `typing.Set` with `set`"
301
+
302
+ @property
303
+ def description(self) -> str:
304
+ return (
305
+ "PEP 585 deprecated `typing.Set` in Python 3.9. "
306
+ "Replace with the built-in `set` type for generic annotations."
307
+ )
308
+
309
+ def editor(self) -> TreeVisitor[Any, ExecutionContext]:
310
+ return _make_pep585_editor("Set", "set")
311
+
312
+
313
+ @categorize(_Python39)
314
+ class ReplaceTypingTupleWithTuple(Recipe):
315
+ """
316
+ Find and migrate `typing.Tuple` to built-in `tuple`.
317
+
318
+ PEP 585 deprecated `typing.Tuple` in Python 3.9. The built-in `tuple` type
319
+ can now be used directly as a generic type.
320
+
321
+ Example:
322
+ Before:
323
+ from typing import Tuple
324
+ point: Tuple[int, int] = (0, 0)
325
+
326
+ After:
327
+ point: tuple[int, int] = (0, 0)
328
+ """
329
+
330
+ @property
331
+ def name(self) -> str:
332
+ return "org.openrewrite.python.migrate.ReplaceTypingTupleWithTuple"
333
+
334
+ @property
335
+ def display_name(self) -> str:
336
+ return "Replace `typing.Tuple` with `tuple`"
337
+
338
+ @property
339
+ def description(self) -> str:
340
+ return (
341
+ "PEP 585 deprecated `typing.Tuple` in Python 3.9. "
342
+ "Replace with the built-in `tuple` type for generic annotations."
343
+ )
344
+
345
+ def editor(self) -> TreeVisitor[Any, ExecutionContext]:
346
+ return _make_pep585_editor("Tuple", "tuple")
347
+
348
+
349
+ @categorize(_Python311)
350
+ class ReplaceTypingText(Recipe):
351
+ """
352
+ Find and migrate `typing.Text` to `str`.
353
+
354
+ `typing.Text` was an alias for `str` provided for Python 2/3 compatibility.
355
+ It is deprecated as of Python 3.11 since Python 2 is no longer supported.
356
+
357
+ Example:
358
+ Before:
359
+ from typing import Text
360
+ name: Text = "hello"
361
+
362
+ After:
363
+ name: str = "hello"
364
+ """
365
+
366
+ @property
367
+ def name(self) -> str:
368
+ return "org.openrewrite.python.migrate.ReplaceTypingText"
369
+
370
+ @property
371
+ def display_name(self) -> str:
372
+ return "Replace `typing.Text` with `str`"
373
+
374
+ @property
375
+ def description(self) -> str:
376
+ return (
377
+ "`typing.Text` is deprecated as of Python 3.11. "
378
+ "It was an alias for `str` for Python 2/3 compatibility. Replace with `str`."
379
+ )
380
+
381
+ def editor(self) -> TreeVisitor[Any, ExecutionContext]:
382
+ from rewrite.python.tree import MultiImport
383
+
384
+ class Visitor(PythonVisitor[ExecutionContext]):
385
+ def visit_identifier(
386
+ self, ident: Identifier, p: ExecutionContext
387
+ ) -> Identifier:
388
+ ident = cast(Identifier, super().visit_identifier(ident, p))
389
+
390
+ if ident.simple_name != "Text":
391
+ return ident
392
+
393
+ # Skip identifiers inside import statements
394
+ if self.cursor.first_enclosing(MultiImport) is not None:
395
+ return ident
396
+
397
+ # Type attribution correctly resolves typing.Text to str
398
+ # (since Text is just an alias), so we can't use field_type to
399
+ # confirm the import origin. Instead we rely on the name check
400
+ # and the import-context guard above.
401
+ maybe_remove_import(
402
+ self, RemoveImportOptions(module="typing", name="Text")
403
+ )
404
+ return ident.replace(_simple_name="str")
405
+
406
+ return Visitor()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openrewrite-migrate-python
3
- Version: 0.6.0.dev20260418171218
3
+ Version: 0.6.0.dev20260420171522
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