openrewrite-migrate-python 0.14.0.dev20260901135710__tar.gz → 0.14.0.dev20260901153140__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.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/PKG-INFO +1 -1
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/pyproject.toml +1 -1
- openrewrite_migrate_python-0.14.0.dev20260901153140/src/openrewrite_migrate_python/migrate/_typing_imports.py +164 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/typing_deprecations.py +55 -38
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/typing_union_to_pipe.py +14 -5
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python.egg-info/PKG-INFO +1 -1
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_typing_deprecations.py +251 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_typing_union_to_pipe.py +26 -0
- openrewrite_migrate_python-0.14.0.dev20260901135710/src/openrewrite_migrate_python/migrate/_typing_imports.py +0 -48
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/setup.cfg +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_code_quality_python/__init__.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_code_quality_python/codequality/__init__.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_code_quality_python/codequality/_semantically_equal.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_code_quality_python/codequality/all_branches_identical.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_code_quality_python/codequality/boolean_checks_not_inverted.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_code_quality_python/codequality/collapsible_if_statements.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_code_quality_python/codequality/find_suspicious_chained_comparison.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_code_quality_python/codequality/merge_identical_branches.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_code_quality_python/codequality/remove_duplicate_conditions.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_code_quality_python/codequality/remove_self_assignment.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_code_quality_python/codequality/remove_unconditional_value_overwrite.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_code_quality_python/codequality/simplify_boolean_literal.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_code_quality_python/codequality/simplify_redundant_logical_expression.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/__init__.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/__init__.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/_import_hygiene.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/_markers.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/aifc_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/array_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/ast_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/asyncio_coroutine_to_async.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/asyncio_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/avro_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/calendar_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/cgi_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/cgi_parse_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/collections_abc_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/configparser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/datetime_utc.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/distutils_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/distutils_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/functools_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/future_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/gettext_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/html_parser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/imp_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/langchain_classic_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/langchain_community_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/langchain_provider_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/locale_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/locale_getdefaultlocale_deprecation.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/macpath_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/mailcap_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/nntplib_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/os_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/pathlib_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/pep594_system_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/pipes_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/pkgutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/platform_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/pydantic_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/pydantic_fields.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/pydantic_model_fields.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/re_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/removed_modules_312.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/shutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/socket_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/ssl_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/string_formatting.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/sys_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/sys_last_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/tarfile_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/telnetlib_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/tempfile_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/threading_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/threading_is_alive_deprecation.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/typing_callable.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/unittest_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/upgrade_to_langchain02.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/upgrade_to_langchain1.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/upgrade_to_pydantic.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/upgrade_to_python310.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/upgrade_to_python311.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/upgrade_to_python312.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/upgrade_to_python313.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/upgrade_to_python314.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/upgrade_to_python38.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/upgrade_to_python39.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/urllib_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/uu_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/xdrlib_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python/migrate/xml_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python.egg-info/SOURCES.txt +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python.egg-info/dependency_links.txt +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python.egg-info/entry_points.txt +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python.egg-info/requires.txt +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/src/openrewrite_migrate_python.egg-info/top_level.txt +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_aifc_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_array_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_ast_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_asyncio_coroutine_to_async.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_asyncio_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_avro_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_calendar_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_cgi_parse_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_change_import_recipes.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_collections_abc_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_configparser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_datetime_utc.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_distutils_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_future_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_gettext_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_html_parser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_imp_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_langchain_classic_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_langchain_community_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_langchain_provider_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_locale_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_locale_getdefaultlocale_deprecation.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_macpath_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_os_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_pep594_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_pep594_system_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_pkgutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_platform_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_pydantic_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_pydantic_fields.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_pydantic_model_fields.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_re_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_removed_modules_312.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_shutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_ssl_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_string_formatting.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_sys_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_sys_last_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_tarfile_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_threading_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_threading_extended.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_threading_is_alive_deprecation.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_typing_alias_moves.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_typing_callable.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_unittest_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_upgrade_recipes.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/tests/test_upgrade_to_pydantic.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260901135710 → openrewrite_migrate_python-0.14.0.dev20260901153140}/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.14.0.
|
|
3
|
+
Version: 0.14.0.dev20260901153140
|
|
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.14.0.
|
|
8
|
+
version = "0.14.0.dev20260901153140" # Updated dynamically during release
|
|
9
9
|
authors = [{ name = "Moderne Inc.", email = "support@moderne.io" }]
|
|
10
10
|
license = { text = "Moderne Proprietary" }
|
|
11
11
|
readme = "README.md"
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""Internal helpers for locating references to the typing module in a file."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, Iterator, List, Optional, Sequence, Set, Tuple, cast
|
|
4
|
+
|
|
5
|
+
from rewrite.java.support_types import JRightPadded, Space, Statement
|
|
6
|
+
from rewrite.java.tree import Block, If, Import, J
|
|
7
|
+
from rewrite.python.import_utils import get_alias_name, get_name_string, get_qualid_name
|
|
8
|
+
from rewrite.python.remove_import import RemoveImport, RemoveImportOptions, prefix_to_inherit
|
|
9
|
+
from rewrite.python.tree import CompilationUnit, MultiImport
|
|
10
|
+
from rewrite.python.visitor import PythonVisitor
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _module_scope_statements(statements: Sequence[Statement]) -> Iterator[Statement]:
|
|
14
|
+
"""Every statement binding names in the module scope, `if` bodies included.
|
|
15
|
+
|
|
16
|
+
`if TYPE_CHECKING:` is where files that defer their annotations keep their
|
|
17
|
+
typing imports.
|
|
18
|
+
"""
|
|
19
|
+
for stmt in statements:
|
|
20
|
+
yield stmt
|
|
21
|
+
body = _unconditional_body(stmt) if isinstance(stmt, If) else None
|
|
22
|
+
if body is not None:
|
|
23
|
+
yield from _module_scope_statements(body.statements)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _unconditional_body(if_: If) -> Optional[Block]:
|
|
27
|
+
"""The body of an `if` that only adds bindings to the enclosing scope.
|
|
28
|
+
|
|
29
|
+
None once there is an `else`: the branches are then alternative bindings of
|
|
30
|
+
the same name, and honouring one would rewrite the other's binding too.
|
|
31
|
+
"""
|
|
32
|
+
then_part = if_.then_part
|
|
33
|
+
return then_part if if_.else_part is None and isinstance(then_part, Block) else None
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def scan_typing_imports(cu: CompilationUnit) -> Tuple[Dict[str, str], Set[str]]:
|
|
37
|
+
"""Map how this file can reference typing members.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
A tuple of:
|
|
41
|
+
- exposed name -> typing member, for ``from typing import member [as alias]``
|
|
42
|
+
- the set of names bound to the typing module itself, for
|
|
43
|
+
``import typing [as alias]``
|
|
44
|
+
"""
|
|
45
|
+
members: Dict[str, str] = {}
|
|
46
|
+
module_refs: Set[str] = set()
|
|
47
|
+
for stmt in _module_scope_statements(cu.statements):
|
|
48
|
+
if isinstance(stmt, MultiImport):
|
|
49
|
+
if stmt.from_ is not None:
|
|
50
|
+
if get_name_string(stmt.from_) == "typing":
|
|
51
|
+
for imp in stmt.names:
|
|
52
|
+
name = get_qualid_name(imp.qualid)
|
|
53
|
+
members.setdefault(get_alias_name(imp) or name, name)
|
|
54
|
+
else:
|
|
55
|
+
for imp in stmt.names:
|
|
56
|
+
if get_qualid_name(imp.qualid) == "typing":
|
|
57
|
+
module_refs.add(get_alias_name(imp) or "typing")
|
|
58
|
+
elif isinstance(stmt, Import):
|
|
59
|
+
if get_qualid_name(stmt.qualid) == "typing":
|
|
60
|
+
module_refs.add(get_alias_name(stmt) or "typing")
|
|
61
|
+
return members, module_refs
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def maybe_remove_typing_import(visitor: PythonVisitor, name: Optional[str] = None) -> None:
|
|
65
|
+
"""Schedule removal of a typing import once it is no longer used.
|
|
66
|
+
|
|
67
|
+
Mirrors the SDK's `maybe_remove_import`, registering the block-aware visitor.
|
|
68
|
+
"""
|
|
69
|
+
options = RemoveImportOptions(module="typing", name=name)
|
|
70
|
+
if visitor._after_visit is None:
|
|
71
|
+
visitor._after_visit = []
|
|
72
|
+
for scheduled in visitor._after_visit:
|
|
73
|
+
# Only this visitor counts as already scheduled: a plain `RemoveImport`
|
|
74
|
+
# for the same name reaches the top level alone, and would leave the
|
|
75
|
+
# nested imports this exists to remove.
|
|
76
|
+
if (
|
|
77
|
+
type(scheduled) is _RemoveImportInBlocks
|
|
78
|
+
and scheduled.module == options.module
|
|
79
|
+
and scheduled.name == options.name
|
|
80
|
+
):
|
|
81
|
+
return
|
|
82
|
+
visitor._after_visit.append(_RemoveImportInBlocks(options))
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def maybe_remove_typing_module_import(visitor: PythonVisitor, module_refs: Set[str]) -> None:
|
|
86
|
+
"""Schedule removal of `import typing` once it is no longer used.
|
|
87
|
+
|
|
88
|
+
RemoveImport's usage check counts `typing` identifiers, which an aliased
|
|
89
|
+
module import doesn't produce — removal is only scheduled when an
|
|
90
|
+
unaliased `import typing` exists.
|
|
91
|
+
"""
|
|
92
|
+
if "typing" in module_refs:
|
|
93
|
+
maybe_remove_typing_import(visitor)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class _RemoveImportInBlocks(RemoveImport):
|
|
97
|
+
"""`RemoveImport` extended to imports inside module-scope `if` bodies.
|
|
98
|
+
|
|
99
|
+
The base visitor prunes only the file's top-level statement list.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
def visit_compilation_unit(self, cu: CompilationUnit, p: Any) -> J:
|
|
103
|
+
cu = cast(CompilationUnit, super().visit_compilation_unit(cu, p))
|
|
104
|
+
kept = self._prune(cu.padding.statements, prune_imports=False)
|
|
105
|
+
return cu if kept is None else cu.padding.replace(_statements=kept)
|
|
106
|
+
|
|
107
|
+
def _prune(
|
|
108
|
+
self, padded_statements: Sequence[JRightPadded], prune_imports: bool
|
|
109
|
+
) -> Optional[List[JRightPadded]]:
|
|
110
|
+
"""The statements with the import gone, or None when nothing changed."""
|
|
111
|
+
kept: List[JRightPadded] = []
|
|
112
|
+
inherited: Optional[Space] = None
|
|
113
|
+
changed = False
|
|
114
|
+
for index, padded in enumerate(padded_statements):
|
|
115
|
+
stmt = padded.element
|
|
116
|
+
if isinstance(stmt, If):
|
|
117
|
+
result: Optional[Statement] = self._prune_if(stmt)
|
|
118
|
+
elif prune_imports and isinstance(stmt, MultiImport):
|
|
119
|
+
result = self._process_multi_import(stmt)
|
|
120
|
+
elif prune_imports and isinstance(stmt, Import):
|
|
121
|
+
result = self._process_single_import(stmt)
|
|
122
|
+
else:
|
|
123
|
+
result = stmt
|
|
124
|
+
|
|
125
|
+
if result is None:
|
|
126
|
+
changed = True
|
|
127
|
+
if inherited is None:
|
|
128
|
+
inherited = prefix_to_inherit(stmt, index)
|
|
129
|
+
continue
|
|
130
|
+
if result is not stmt:
|
|
131
|
+
padded = JRightPadded(result, padded.after, padded.markers)
|
|
132
|
+
changed = True
|
|
133
|
+
if inherited is not None:
|
|
134
|
+
if not padded.element.prefix.comments:
|
|
135
|
+
padded = JRightPadded(
|
|
136
|
+
padded.element.replace(prefix=inherited), padded.after, padded.markers
|
|
137
|
+
)
|
|
138
|
+
elif inherited.comments:
|
|
139
|
+
# Neither comment can be given up, and one prefix holds both.
|
|
140
|
+
return None
|
|
141
|
+
inherited = None
|
|
142
|
+
kept.append(padded)
|
|
143
|
+
# A leftover prefix means nothing followed the removal to carry it, so a
|
|
144
|
+
# comment on the removed statement would be dropped with it.
|
|
145
|
+
if inherited is not None and inherited.comments:
|
|
146
|
+
return None
|
|
147
|
+
return kept if changed else None
|
|
148
|
+
|
|
149
|
+
def _prune_if(self, if_: If) -> Optional[If]:
|
|
150
|
+
"""`if_` with the import gone from its body, or None once that empties it."""
|
|
151
|
+
then_part = _unconditional_body(if_)
|
|
152
|
+
if then_part is None:
|
|
153
|
+
return if_
|
|
154
|
+
kept = self._prune(then_part.padding.statements, prune_imports=True)
|
|
155
|
+
if kept is None:
|
|
156
|
+
return if_
|
|
157
|
+
if not kept:
|
|
158
|
+
return None
|
|
159
|
+
padded = if_.padding.then_part
|
|
160
|
+
return if_.padding.replace(
|
|
161
|
+
_then_part=JRightPadded(
|
|
162
|
+
then_part.padding.replace(_statements=kept), padded.after, padded.markers
|
|
163
|
+
)
|
|
164
|
+
)
|
|
@@ -20,18 +20,21 @@ handled with `ChangeImport` in `upgrade_to_python39`.
|
|
|
20
20
|
See: https://peps.python.org/pep-0585/
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
|
-
import
|
|
23
|
+
import ast
|
|
24
24
|
from typing import Any, ClassVar, Optional, Set, cast
|
|
25
25
|
|
|
26
26
|
from rewrite import ExecutionContext, Recipe, TreeVisitor
|
|
27
27
|
from rewrite.category import CategoryDescriptor
|
|
28
28
|
from rewrite.decorators import categorize
|
|
29
29
|
from rewrite.marketplace import Python
|
|
30
|
-
from rewrite.python.
|
|
31
|
-
from rewrite.python.remove_import import RemoveImportOptions, maybe_remove_import
|
|
30
|
+
from rewrite.python.markers import Quoted
|
|
32
31
|
from rewrite.python.scope_utils import LocalBindings
|
|
33
32
|
|
|
34
|
-
from ._typing_imports import
|
|
33
|
+
from ._typing_imports import (
|
|
34
|
+
maybe_remove_typing_import,
|
|
35
|
+
maybe_remove_typing_module_import,
|
|
36
|
+
scan_typing_imports,
|
|
37
|
+
)
|
|
35
38
|
from rewrite.python.tree import CompilationUnit, MultiImport, NamedArgument
|
|
36
39
|
from rewrite.python.visitor import PythonVisitor
|
|
37
40
|
from rewrite.java.tree import (
|
|
@@ -78,67 +81,78 @@ def _make_builtin_alias_editor(old_name: str, new_name: str) -> "TreeVisitor[Any
|
|
|
78
81
|
self._bare_ref: Optional[str] = None
|
|
79
82
|
# Names that refer to the typing module ('typing' or import aliases).
|
|
80
83
|
self._module_refs: Set[str] = set()
|
|
81
|
-
self._keep_from_import: bool = False
|
|
82
84
|
self._rewrote_qualified: bool = False
|
|
83
85
|
self._local_bindings = LocalBindings()
|
|
84
86
|
|
|
85
87
|
def visit_compilation_unit(
|
|
86
88
|
self, cu: CompilationUnit, p: ExecutionContext
|
|
87
89
|
) -> CompilationUnit:
|
|
88
|
-
self._bare_ref = None
|
|
89
|
-
self._module_refs = set()
|
|
90
90
|
self._rewrote_qualified = False
|
|
91
91
|
self._local_bindings = LocalBindings()
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
for imp in stmt.names:
|
|
98
|
-
if get_qualid_name(imp.qualid) == old_name and self._bare_ref is None:
|
|
99
|
-
self._bare_ref = get_alias_name(imp) or old_name
|
|
100
|
-
else:
|
|
101
|
-
for imp in stmt.names:
|
|
102
|
-
if get_qualid_name(imp.qualid) == "typing":
|
|
103
|
-
self._module_refs.add(get_alias_name(imp) or "typing")
|
|
104
|
-
elif isinstance(stmt, Import):
|
|
105
|
-
if get_qualid_name(stmt.qualid) == "typing":
|
|
106
|
-
self._module_refs.add(get_alias_name(stmt) or "typing")
|
|
93
|
+
members, self._module_refs = scan_typing_imports(cu)
|
|
94
|
+
self._bare_ref = next(
|
|
95
|
+
(exposed for exposed, name in members.items() if name == old_name), None
|
|
96
|
+
)
|
|
107
97
|
|
|
108
98
|
if self._bare_ref is None and not self._module_refs:
|
|
109
99
|
return cu
|
|
110
100
|
|
|
111
|
-
# A reference inside a string annotation is a Literal, not an
|
|
112
|
-
# Identifier, so it is neither renamed nor seen by RemoveImport's
|
|
113
|
-
# usage check; keep the import so such references stay resolvable.
|
|
114
|
-
self._keep_from_import = self._bare_ref is not None and self._used_in_string_literal(
|
|
115
|
-
cu, self._bare_ref
|
|
116
|
-
)
|
|
117
|
-
|
|
118
101
|
result = cast(CompilationUnit, super().visit_compilation_unit(cu, p))
|
|
119
102
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
103
|
+
# A string forward reference is neither renamed above nor seen by
|
|
104
|
+
# RemoveImport's usage check; scanning the rewritten tree finds the
|
|
105
|
+
# ones that outlived the rename.
|
|
106
|
+
if self._bare_ref is not None and not self._forward_reference_survives(
|
|
107
|
+
result, self._bare_ref
|
|
108
|
+
):
|
|
109
|
+
maybe_remove_typing_import(self, old_name)
|
|
124
110
|
if self._rewrote_qualified:
|
|
125
111
|
maybe_remove_typing_module_import(self, self._module_refs)
|
|
126
112
|
|
|
127
113
|
return result
|
|
128
114
|
|
|
129
115
|
@staticmethod
|
|
130
|
-
def
|
|
131
|
-
|
|
116
|
+
def _forward_reference_survives(cu: CompilationUnit, name: str) -> bool:
|
|
117
|
+
"""True when a string forward reference still names ``name``.
|
|
118
|
+
|
|
119
|
+
The parser leaves such a reference as text -- a string `Literal`
|
|
120
|
+
annotation, or an `Identifier` marked `Quoted` -- so its contents are
|
|
121
|
+
parsed as an expression. Prose that merely spells the name out, as a
|
|
122
|
+
docstring does, is not an expression and so is not a reference.
|
|
123
|
+
"""
|
|
132
124
|
found = False
|
|
133
125
|
|
|
134
|
-
|
|
126
|
+
def names_target(text: str) -> bool:
|
|
127
|
+
if name not in text:
|
|
128
|
+
return False
|
|
129
|
+
try:
|
|
130
|
+
parsed = ast.parse(text.strip(), mode="eval")
|
|
131
|
+
except (SyntaxError, ValueError):
|
|
132
|
+
return False
|
|
133
|
+
return any(
|
|
134
|
+
isinstance(node, ast.Name) and node.id == name
|
|
135
|
+
for node in ast.walk(parsed)
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
class ForwardReferenceScan(PythonVisitor[Any]):
|
|
135
139
|
def visit_literal(self, literal: Literal, p: Any) -> J:
|
|
136
140
|
nonlocal found
|
|
137
|
-
if not found and isinstance(literal.value, str) and
|
|
141
|
+
if not found and isinstance(literal.value, str) and names_target(literal.value):
|
|
138
142
|
found = True
|
|
139
143
|
return literal
|
|
140
144
|
|
|
141
|
-
|
|
145
|
+
def visit_identifier(self, ident: Identifier, p: Any) -> J:
|
|
146
|
+
nonlocal found
|
|
147
|
+
if (
|
|
148
|
+
not found
|
|
149
|
+
and ident.markers.find_first(Quoted) is not None
|
|
150
|
+
and names_target(ident.simple_name)
|
|
151
|
+
):
|
|
152
|
+
found = True
|
|
153
|
+
return ident
|
|
154
|
+
|
|
155
|
+
ForwardReferenceScan().visit(cu, None)
|
|
142
156
|
return found
|
|
143
157
|
|
|
144
158
|
def visit_field_access(self, field_access: FieldAccess, p: ExecutionContext) -> J:
|
|
@@ -203,7 +217,10 @@ class _ReplaceTypingAliasRecipe(Recipe):
|
|
|
203
217
|
def description(self) -> str:
|
|
204
218
|
return (
|
|
205
219
|
f"PEP 585 deprecated `typing.{self.old_name}` in Python 3.9. "
|
|
206
|
-
f"Replace with the built-in `{self.new_name}` type for generic annotations."
|
|
220
|
+
f"Replace with the built-in `{self.new_name}` type for generic annotations. "
|
|
221
|
+
"Applies inside `if TYPE_CHECKING:` blocks as well; the built-in generic is "
|
|
222
|
+
"valid at runtime from Python 3.9 on, so no `from __future__ import "
|
|
223
|
+
"annotations` is needed."
|
|
207
224
|
)
|
|
208
225
|
|
|
209
226
|
def editor(self) -> TreeVisitor[Any, ExecutionContext]:
|
|
@@ -18,7 +18,6 @@ from rewrite.decorators import categorize
|
|
|
18
18
|
from rewrite.marketplace import Python
|
|
19
19
|
from rewrite.markers import Markers
|
|
20
20
|
from rewrite.python.markers import Quoted
|
|
21
|
-
from rewrite.python.remove_import import RemoveImportOptions, maybe_remove_import
|
|
22
21
|
from rewrite.python.visitor import PythonVisitor
|
|
23
22
|
from rewrite.java.support_types import JRightPadded, Space
|
|
24
23
|
from rewrite.java.tree import (
|
|
@@ -33,7 +32,11 @@ from rewrite.java.tree import (
|
|
|
33
32
|
from rewrite.python.tree import CollectionLiteral, CompilationUnit, UnionType
|
|
34
33
|
from rewrite.utils import random_id
|
|
35
34
|
|
|
36
|
-
from ._typing_imports import
|
|
35
|
+
from ._typing_imports import (
|
|
36
|
+
maybe_remove_typing_import,
|
|
37
|
+
maybe_remove_typing_module_import,
|
|
38
|
+
scan_typing_imports,
|
|
39
|
+
)
|
|
37
40
|
|
|
38
41
|
# Define category path: Python > Migrate > Python 3.10
|
|
39
42
|
_Python310 = [
|
|
@@ -89,7 +92,7 @@ class _PipeSyntaxVisitor(PythonVisitor[ExecutionContext]):
|
|
|
89
92
|
if isinstance(clazz, FieldAccess):
|
|
90
93
|
maybe_remove_typing_module_import(self, self._module_refs)
|
|
91
94
|
else:
|
|
92
|
-
|
|
95
|
+
maybe_remove_typing_import(self, member)
|
|
93
96
|
|
|
94
97
|
|
|
95
98
|
def _create_none_literal(prefix: Space) -> Literal:
|
|
@@ -171,7 +174,10 @@ class ReplaceTypingOptionalWithUnion(Recipe):
|
|
|
171
174
|
def description(self) -> str:
|
|
172
175
|
return (
|
|
173
176
|
"PEP 604 introduced the `|` operator for union types in Python 3.10. "
|
|
174
|
-
"Replace `Optional[X]` with the more concise `X | None` syntax."
|
|
177
|
+
"Replace `Optional[X]` with the more concise `X | None` syntax. "
|
|
178
|
+
"Applies inside `if TYPE_CHECKING:` blocks as well; `X | None` is valid at "
|
|
179
|
+
"runtime from Python 3.10 on, so no `from __future__ import annotations` "
|
|
180
|
+
"is needed."
|
|
175
181
|
)
|
|
176
182
|
|
|
177
183
|
@property
|
|
@@ -258,7 +264,10 @@ class ReplaceTypingUnionWithPipe(Recipe):
|
|
|
258
264
|
def description(self) -> str:
|
|
259
265
|
return (
|
|
260
266
|
"PEP 604 introduced the `|` operator for union types in Python 3.10. "
|
|
261
|
-
"Replace `Union[X, Y, ...]` with the more concise `X | Y | ...` syntax."
|
|
267
|
+
"Replace `Union[X, Y, ...]` with the more concise `X | Y | ...` syntax. "
|
|
268
|
+
"Applies inside `if TYPE_CHECKING:` blocks as well; `X | Y` is valid at "
|
|
269
|
+
"runtime from Python 3.10 on, so no `from __future__ import annotations` "
|
|
270
|
+
"is needed."
|
|
262
271
|
)
|
|
263
272
|
|
|
264
273
|
@property
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openrewrite-migrate-python
|
|
3
|
-
Version: 0.14.0.
|
|
3
|
+
Version: 0.14.0.dev20260901153140
|
|
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
|
|
@@ -430,6 +430,66 @@ class TestPep585CornerCases:
|
|
|
430
430
|
)
|
|
431
431
|
)
|
|
432
432
|
|
|
433
|
+
def test_removes_import_when_only_a_docstring_mentions_the_name(self):
|
|
434
|
+
"""Prose that happens to spell the name is not a reference to it."""
|
|
435
|
+
spec = RecipeSpec(recipe=ReplaceTypingListWithList())
|
|
436
|
+
spec.rewrite_run(
|
|
437
|
+
python(
|
|
438
|
+
"""
|
|
439
|
+
from typing import List
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
def f(items):
|
|
443
|
+
'Return a List of things.'
|
|
444
|
+
return items
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
x: List[int] = []
|
|
448
|
+
""",
|
|
449
|
+
"""
|
|
450
|
+
def f(items):
|
|
451
|
+
'Return a List of things.'
|
|
452
|
+
return items
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
x: list[int] = []
|
|
456
|
+
""",
|
|
457
|
+
)
|
|
458
|
+
)
|
|
459
|
+
|
|
460
|
+
def test_keeps_import_used_by_quoted_annotation(self):
|
|
461
|
+
"""A quoted annotation the rename leaves alone still needs the import."""
|
|
462
|
+
spec = RecipeSpec(recipe=ReplaceTypingListWithList())
|
|
463
|
+
spec.rewrite_run(
|
|
464
|
+
python(
|
|
465
|
+
"""
|
|
466
|
+
from typing import List
|
|
467
|
+
x: List[int] = []
|
|
468
|
+
y: "List[int]" = []
|
|
469
|
+
""",
|
|
470
|
+
"""
|
|
471
|
+
from typing import List
|
|
472
|
+
x: list[int] = []
|
|
473
|
+
y: "List[int]" = []
|
|
474
|
+
""",
|
|
475
|
+
)
|
|
476
|
+
)
|
|
477
|
+
|
|
478
|
+
def test_removes_import_when_the_quoted_annotation_is_renamed(self):
|
|
479
|
+
"""The rename reaches inside a bare quoted annotation, freeing the import."""
|
|
480
|
+
spec = RecipeSpec(recipe=ReplaceTypingListWithList())
|
|
481
|
+
spec.rewrite_run(
|
|
482
|
+
python(
|
|
483
|
+
"""
|
|
484
|
+
from typing import List
|
|
485
|
+
x: "List" = []
|
|
486
|
+
""",
|
|
487
|
+
"""
|
|
488
|
+
x: "list" = []
|
|
489
|
+
""",
|
|
490
|
+
)
|
|
491
|
+
)
|
|
492
|
+
|
|
433
493
|
def test_does_not_rename_keyword_argument(self):
|
|
434
494
|
"""A keyword argument named `List` binds a parameter, not the import."""
|
|
435
495
|
spec = RecipeSpec(recipe=ReplaceTypingListWithList())
|
|
@@ -521,3 +581,194 @@ class TestReplaceTypingText:
|
|
|
521
581
|
"""
|
|
522
582
|
)
|
|
523
583
|
)
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
class TestTypeCheckingBlocks:
|
|
587
|
+
"""Typing imports nested in an `if TYPE_CHECKING:` block."""
|
|
588
|
+
|
|
589
|
+
def test_rewrites_and_drops_emptied_block(self):
|
|
590
|
+
spec = RecipeSpec(recipe=ReplaceTypingListWithList())
|
|
591
|
+
spec.rewrite_run(
|
|
592
|
+
python(
|
|
593
|
+
"""
|
|
594
|
+
from __future__ import annotations
|
|
595
|
+
from typing import TYPE_CHECKING
|
|
596
|
+
|
|
597
|
+
if TYPE_CHECKING:
|
|
598
|
+
from typing import List
|
|
599
|
+
|
|
600
|
+
def f(x: List[int]) -> None: ...
|
|
601
|
+
""",
|
|
602
|
+
"""
|
|
603
|
+
from __future__ import annotations
|
|
604
|
+
from typing import TYPE_CHECKING
|
|
605
|
+
|
|
606
|
+
def f(x: list[int]) -> None: ...
|
|
607
|
+
""",
|
|
608
|
+
)
|
|
609
|
+
)
|
|
610
|
+
|
|
611
|
+
def test_keeps_block_holding_other_imports(self):
|
|
612
|
+
spec = RecipeSpec(recipe=ReplaceTypingListWithList())
|
|
613
|
+
spec.rewrite_run(
|
|
614
|
+
python(
|
|
615
|
+
"""
|
|
616
|
+
from typing import TYPE_CHECKING
|
|
617
|
+
|
|
618
|
+
if TYPE_CHECKING:
|
|
619
|
+
from typing import List, Optional
|
|
620
|
+
|
|
621
|
+
def f(x: List[int], y: Optional[str]) -> None: ...
|
|
622
|
+
""",
|
|
623
|
+
"""
|
|
624
|
+
from typing import TYPE_CHECKING
|
|
625
|
+
|
|
626
|
+
if TYPE_CHECKING:
|
|
627
|
+
from typing import Optional
|
|
628
|
+
|
|
629
|
+
def f(x: list[int], y: Optional[str]) -> None: ...
|
|
630
|
+
""",
|
|
631
|
+
)
|
|
632
|
+
)
|
|
633
|
+
|
|
634
|
+
def test_rewrites_qualified_reference(self):
|
|
635
|
+
spec = RecipeSpec(recipe=ReplaceTypingListWithList())
|
|
636
|
+
spec.rewrite_run(
|
|
637
|
+
python(
|
|
638
|
+
"""
|
|
639
|
+
from typing import TYPE_CHECKING
|
|
640
|
+
|
|
641
|
+
if TYPE_CHECKING:
|
|
642
|
+
import typing
|
|
643
|
+
|
|
644
|
+
def f(x: typing.List[int]) -> None: ...
|
|
645
|
+
""",
|
|
646
|
+
"""
|
|
647
|
+
from typing import TYPE_CHECKING
|
|
648
|
+
|
|
649
|
+
def f(x: list[int]) -> None: ...
|
|
650
|
+
""",
|
|
651
|
+
)
|
|
652
|
+
)
|
|
653
|
+
|
|
654
|
+
def test_ignores_a_block_whose_else_binds_the_name(self):
|
|
655
|
+
"""Renaming the `else` binding too would rebind the builtin."""
|
|
656
|
+
spec = RecipeSpec(recipe=ReplaceTypingListWithList())
|
|
657
|
+
spec.rewrite_run(
|
|
658
|
+
python(
|
|
659
|
+
"""
|
|
660
|
+
from typing import TYPE_CHECKING
|
|
661
|
+
import collections
|
|
662
|
+
|
|
663
|
+
if TYPE_CHECKING:
|
|
664
|
+
from typing import List
|
|
665
|
+
else:
|
|
666
|
+
List = collections.UserList
|
|
667
|
+
|
|
668
|
+
def f(x: List[int]) -> None: ...
|
|
669
|
+
"""
|
|
670
|
+
)
|
|
671
|
+
)
|
|
672
|
+
|
|
673
|
+
def test_keeps_a_comment_on_the_statement_after_a_removed_import(self):
|
|
674
|
+
spec = RecipeSpec(recipe=ReplaceTypingListWithList())
|
|
675
|
+
spec.rewrite_run(
|
|
676
|
+
python(
|
|
677
|
+
"""
|
|
678
|
+
from typing import TYPE_CHECKING
|
|
679
|
+
|
|
680
|
+
if TYPE_CHECKING:
|
|
681
|
+
from typing import List
|
|
682
|
+
# needed for annotations
|
|
683
|
+
from typing import Dict
|
|
684
|
+
|
|
685
|
+
def f(x: List[int], y: Dict[str, int]) -> None: ...
|
|
686
|
+
""",
|
|
687
|
+
"""
|
|
688
|
+
from typing import TYPE_CHECKING
|
|
689
|
+
|
|
690
|
+
if TYPE_CHECKING:
|
|
691
|
+
# needed for annotations
|
|
692
|
+
from typing import Dict
|
|
693
|
+
|
|
694
|
+
def f(x: list[int], y: Dict[str, int]) -> None: ...
|
|
695
|
+
""",
|
|
696
|
+
)
|
|
697
|
+
)
|
|
698
|
+
|
|
699
|
+
def test_keeps_import_whose_comment_would_be_lost(self):
|
|
700
|
+
"""No prefix can hold the comment once the import it leads is gone."""
|
|
701
|
+
RecipeSpec(recipe=ReplaceTypingListWithList()).rewrite_run(
|
|
702
|
+
python(
|
|
703
|
+
"""
|
|
704
|
+
from typing import TYPE_CHECKING
|
|
705
|
+
|
|
706
|
+
if TYPE_CHECKING:
|
|
707
|
+
# only needed for annotations
|
|
708
|
+
from typing import List
|
|
709
|
+
|
|
710
|
+
def f(x: List[int]) -> None: ...
|
|
711
|
+
""",
|
|
712
|
+
"""
|
|
713
|
+
from typing import TYPE_CHECKING
|
|
714
|
+
|
|
715
|
+
if TYPE_CHECKING:
|
|
716
|
+
# only needed for annotations
|
|
717
|
+
from typing import List
|
|
718
|
+
|
|
719
|
+
def f(x: list[int]) -> None: ...
|
|
720
|
+
""",
|
|
721
|
+
)
|
|
722
|
+
)
|
|
723
|
+
|
|
724
|
+
RecipeSpec(recipe=ReplaceTypingListWithList()).rewrite_run(
|
|
725
|
+
python(
|
|
726
|
+
"""
|
|
727
|
+
from typing import TYPE_CHECKING
|
|
728
|
+
|
|
729
|
+
if TYPE_CHECKING:
|
|
730
|
+
from collections.abc import Sequence
|
|
731
|
+
# only needed for annotations
|
|
732
|
+
from typing import List
|
|
733
|
+
|
|
734
|
+
def f(x: List[int], y: Sequence[int]) -> None: ...
|
|
735
|
+
""",
|
|
736
|
+
"""
|
|
737
|
+
from typing import TYPE_CHECKING
|
|
738
|
+
|
|
739
|
+
if TYPE_CHECKING:
|
|
740
|
+
from collections.abc import Sequence
|
|
741
|
+
# only needed for annotations
|
|
742
|
+
from typing import List
|
|
743
|
+
|
|
744
|
+
def f(x: list[int], y: Sequence[int]) -> None: ...
|
|
745
|
+
""",
|
|
746
|
+
)
|
|
747
|
+
)
|
|
748
|
+
|
|
749
|
+
RecipeSpec(recipe=ReplaceTypingListWithList()).rewrite_run(
|
|
750
|
+
python(
|
|
751
|
+
"""
|
|
752
|
+
from typing import TYPE_CHECKING
|
|
753
|
+
|
|
754
|
+
if TYPE_CHECKING:
|
|
755
|
+
# comment A
|
|
756
|
+
from typing import List
|
|
757
|
+
# comment B
|
|
758
|
+
from typing import Dict
|
|
759
|
+
|
|
760
|
+
def f(x: List[int], y: Dict[str, int]) -> None: ...
|
|
761
|
+
""",
|
|
762
|
+
"""
|
|
763
|
+
from typing import TYPE_CHECKING
|
|
764
|
+
|
|
765
|
+
if TYPE_CHECKING:
|
|
766
|
+
# comment A
|
|
767
|
+
from typing import List
|
|
768
|
+
# comment B
|
|
769
|
+
from typing import Dict
|
|
770
|
+
|
|
771
|
+
def f(x: list[int], y: Dict[str, int]) -> None: ...
|
|
772
|
+
""",
|
|
773
|
+
)
|
|
774
|
+
)
|
|
@@ -340,3 +340,29 @@ class TestReplaceTypingUnionWithPipe:
|
|
|
340
340
|
""",
|
|
341
341
|
)
|
|
342
342
|
)
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
class TestTypeCheckingBlocks:
|
|
346
|
+
"""Typing imports nested in an `if TYPE_CHECKING:` block."""
|
|
347
|
+
|
|
348
|
+
def test_rewrites_optional_and_drops_emptied_block(self):
|
|
349
|
+
spec = RecipeSpec(recipe=ReplaceTypingOptionalWithUnion())
|
|
350
|
+
spec.rewrite_run(
|
|
351
|
+
python(
|
|
352
|
+
"""
|
|
353
|
+
from __future__ import annotations
|
|
354
|
+
from typing import TYPE_CHECKING
|
|
355
|
+
|
|
356
|
+
if TYPE_CHECKING:
|
|
357
|
+
from typing import Optional
|
|
358
|
+
|
|
359
|
+
def f(y: Optional[str]) -> None: ...
|
|
360
|
+
""",
|
|
361
|
+
"""
|
|
362
|
+
from __future__ import annotations
|
|
363
|
+
from typing import TYPE_CHECKING
|
|
364
|
+
|
|
365
|
+
def f(y: str | None) -> None: ...
|
|
366
|
+
""",
|
|
367
|
+
)
|
|
368
|
+
)
|