openrewrite-migrate-python 0.11.0.dev20260728173129__tar.gz → 0.12.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.
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/PKG-INFO +1 -1
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/pyproject.toml +1 -1
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/__init__.py +4 -0
- openrewrite_migrate_python-0.12.0/src/openrewrite_migrate_python/migrate/_import_hygiene.py +55 -0
- openrewrite_migrate_python-0.12.0/src/openrewrite_migrate_python/migrate/_typing_imports.py +48 -0
- openrewrite_migrate_python-0.12.0/src/openrewrite_migrate_python/migrate/collections_abc_migrations.py +105 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/future_imports.py +3 -1
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/typing_callable.py +5 -4
- openrewrite_migrate_python-0.12.0/src/openrewrite_migrate_python/migrate/typing_deprecations.py +360 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/typing_union_to_pipe.py +79 -50
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python311.py +3 -0
- openrewrite_migrate_python-0.12.0/src/openrewrite_migrate_python/migrate/upgrade_to_python39.py +154 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python.egg-info/PKG-INFO +1 -1
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python.egg-info/SOURCES.txt +3 -1
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_collections_abc_migrations.py +103 -0
- openrewrite_migrate_python-0.12.0/tests/test_typing_alias_moves.py +142 -0
- openrewrite_migrate_python-0.12.0/tests/test_typing_callable.py +65 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_typing_deprecations.py +194 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_typing_union_to_pipe.py +92 -4
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_upgrade_recipes.py +5 -0
- openrewrite_migrate_python-0.11.0.dev20260728173129/src/openrewrite_migrate_python/migrate/collections_abc_migrations.py +0 -207
- openrewrite_migrate_python-0.11.0.dev20260728173129/src/openrewrite_migrate_python/migrate/typing_deprecations.py +0 -406
- openrewrite_migrate_python-0.11.0.dev20260728173129/src/openrewrite_migrate_python/migrate/upgrade_to_python39.py +0 -130
- openrewrite_migrate_python-0.11.0.dev20260728173129/tests/test_change_type_recipes.py +0 -65
- openrewrite_migrate_python-0.11.0.dev20260728173129/tests/test_typing_callable.py +0 -25
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/setup.cfg +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_code_quality_python/__init__.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_code_quality_python/codequality/__init__.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_code_quality_python/codequality/_semantically_equal.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_code_quality_python/codequality/all_branches_identical.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_code_quality_python/codequality/boolean_checks_not_inverted.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_code_quality_python/codequality/collapsible_if_statements.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_code_quality_python/codequality/merge_identical_branches.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_code_quality_python/codequality/remove_duplicate_conditions.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_code_quality_python/codequality/remove_self_assignment.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_code_quality_python/codequality/remove_unconditional_value_overwrite.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_code_quality_python/codequality/simplify_boolean_literal.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_code_quality_python/codequality/simplify_redundant_logical_expression.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/__init__.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/_markers.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/aifc_migrations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/array_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/ast_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/asyncio_coroutine_to_async.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/asyncio_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/avro_migrations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/calendar_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/cgi_migrations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/cgi_parse_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/configparser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/datetime_utc.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/distutils_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/distutils_migrations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/functools_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/gettext_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/html_parser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/imp_migrations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/langchain_classic_imports.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/langchain_community_imports.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/langchain_provider_imports.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/locale_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/locale_getdefaultlocale_deprecation.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/macpath_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/mailcap_migrations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/nntplib_migrations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/os_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/pathlib_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/pep594_system_migrations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/pipes_migrations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/pkgutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/platform_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/pydantic_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/pydantic_fields.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/pydantic_model_fields.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/re_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/removed_modules_312.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/shutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/socket_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/ssl_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/string_formatting.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/sys_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/sys_last_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/tarfile_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/telnetlib_migrations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/tempfile_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/threading_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/threading_is_alive_deprecation.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/unittest_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/upgrade_to_langchain02.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/upgrade_to_langchain1.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/upgrade_to_pydantic.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python310.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python312.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python313.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python314.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python38.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/urllib_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/uu_migrations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/xdrlib_migrations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python/migrate/xml_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python.egg-info/dependency_links.txt +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python.egg-info/entry_points.txt +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python.egg-info/requires.txt +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/src/openrewrite_migrate_python.egg-info/top_level.txt +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_aifc_migrations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_array_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_ast_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_asyncio_coroutine_to_async.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_asyncio_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_avro_migrations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_calendar_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_cgi_parse_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_change_import_recipes.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_configparser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_datetime_utc.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_distutils_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_future_imports.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_gettext_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_html_parser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_imp_migrations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_langchain_classic_imports.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_langchain_community_imports.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_langchain_provider_imports.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_locale_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_locale_getdefaultlocale_deprecation.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_macpath_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_os_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_pep594_migrations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_pep594_system_migrations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_pkgutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_platform_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_pydantic_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_pydantic_fields.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_pydantic_model_fields.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_re_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_removed_modules_312.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_shutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_ssl_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_string_formatting.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_sys_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_sys_last_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_tarfile_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_threading_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_threading_extended.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_threading_is_alive_deprecation.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_unittest_deprecations.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_upgrade_to_pydantic.py +0 -0
- {openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/tests/test_xml_deprecations.py +0 -0
{openrewrite_migrate_python-0.11.0.dev20260728173129 → openrewrite_migrate_python-0.12.0}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openrewrite-migrate-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.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
|
|
@@ -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.
|
|
8
|
+
version = "0.12.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"
|
|
@@ -100,10 +100,12 @@ from .threading_deprecations import (
|
|
|
100
100
|
from .typing_callable import ReplaceTypingCallableWithCollectionsAbcCallable
|
|
101
101
|
from .typing_deprecations import (
|
|
102
102
|
ReplaceTypingDictWithDict,
|
|
103
|
+
ReplaceTypingFrozenSetWithFrozenset,
|
|
103
104
|
ReplaceTypingListWithList,
|
|
104
105
|
ReplaceTypingSetWithSet,
|
|
105
106
|
ReplaceTypingText,
|
|
106
107
|
ReplaceTypingTupleWithTuple,
|
|
108
|
+
ReplaceTypingTypeWithType,
|
|
107
109
|
)
|
|
108
110
|
from .typing_union_to_pipe import (
|
|
109
111
|
ReplaceTypingOptionalWithUnion,
|
|
@@ -222,11 +224,13 @@ __all__ = [
|
|
|
222
224
|
# Auto-fix: Typing
|
|
223
225
|
"ReplaceTypingCallableWithCollectionsAbcCallable",
|
|
224
226
|
"ReplaceTypingDictWithDict",
|
|
227
|
+
"ReplaceTypingFrozenSetWithFrozenset",
|
|
225
228
|
"ReplaceTypingListWithList",
|
|
226
229
|
"ReplaceTypingOptionalWithUnion",
|
|
227
230
|
"ReplaceTypingSetWithSet",
|
|
228
231
|
"ReplaceTypingText",
|
|
229
232
|
"ReplaceTypingTupleWithTuple",
|
|
233
|
+
"ReplaceTypingTypeWithType",
|
|
230
234
|
"ReplaceTypingUnionWithPipe",
|
|
231
235
|
# Auto-fix: Unittest
|
|
232
236
|
"ReplaceUnittestDeprecatedAliases",
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Internal cleanup recipe shared by composites built on `ChangeImport`.
|
|
2
|
+
|
|
3
|
+
When every name of a ``from X import a, b`` statement is migrated away, the
|
|
4
|
+
SDK's `ChangeImport` drops the emptied statement without transferring its
|
|
5
|
+
prefix, which can leave a blank line at the very start of the file. This
|
|
6
|
+
recipe trims it. It runs as the last step of a composite, after all import
|
|
7
|
+
rewrites have been applied.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from rewrite import ExecutionContext, Recipe, TreeVisitor
|
|
13
|
+
from rewrite.java.support_types import JRightPadded
|
|
14
|
+
from rewrite.java.tree import Import
|
|
15
|
+
from rewrite.python.tree import CompilationUnit, MultiImport
|
|
16
|
+
from rewrite.python.visitor import PythonVisitor
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TrimLeadingBlankLines(Recipe):
|
|
20
|
+
"""Remove blank lines that precede a file's first import statement."""
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def name(self) -> str:
|
|
24
|
+
return "org.openrewrite.python.migrate.TrimLeadingBlankLines"
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def display_name(self) -> str:
|
|
28
|
+
return "Trim blank lines before a leading import"
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def description(self) -> str:
|
|
32
|
+
return "Remove blank lines that precede a file's first import statement."
|
|
33
|
+
|
|
34
|
+
def editor(self) -> TreeVisitor[Any, ExecutionContext]:
|
|
35
|
+
class Visitor(PythonVisitor[ExecutionContext]):
|
|
36
|
+
def visit_compilation_unit(
|
|
37
|
+
self, cu: CompilationUnit, p: ExecutionContext
|
|
38
|
+
) -> CompilationUnit:
|
|
39
|
+
padded_stmts = list(cu.padding.statements)
|
|
40
|
+
if not padded_stmts:
|
|
41
|
+
return cu
|
|
42
|
+
first = padded_stmts[0]
|
|
43
|
+
stmt = first.element
|
|
44
|
+
if not isinstance(stmt, (Import, MultiImport)):
|
|
45
|
+
return cu
|
|
46
|
+
prefix = stmt.prefix
|
|
47
|
+
if prefix.comments or not prefix.whitespace or not prefix.whitespace.startswith("\n"):
|
|
48
|
+
return cu
|
|
49
|
+
new_prefix = prefix.replace(_whitespace=prefix.whitespace.lstrip("\n"))
|
|
50
|
+
padded_stmts[0] = JRightPadded(
|
|
51
|
+
stmt.replace(prefix=new_prefix), first.after, first.markers
|
|
52
|
+
)
|
|
53
|
+
return cu.padding.replace(_statements=padded_stmts)
|
|
54
|
+
|
|
55
|
+
return Visitor()
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Internal helpers for locating references to the typing module in a file."""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Set, Tuple
|
|
4
|
+
|
|
5
|
+
from rewrite.java.tree import Import
|
|
6
|
+
from rewrite.python.import_utils import get_alias_name, get_name_string, get_qualid_name
|
|
7
|
+
from rewrite.python.remove_import import RemoveImportOptions, maybe_remove_import
|
|
8
|
+
from rewrite.python.tree import CompilationUnit, MultiImport
|
|
9
|
+
from rewrite.python.visitor import PythonVisitor
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def scan_typing_imports(cu: CompilationUnit) -> Tuple[Dict[str, str], Set[str]]:
|
|
13
|
+
"""Map how this file can reference typing members.
|
|
14
|
+
|
|
15
|
+
Returns:
|
|
16
|
+
A tuple of:
|
|
17
|
+
- exposed name -> typing member, for ``from typing import member [as alias]``
|
|
18
|
+
- the set of names bound to the typing module itself, for
|
|
19
|
+
``import typing [as alias]``
|
|
20
|
+
"""
|
|
21
|
+
members: Dict[str, str] = {}
|
|
22
|
+
module_refs: Set[str] = set()
|
|
23
|
+
for stmt in cu.statements:
|
|
24
|
+
if isinstance(stmt, MultiImport):
|
|
25
|
+
if stmt.from_ is not None:
|
|
26
|
+
if get_name_string(stmt.from_) == "typing":
|
|
27
|
+
for imp in stmt.names:
|
|
28
|
+
name = get_qualid_name(imp.qualid)
|
|
29
|
+
members.setdefault(get_alias_name(imp) or name, name)
|
|
30
|
+
else:
|
|
31
|
+
for imp in stmt.names:
|
|
32
|
+
if get_qualid_name(imp.qualid) == "typing":
|
|
33
|
+
module_refs.add(get_alias_name(imp) or "typing")
|
|
34
|
+
elif isinstance(stmt, Import):
|
|
35
|
+
if get_qualid_name(stmt.qualid) == "typing":
|
|
36
|
+
module_refs.add(get_alias_name(stmt) or "typing")
|
|
37
|
+
return members, module_refs
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def maybe_remove_typing_module_import(visitor: PythonVisitor, module_refs: Set[str]) -> None:
|
|
41
|
+
"""Schedule removal of `import typing` once it is no longer used.
|
|
42
|
+
|
|
43
|
+
RemoveImport's usage check counts `typing` identifiers, which an aliased
|
|
44
|
+
module import doesn't produce — removal is only scheduled when an
|
|
45
|
+
unaliased `import typing` exists.
|
|
46
|
+
"""
|
|
47
|
+
if "typing" in module_refs:
|
|
48
|
+
maybe_remove_import(visitor, RemoveImportOptions(module="typing"))
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Recipes for migrating deprecated collections imports to collections.abc.
|
|
3
|
+
|
|
4
|
+
The abstract base classes were moved from `collections` to `collections.abc`
|
|
5
|
+
in Python 3.3 and the old import locations were removed in Python 3.10.
|
|
6
|
+
|
|
7
|
+
See: https://docs.python.org/3/library/collections.abc.html
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import List
|
|
11
|
+
|
|
12
|
+
from rewrite import Recipe
|
|
13
|
+
from rewrite.category import CategoryDescriptor
|
|
14
|
+
from rewrite.decorators import categorize
|
|
15
|
+
from rewrite.marketplace import Python
|
|
16
|
+
from rewrite.python.recipes import ChangeImport
|
|
17
|
+
|
|
18
|
+
# Define category path: Python > Migrate > Python 3.10
|
|
19
|
+
_Python310 = [
|
|
20
|
+
*Python,
|
|
21
|
+
CategoryDescriptor(display_name="Migrate"),
|
|
22
|
+
CategoryDescriptor(display_name="Python 3.10"),
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
# All ABC aliases that `collections` re-exported until their removal in
|
|
26
|
+
# Python 3.10 (`_collections_abc.__all__` as of Python 3.9).
|
|
27
|
+
COLLECTIONS_ABC_CLASSES: tuple = (
|
|
28
|
+
"AsyncGenerator",
|
|
29
|
+
"AsyncIterable",
|
|
30
|
+
"AsyncIterator",
|
|
31
|
+
"Awaitable",
|
|
32
|
+
"ByteString",
|
|
33
|
+
"Callable",
|
|
34
|
+
"Collection",
|
|
35
|
+
"Container",
|
|
36
|
+
"Coroutine",
|
|
37
|
+
"Generator",
|
|
38
|
+
"Hashable",
|
|
39
|
+
"ItemsView",
|
|
40
|
+
"Iterable",
|
|
41
|
+
"Iterator",
|
|
42
|
+
"KeysView",
|
|
43
|
+
"Mapping",
|
|
44
|
+
"MappingView",
|
|
45
|
+
"MutableMapping",
|
|
46
|
+
"MutableSequence",
|
|
47
|
+
"MutableSet",
|
|
48
|
+
"Reversible",
|
|
49
|
+
"Sequence",
|
|
50
|
+
"Set",
|
|
51
|
+
"Sized",
|
|
52
|
+
"ValuesView",
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@categorize(_Python310)
|
|
57
|
+
class ReplaceCollectionsAbcImports(Recipe):
|
|
58
|
+
"""
|
|
59
|
+
Replace deprecated `collections` imports with `collections.abc` imports.
|
|
60
|
+
|
|
61
|
+
The abstract base classes were moved from `collections` to `collections.abc`
|
|
62
|
+
in Python 3.3 and the old import locations were removed in Python 3.10.
|
|
63
|
+
|
|
64
|
+
Example:
|
|
65
|
+
Before:
|
|
66
|
+
from collections import Callable, Mapping
|
|
67
|
+
|
|
68
|
+
After:
|
|
69
|
+
from collections.abc import Callable, Mapping
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def name(self) -> str:
|
|
74
|
+
return "org.openrewrite.python.migrate.ReplaceCollectionsAbcImports"
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def display_name(self) -> str:
|
|
78
|
+
return "Replace `collections` ABC imports with `collections.abc`"
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def description(self) -> str:
|
|
82
|
+
return (
|
|
83
|
+
"Migrate deprecated abstract base class imports from `collections` to "
|
|
84
|
+
"`collections.abc`. These imports were deprecated in Python 3.3 and "
|
|
85
|
+
"removed in Python 3.10."
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def tags(self) -> List[str]:
|
|
90
|
+
return ["python", "migration", "3.10", "collections"]
|
|
91
|
+
|
|
92
|
+
def recipe_list(self) -> List[Recipe]:
|
|
93
|
+
from ._import_hygiene import TrimLeadingBlankLines
|
|
94
|
+
|
|
95
|
+
return [
|
|
96
|
+
*(
|
|
97
|
+
ChangeImport(
|
|
98
|
+
old_module="collections",
|
|
99
|
+
old_name=abc_class,
|
|
100
|
+
new_module="collections.abc",
|
|
101
|
+
)
|
|
102
|
+
for abc_class in COLLECTIONS_ABC_CLASSES
|
|
103
|
+
),
|
|
104
|
+
TrimLeadingBlankLines(),
|
|
105
|
+
]
|
|
@@ -91,7 +91,9 @@ class RemoveFutureImports(Recipe):
|
|
|
91
91
|
def description(self) -> str:
|
|
92
92
|
return (
|
|
93
93
|
"Remove `from __future__ import ...` statements for features that "
|
|
94
|
-
"are enabled by default in Python 3."
|
|
94
|
+
"are enabled by default in Python 3. The search-only `FindFutureImports` "
|
|
95
|
+
"recipe reports all `__future__` imports, including `annotations`, "
|
|
96
|
+
"which this recipe keeps."
|
|
95
97
|
)
|
|
96
98
|
|
|
97
99
|
@property
|
|
@@ -15,7 +15,7 @@ from rewrite import Recipe
|
|
|
15
15
|
from rewrite.category import CategoryDescriptor
|
|
16
16
|
from rewrite.decorators import categorize
|
|
17
17
|
from rewrite.marketplace import Python
|
|
18
|
-
from rewrite.python.recipes import
|
|
18
|
+
from rewrite.python.recipes import ChangeImport
|
|
19
19
|
|
|
20
20
|
# Define category path
|
|
21
21
|
_Python39 = [
|
|
@@ -60,8 +60,9 @@ class ReplaceTypingCallableWithCollectionsAbcCallable(Recipe):
|
|
|
60
60
|
|
|
61
61
|
def recipe_list(self) -> List[Recipe]:
|
|
62
62
|
return [
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
ChangeImport(
|
|
64
|
+
old_module="typing",
|
|
65
|
+
old_name="Callable",
|
|
66
|
+
new_module="collections.abc",
|
|
66
67
|
)
|
|
67
68
|
]
|
openrewrite_migrate_python-0.12.0/src/openrewrite_migrate_python/migrate/typing_deprecations.py
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Recipes for migrating deprecated typing module aliases to built-in types.
|
|
3
|
+
|
|
4
|
+
PEP 585 (Python 3.9+) deprecated the typing aliases for built-in generics:
|
|
5
|
+
|
|
6
|
+
- typing.List[X] -> list[X]
|
|
7
|
+
- typing.Dict[K, V] -> dict[K, V]
|
|
8
|
+
- typing.Set[X] -> set[X]
|
|
9
|
+
- typing.FrozenSet[X] -> frozenset[X]
|
|
10
|
+
- typing.Tuple[X, ...] -> tuple[X, ...]
|
|
11
|
+
- typing.Type[X] -> type[X]
|
|
12
|
+
|
|
13
|
+
Additionally, typing.Text (an alias for str, deprecated in Python 3.11) is
|
|
14
|
+
migrated to str by the same mechanism.
|
|
15
|
+
|
|
16
|
+
Aliases that moved to another stdlib module (typing.Iterable, typing.Deque,
|
|
17
|
+
typing.Pattern, ...) are import moves rather than builtin renames; they are
|
|
18
|
+
handled with `ChangeImport` in `upgrade_to_python39`.
|
|
19
|
+
|
|
20
|
+
See: https://peps.python.org/pep-0585/
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import re
|
|
24
|
+
from typing import Any, ClassVar, Optional, Set, cast
|
|
25
|
+
|
|
26
|
+
from rewrite import ExecutionContext, Recipe, TreeVisitor
|
|
27
|
+
from rewrite.category import CategoryDescriptor
|
|
28
|
+
from rewrite.decorators import categorize
|
|
29
|
+
from rewrite.marketplace import Python
|
|
30
|
+
from rewrite.python.import_utils import get_alias_name, get_name_string, get_qualid_name
|
|
31
|
+
from rewrite.python.remove_import import RemoveImportOptions, maybe_remove_import
|
|
32
|
+
|
|
33
|
+
from ._typing_imports import maybe_remove_typing_module_import
|
|
34
|
+
from rewrite.python.tree import CompilationUnit, MultiImport, NamedArgument
|
|
35
|
+
from rewrite.python.visitor import PythonVisitor
|
|
36
|
+
from rewrite.java.tree import (
|
|
37
|
+
FieldAccess,
|
|
38
|
+
Identifier,
|
|
39
|
+
Import,
|
|
40
|
+
J,
|
|
41
|
+
Literal,
|
|
42
|
+
MethodDeclaration,
|
|
43
|
+
VariableDeclarations,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
# Define category paths
|
|
47
|
+
_Python39 = [
|
|
48
|
+
*Python,
|
|
49
|
+
CategoryDescriptor(display_name="Migrate"),
|
|
50
|
+
CategoryDescriptor(display_name="Python 3.9"),
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
_Python311 = [
|
|
54
|
+
*Python,
|
|
55
|
+
CategoryDescriptor(display_name="Migrate"),
|
|
56
|
+
CategoryDescriptor(display_name="Python 3.11"),
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _make_builtin_alias_editor(old_name: str, new_name: str) -> "TreeVisitor[Any, ExecutionContext]":
|
|
61
|
+
"""Create a visitor that renames a typing alias to its built-in equivalent.
|
|
62
|
+
|
|
63
|
+
Handles both reference forms and cleans up imports afterwards:
|
|
64
|
+
|
|
65
|
+
- ``from typing import <old_name> [as alias]`` plus bare (or aliased)
|
|
66
|
+
identifier references
|
|
67
|
+
- ``import typing [as alias]`` plus qualified ``typing.<old_name>``
|
|
68
|
+
attribute references
|
|
69
|
+
|
|
70
|
+
Import removal is delegated to the SDK's `RemoveImport`, which only
|
|
71
|
+
removes imports that are no longer referenced and preserves comments.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
class BuiltinAliasVisitor(PythonVisitor[ExecutionContext]):
|
|
75
|
+
def __init__(self) -> None:
|
|
76
|
+
super().__init__()
|
|
77
|
+
# Name that refers to the alias in code: the import alias if
|
|
78
|
+
# present, else the typing name. None when there is no from-import.
|
|
79
|
+
self._bare_ref: Optional[str] = None
|
|
80
|
+
# Names that refer to the typing module ('typing' or import aliases).
|
|
81
|
+
self._module_refs: Set[str] = set()
|
|
82
|
+
self._keep_from_import: bool = False
|
|
83
|
+
self._rewrote_qualified: bool = False
|
|
84
|
+
|
|
85
|
+
def visit_compilation_unit(
|
|
86
|
+
self, cu: CompilationUnit, p: ExecutionContext
|
|
87
|
+
) -> CompilationUnit:
|
|
88
|
+
self._bare_ref = None
|
|
89
|
+
self._module_refs = set()
|
|
90
|
+
self._rewrote_qualified = False
|
|
91
|
+
|
|
92
|
+
for stmt in cu.statements:
|
|
93
|
+
if isinstance(stmt, MultiImport):
|
|
94
|
+
if stmt.from_ is not None:
|
|
95
|
+
if get_name_string(stmt.from_) == "typing":
|
|
96
|
+
for imp in stmt.names:
|
|
97
|
+
if get_qualid_name(imp.qualid) == old_name and self._bare_ref is None:
|
|
98
|
+
self._bare_ref = get_alias_name(imp) or old_name
|
|
99
|
+
else:
|
|
100
|
+
for imp in stmt.names:
|
|
101
|
+
if get_qualid_name(imp.qualid) == "typing":
|
|
102
|
+
self._module_refs.add(get_alias_name(imp) or "typing")
|
|
103
|
+
elif isinstance(stmt, Import):
|
|
104
|
+
if get_qualid_name(stmt.qualid) == "typing":
|
|
105
|
+
self._module_refs.add(get_alias_name(stmt) or "typing")
|
|
106
|
+
|
|
107
|
+
if self._bare_ref is None and not self._module_refs:
|
|
108
|
+
return cu
|
|
109
|
+
|
|
110
|
+
# A reference inside a string annotation is a Literal, not an
|
|
111
|
+
# Identifier, so it is neither renamed nor seen by RemoveImport's
|
|
112
|
+
# usage check; keep the import so such references stay resolvable.
|
|
113
|
+
self._keep_from_import = self._bare_ref is not None and self._used_in_string_literal(
|
|
114
|
+
cu, self._bare_ref
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
result = cast(CompilationUnit, super().visit_compilation_unit(cu, p))
|
|
118
|
+
|
|
119
|
+
if self._bare_ref is not None and not self._keep_from_import:
|
|
120
|
+
maybe_remove_import(
|
|
121
|
+
self, RemoveImportOptions(module="typing", name=old_name)
|
|
122
|
+
)
|
|
123
|
+
if self._rewrote_qualified:
|
|
124
|
+
maybe_remove_typing_module_import(self, self._module_refs)
|
|
125
|
+
|
|
126
|
+
return result
|
|
127
|
+
|
|
128
|
+
@staticmethod
|
|
129
|
+
def _used_in_string_literal(cu: CompilationUnit, name: str) -> bool:
|
|
130
|
+
pattern = re.compile(rf"\b{re.escape(name)}\b")
|
|
131
|
+
found = False
|
|
132
|
+
|
|
133
|
+
class LiteralScan(PythonVisitor[Any]):
|
|
134
|
+
def visit_literal(self, literal: Literal, p: Any) -> J:
|
|
135
|
+
nonlocal found
|
|
136
|
+
if not found and isinstance(literal.value, str) and pattern.search(literal.value):
|
|
137
|
+
found = True
|
|
138
|
+
return literal
|
|
139
|
+
|
|
140
|
+
LiteralScan().visit(cu, None)
|
|
141
|
+
return found
|
|
142
|
+
|
|
143
|
+
def visit_field_access(self, field_access: FieldAccess, p: ExecutionContext) -> J:
|
|
144
|
+
if (
|
|
145
|
+
isinstance(field_access.target, Identifier)
|
|
146
|
+
and field_access.target.simple_name in self._module_refs
|
|
147
|
+
and field_access.name.simple_name == old_name
|
|
148
|
+
):
|
|
149
|
+
self._rewrote_qualified = True
|
|
150
|
+
return field_access.name.replace(_simple_name=new_name).replace(
|
|
151
|
+
prefix=field_access.prefix
|
|
152
|
+
)
|
|
153
|
+
return super().visit_field_access(field_access, p)
|
|
154
|
+
|
|
155
|
+
def visit_identifier(self, ident: Identifier, p: ExecutionContext) -> J:
|
|
156
|
+
ident = cast(Identifier, super().visit_identifier(ident, p))
|
|
157
|
+
if self._bare_ref is None or ident.simple_name != self._bare_ref:
|
|
158
|
+
return ident
|
|
159
|
+
|
|
160
|
+
# Skip identifiers that are part of import statements
|
|
161
|
+
if (
|
|
162
|
+
self.cursor.first_enclosing(MultiImport) is not None
|
|
163
|
+
or self.cursor.first_enclosing(Import) is not None
|
|
164
|
+
):
|
|
165
|
+
return ident
|
|
166
|
+
|
|
167
|
+
parent = self.cursor.parent_tree_cursor().value
|
|
168
|
+
# The attribute of a field access (`x.List`) belongs to `x`'s
|
|
169
|
+
# namespace, not to the typing import.
|
|
170
|
+
if isinstance(parent, FieldAccess) and parent.name.id == ident.id:
|
|
171
|
+
return ident
|
|
172
|
+
# A keyword-argument name (`f(List=...)`) names a parameter.
|
|
173
|
+
if isinstance(parent, NamedArgument) and parent.name.id == ident.id:
|
|
174
|
+
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
|
+
):
|
|
188
|
+
return ident
|
|
189
|
+
|
|
190
|
+
return ident.replace(_simple_name=new_name)
|
|
191
|
+
|
|
192
|
+
return BuiltinAliasVisitor()
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
class _ReplaceTypingAliasRecipe(Recipe):
|
|
196
|
+
"""Base for recipes that replace a typing alias with a built-in type."""
|
|
197
|
+
|
|
198
|
+
old_name: ClassVar[str]
|
|
199
|
+
new_name: ClassVar[str]
|
|
200
|
+
|
|
201
|
+
@property
|
|
202
|
+
def name(self) -> str:
|
|
203
|
+
return (
|
|
204
|
+
"org.openrewrite.python.migrate."
|
|
205
|
+
f"ReplaceTyping{self.old_name}With{self.new_name.capitalize()}"
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
@property
|
|
209
|
+
def display_name(self) -> str:
|
|
210
|
+
return f"Replace `typing.{self.old_name}` with `{self.new_name}`"
|
|
211
|
+
|
|
212
|
+
@property
|
|
213
|
+
def description(self) -> str:
|
|
214
|
+
return (
|
|
215
|
+
f"PEP 585 deprecated `typing.{self.old_name}` in Python 3.9. "
|
|
216
|
+
f"Replace with the built-in `{self.new_name}` type for generic annotations."
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
def editor(self) -> TreeVisitor[Any, ExecutionContext]:
|
|
220
|
+
return _make_builtin_alias_editor(self.old_name, self.new_name)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
@categorize(_Python39)
|
|
224
|
+
class ReplaceTypingListWithList(_ReplaceTypingAliasRecipe):
|
|
225
|
+
"""
|
|
226
|
+
Migrate `typing.List` to built-in `list`.
|
|
227
|
+
|
|
228
|
+
Example:
|
|
229
|
+
Before:
|
|
230
|
+
from typing import List
|
|
231
|
+
items: List[str] = []
|
|
232
|
+
|
|
233
|
+
After:
|
|
234
|
+
items: list[str] = []
|
|
235
|
+
"""
|
|
236
|
+
|
|
237
|
+
old_name = "List"
|
|
238
|
+
new_name = "list"
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
@categorize(_Python39)
|
|
242
|
+
class ReplaceTypingDictWithDict(_ReplaceTypingAliasRecipe):
|
|
243
|
+
"""
|
|
244
|
+
Migrate `typing.Dict` to built-in `dict`.
|
|
245
|
+
|
|
246
|
+
Example:
|
|
247
|
+
Before:
|
|
248
|
+
from typing import Dict
|
|
249
|
+
mapping: Dict[str, int] = {}
|
|
250
|
+
|
|
251
|
+
After:
|
|
252
|
+
mapping: dict[str, int] = {}
|
|
253
|
+
"""
|
|
254
|
+
|
|
255
|
+
old_name = "Dict"
|
|
256
|
+
new_name = "dict"
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
@categorize(_Python39)
|
|
260
|
+
class ReplaceTypingSetWithSet(_ReplaceTypingAliasRecipe):
|
|
261
|
+
"""
|
|
262
|
+
Migrate `typing.Set` to built-in `set`.
|
|
263
|
+
|
|
264
|
+
Example:
|
|
265
|
+
Before:
|
|
266
|
+
from typing import Set
|
|
267
|
+
items: Set[int] = set()
|
|
268
|
+
|
|
269
|
+
After:
|
|
270
|
+
items: set[int] = set()
|
|
271
|
+
"""
|
|
272
|
+
|
|
273
|
+
old_name = "Set"
|
|
274
|
+
new_name = "set"
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
@categorize(_Python39)
|
|
278
|
+
class ReplaceTypingFrozenSetWithFrozenset(_ReplaceTypingAliasRecipe):
|
|
279
|
+
"""
|
|
280
|
+
Migrate `typing.FrozenSet` to built-in `frozenset`.
|
|
281
|
+
|
|
282
|
+
Example:
|
|
283
|
+
Before:
|
|
284
|
+
from typing import FrozenSet
|
|
285
|
+
items: FrozenSet[int] = frozenset()
|
|
286
|
+
|
|
287
|
+
After:
|
|
288
|
+
items: frozenset[int] = frozenset()
|
|
289
|
+
"""
|
|
290
|
+
|
|
291
|
+
old_name = "FrozenSet"
|
|
292
|
+
new_name = "frozenset"
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
@categorize(_Python39)
|
|
296
|
+
class ReplaceTypingTupleWithTuple(_ReplaceTypingAliasRecipe):
|
|
297
|
+
"""
|
|
298
|
+
Migrate `typing.Tuple` to built-in `tuple`.
|
|
299
|
+
|
|
300
|
+
Example:
|
|
301
|
+
Before:
|
|
302
|
+
from typing import Tuple
|
|
303
|
+
point: Tuple[int, int] = (0, 0)
|
|
304
|
+
|
|
305
|
+
After:
|
|
306
|
+
point: tuple[int, int] = (0, 0)
|
|
307
|
+
"""
|
|
308
|
+
|
|
309
|
+
old_name = "Tuple"
|
|
310
|
+
new_name = "tuple"
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
@categorize(_Python39)
|
|
314
|
+
class ReplaceTypingTypeWithType(_ReplaceTypingAliasRecipe):
|
|
315
|
+
"""
|
|
316
|
+
Migrate `typing.Type` to built-in `type`.
|
|
317
|
+
|
|
318
|
+
Example:
|
|
319
|
+
Before:
|
|
320
|
+
from typing import Type
|
|
321
|
+
cls: Type[int] = int
|
|
322
|
+
|
|
323
|
+
After:
|
|
324
|
+
cls: type[int] = int
|
|
325
|
+
"""
|
|
326
|
+
|
|
327
|
+
old_name = "Type"
|
|
328
|
+
new_name = "type"
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
@categorize(_Python311)
|
|
332
|
+
class ReplaceTypingText(_ReplaceTypingAliasRecipe):
|
|
333
|
+
"""
|
|
334
|
+
Migrate `typing.Text` to `str`.
|
|
335
|
+
|
|
336
|
+
`typing.Text` was an alias for `str` provided for Python 2/3 compatibility.
|
|
337
|
+
It is deprecated as of Python 3.11 since Python 2 is no longer supported.
|
|
338
|
+
|
|
339
|
+
Example:
|
|
340
|
+
Before:
|
|
341
|
+
from typing import Text
|
|
342
|
+
name: Text = "hello"
|
|
343
|
+
|
|
344
|
+
After:
|
|
345
|
+
name: str = "hello"
|
|
346
|
+
"""
|
|
347
|
+
|
|
348
|
+
old_name = "Text"
|
|
349
|
+
new_name = "str"
|
|
350
|
+
|
|
351
|
+
@property
|
|
352
|
+
def name(self) -> str:
|
|
353
|
+
return "org.openrewrite.python.migrate.ReplaceTypingText"
|
|
354
|
+
|
|
355
|
+
@property
|
|
356
|
+
def description(self) -> str:
|
|
357
|
+
return (
|
|
358
|
+
"`typing.Text` is deprecated as of Python 3.11. "
|
|
359
|
+
"It was an alias for `str` for Python 2/3 compatibility. Replace with `str`."
|
|
360
|
+
)
|