openrewrite-migrate-python 0.14.0.dev20260903170551__tar.gz → 0.14.0.dev20260904122505__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.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/PKG-INFO +2 -2
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/pyproject.toml +2 -6
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_code_quality_python/codequality/_reindent.py +0 -16
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_code_quality_python/codequality/all_branches_identical.py +2 -3
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_code_quality_python/codequality/collapsible_if_statements.py +2 -4
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/_from_imports.py +17 -6
- openrewrite_migrate_python-0.14.0.dev20260904122505/src/openrewrite_migrate_python/migrate/_slots.py +14 -0
- openrewrite_migrate_python-0.14.0.dev20260904122505/src/openrewrite_migrate_python/migrate/_typing_imports.py +71 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/asyncio_coroutine_to_async.py +37 -25
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/gettext_deprecations.py +2 -2
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/locale_deprecations.py +3 -1
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/platform_deprecations.py +1 -1
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/ssl_deprecations.py +1 -1
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/string_formatting.py +4 -2
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/typing_deprecations.py +1 -52
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python.egg-info/PKG-INFO +2 -2
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python.egg-info/SOURCES.txt +1 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python.egg-info/requires.txt +1 -1
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_asyncio_coroutine_to_async.py +52 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_gettext_deprecations.py +16 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_locale_deprecations.py +44 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_string_formatting.py +20 -0
- openrewrite_migrate_python-0.14.0.dev20260903170551/src/openrewrite_migrate_python/migrate/_typing_imports.py +0 -164
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/setup.cfg +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_code_quality_python/__init__.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_code_quality_python/codequality/__init__.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_code_quality_python/codequality/_semantically_equal.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_code_quality_python/codequality/_trivia.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_code_quality_python/codequality/boolean_checks_not_inverted.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_code_quality_python/codequality/find_suspicious_chained_comparison.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_code_quality_python/codequality/merge_identical_branches.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_code_quality_python/codequality/remove_duplicate_conditions.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_code_quality_python/codequality/remove_self_assignment.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_code_quality_python/codequality/remove_unconditional_value_overwrite.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_code_quality_python/codequality/simplify_boolean_literal.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_code_quality_python/codequality/simplify_redundant_logical_expression.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/__init__.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/__init__.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/_import_hygiene.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/_langchain_tables.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/_markers.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/aifc_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/array_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/ast_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/asyncio_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/avro_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/calendar_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/cgi_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/cgi_parse_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/collections_abc_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/configparser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/datetime_utc.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/distutils_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/distutils_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/functools_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/future_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/html_parser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/imp_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/langchain_classic_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/langchain_community_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/langchain_provider_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/locale_getdefaultlocale_deprecation.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/macpath_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/mailcap_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/nntplib_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/os_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/pathlib_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/pep594_system_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/pipes_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/pkgutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/pydantic_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/pydantic_fields.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/pydantic_model_fields.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/re_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/removed_modules_312.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/shutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/socket_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/sys_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/sys_last_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/tarfile_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/telnetlib_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/tempfile_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/threading_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/threading_is_alive_deprecation.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/typing_callable.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/typing_union_to_pipe.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/unittest_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/upgrade_to_langchain02.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/upgrade_to_langchain1.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/upgrade_to_pydantic.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/upgrade_to_python310.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/upgrade_to_python311.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/upgrade_to_python312.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/upgrade_to_python313.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/upgrade_to_python314.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/upgrade_to_python38.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/upgrade_to_python39.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/urllib_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/uu_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/xdrlib_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python/migrate/xml_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python.egg-info/dependency_links.txt +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python.egg-info/entry_points.txt +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/src/openrewrite_migrate_python.egg-info/top_level.txt +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_aifc_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_array_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_ast_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_asyncio_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_avro_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_calendar_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_cgi_parse_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_change_import_recipes.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_collections_abc_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_configparser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_datetime_utc.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_distutils_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_future_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_html_parser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_imp_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_langchain_classic_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_langchain_community_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_langchain_provider_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_locale_getdefaultlocale_deprecation.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_macpath_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_os_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_pep594_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_pep594_system_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_pkgutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_platform_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_pydantic_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_pydantic_fields.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_pydantic_model_fields.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_re_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_removed_modules_312.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_shutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_ssl_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_sys_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_sys_last_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_tarfile_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_threading_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_threading_extended.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_threading_is_alive_deprecation.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_typing_alias_moves.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_typing_callable.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_typing_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_typing_union_to_pipe.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_unittest_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_upgrade_recipes.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/tests/test_upgrade_to_pydantic.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260903170551 → openrewrite_migrate_python-0.14.0.dev20260904122505}/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.dev20260904122505
|
|
4
4
|
Summary: OpenRewrite recipes for migrating Python codebases to newer Python versions.
|
|
5
5
|
Author-email: "Moderne Inc." <support@moderne.io>
|
|
6
6
|
License: Moderne Proprietary
|
|
@@ -21,7 +21,7 @@ Classifier: Typing :: Typed
|
|
|
21
21
|
Requires-Python: >=3.10
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
23
23
|
Provides-Extra: dev
|
|
24
|
-
Requires-Dist: openrewrite>=8.91.
|
|
24
|
+
Requires-Dist: openrewrite>=8.91.5; extra == "dev"
|
|
25
25
|
Requires-Dist: pydantic>=2.11; extra == "dev"
|
|
26
26
|
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
27
27
|
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "openrewrite-migrate-python"
|
|
7
7
|
description = "OpenRewrite recipes for migrating Python codebases to newer Python versions."
|
|
8
|
-
version = "0.14.0.
|
|
8
|
+
version = "0.14.0.dev20260904122505" # Updated dynamically during release
|
|
9
9
|
authors = [{ name = "Moderne Inc.", email = "support@moderne.io" }]
|
|
10
10
|
license = { text = "Moderne Proprietary" }
|
|
11
11
|
readme = "README.md"
|
|
@@ -30,11 +30,7 @@ dependencies = []
|
|
|
30
30
|
|
|
31
31
|
[project.optional-dependencies]
|
|
32
32
|
dev = [
|
|
33
|
-
|
|
34
|
-
# against: the current release, so that recipes meet the LST a current CLI produces.
|
|
35
|
-
# 8.91.4 is the first with `Py.Shebang` (openrewrite/rewrite#8729), which a shebanged
|
|
36
|
-
# file puts at `statements[0]` ahead of its imports.
|
|
37
|
-
"openrewrite>=8.91.4",
|
|
33
|
+
"openrewrite>=8.91.5",
|
|
38
34
|
# Needed so type-attribution tests can resolve `pydantic` types.
|
|
39
35
|
"pydantic>=2.11",
|
|
40
36
|
"pytest>=8.0.0",
|
|
@@ -7,8 +7,6 @@ to a shallower nesting level means rewriting every line it spans.
|
|
|
7
7
|
from typing import Optional, TypeVar
|
|
8
8
|
|
|
9
9
|
from rewrite.java.support_types import Space
|
|
10
|
-
from rewrite.java.tree import Statement
|
|
11
|
-
from rewrite.python.tree import ExpressionStatement, StatementExpression
|
|
12
10
|
from rewrite.python.visitor import PythonVisitor
|
|
13
11
|
|
|
14
12
|
T = TypeVar("T")
|
|
@@ -27,20 +25,6 @@ def inherited_prefix(dropped: Space, body: Space) -> Space:
|
|
|
27
25
|
)
|
|
28
26
|
|
|
29
27
|
|
|
30
|
-
def with_prefix(stmt: Statement, prefix: Space) -> Statement:
|
|
31
|
-
"""Set the prefix of *stmt*, threading through the ``Py`` wrappers whose
|
|
32
|
-
own prefix is a read-only view of the node they hold.
|
|
33
|
-
|
|
34
|
-
Drop once openrewrite/rewrite#8742 is the version floor: it gives those
|
|
35
|
-
wrappers a write path, so `stmt.replace(_prefix=...)` suffices alone.
|
|
36
|
-
"""
|
|
37
|
-
if isinstance(stmt, ExpressionStatement):
|
|
38
|
-
return stmt.replace(_expression=with_prefix(stmt.expression, prefix))
|
|
39
|
-
if isinstance(stmt, StatementExpression):
|
|
40
|
-
return stmt.replace(_statement=with_prefix(stmt.statement, prefix))
|
|
41
|
-
return stmt.replace(_prefix=prefix)
|
|
42
|
-
|
|
43
|
-
|
|
44
28
|
def line_indent(space: Space) -> Optional[str]:
|
|
45
29
|
"""Indentation of the line the token following *space* starts on, or
|
|
46
30
|
``None`` when that token shares a line with what precedes it.
|
|
@@ -25,7 +25,6 @@ from openrewrite_code_quality_python.codequality._reindent import (
|
|
|
25
25
|
inherited_prefix,
|
|
26
26
|
line_indent,
|
|
27
27
|
reindent,
|
|
28
|
-
with_prefix,
|
|
29
28
|
)
|
|
30
29
|
from openrewrite_code_quality_python.codequality._semantically_equal import SemanticallyEqual
|
|
31
30
|
|
|
@@ -193,8 +192,8 @@ def _replace_identical_ifs_padded(padded_stmts) -> Optional[list]:
|
|
|
193
192
|
# separating it from the next one is recorded.
|
|
194
193
|
result.append(
|
|
195
194
|
first.replace(
|
|
196
|
-
_element=
|
|
197
|
-
|
|
195
|
+
_element=first.element.replace(
|
|
196
|
+
_prefix=inherited_prefix(s.prefix, first.element.prefix)
|
|
198
197
|
)
|
|
199
198
|
)
|
|
200
199
|
)
|
|
@@ -36,7 +36,6 @@ from openrewrite_code_quality_python.codequality._reindent import (
|
|
|
36
36
|
inherited_prefix,
|
|
37
37
|
line_indent,
|
|
38
38
|
reindent,
|
|
39
|
-
with_prefix,
|
|
40
39
|
)
|
|
41
40
|
|
|
42
41
|
_CodeQuality = [
|
|
@@ -198,9 +197,8 @@ class CollapsibleIfStatements(Recipe):
|
|
|
198
197
|
inner_body = inner_body.replace(
|
|
199
198
|
_statements=[
|
|
200
199
|
first.replace(
|
|
201
|
-
_element=
|
|
202
|
-
first.element
|
|
203
|
-
inherited_prefix(inner.prefix, first.element.prefix),
|
|
200
|
+
_element=first.element.replace(
|
|
201
|
+
_prefix=inherited_prefix(inner.prefix, first.element.prefix)
|
|
204
202
|
)
|
|
205
203
|
),
|
|
206
204
|
*inner_body._statements[1:],
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""Resolving a receiver-less call to the module member it was imported from."""
|
|
2
2
|
|
|
3
|
-
from typing import Dict, Optional
|
|
3
|
+
from typing import Dict, Optional, Set
|
|
4
4
|
|
|
5
5
|
from rewrite import Cursor
|
|
6
6
|
from rewrite.java.tree import FieldAccess, Identifier, J, MethodInvocation
|
|
7
|
+
from rewrite.python import scope_of
|
|
7
8
|
from rewrite.python.import_utils import get_alias_name, get_name_string, get_qualid_name
|
|
8
9
|
from rewrite.python.scope_utils import LocalBindings
|
|
9
10
|
from rewrite.python.tree import CompilationUnit, MultiImport
|
|
@@ -19,18 +20,17 @@ def _is_relative(from_: J) -> bool:
|
|
|
19
20
|
class FromImports:
|
|
20
21
|
"""The members of ``module`` a file binds with ``from <module> import <member>``.
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
these APIs span many versions, so no declared version resolves them all —
|
|
25
|
-
attribution quality does not make this fallback redundant.
|
|
23
|
+
A call spells the name its import bound, which an alias makes differ from the
|
|
24
|
+
member the type gates match on.
|
|
26
25
|
"""
|
|
27
26
|
|
|
28
27
|
def __init__(self, module: str) -> None:
|
|
29
28
|
self._module = module
|
|
30
29
|
self._members: Dict[str, str] = {}
|
|
30
|
+
self._bound: Set[str] = set()
|
|
31
31
|
self._locals = LocalBindings()
|
|
32
32
|
|
|
33
|
-
def scan(self, cu: CompilationUnit) -> None:
|
|
33
|
+
def scan(self, cu: CompilationUnit, cursor: Cursor) -> None:
|
|
34
34
|
"""Record the file's bindings; call from ``visit_compilation_unit``.
|
|
35
35
|
|
|
36
36
|
Top-level ``from`` statements only, since a guarded import's fallback may
|
|
@@ -48,6 +48,17 @@ class FromImports:
|
|
|
48
48
|
for imp in stmt.names:
|
|
49
49
|
name = get_qualid_name(imp.qualid)
|
|
50
50
|
self._members.setdefault(get_alias_name(imp) or name, name)
|
|
51
|
+
# A member this module already binds is one `maybe_add_import` reconciles.
|
|
52
|
+
self._bound = scope_of(cursor).names() - set(self._members)
|
|
53
|
+
|
|
54
|
+
def binds(self, name: str) -> bool:
|
|
55
|
+
"""Whether the module scope binds ``name`` outside this module's imports.
|
|
56
|
+
|
|
57
|
+
A replacement spelled unqualified resolves to the nearest module-scope
|
|
58
|
+
binding, so emitting one where something else holds the name redirects
|
|
59
|
+
the call rather than migrating it.
|
|
60
|
+
"""
|
|
61
|
+
return name in self._bound
|
|
51
62
|
|
|
52
63
|
def member_called(self, method: MethodInvocation, cursor: Cursor) -> Optional[str]:
|
|
53
64
|
"""The ``module`` member a receiver-less ``method`` calls, if it calls one."""
|
openrewrite_migrate_python-0.14.0.dev20260904122505/src/openrewrite_migrate_python/migrate/_slots.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Keeping a replacement node in the slot kind its original occupied."""
|
|
2
|
+
|
|
3
|
+
from rewrite import Cursor
|
|
4
|
+
from rewrite.java.tree import Block, Expression, J
|
|
5
|
+
from rewrite.python.tree import CompilationUnit, ExpressionStatement
|
|
6
|
+
from rewrite.utils import random_id
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def as_slot_of(cursor: Cursor, expression: Expression) -> J:
|
|
10
|
+
"""Wrap ``expression`` as an ``ExpressionStatement`` when the tree at
|
|
11
|
+
``cursor`` is its own statement, so the replacement stays a Statement."""
|
|
12
|
+
if isinstance(cursor.parent_tree_cursor().value, (Block, CompilationUnit)):
|
|
13
|
+
return ExpressionStatement(random_id(), expression)
|
|
14
|
+
return expression
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""Internal helpers for locating references to the typing module in a file."""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Iterator, Optional, Sequence, Set, Tuple
|
|
4
|
+
|
|
5
|
+
from rewrite.java.support_types import Statement
|
|
6
|
+
from rewrite.java.tree import If, Import
|
|
7
|
+
from rewrite.python.import_utils import get_alias_name, get_name_string, get_qualid_name
|
|
8
|
+
from rewrite.python.remove_import import (
|
|
9
|
+
RemoveImportOptions,
|
|
10
|
+
maybe_remove_import,
|
|
11
|
+
unconditional_body,
|
|
12
|
+
)
|
|
13
|
+
from rewrite.python.tree import CompilationUnit, MultiImport
|
|
14
|
+
from rewrite.python.visitor import PythonVisitor
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _module_scope_statements(statements: Sequence[Statement]) -> Iterator[Statement]:
|
|
18
|
+
"""Every statement binding names in the module scope, `if` bodies included.
|
|
19
|
+
|
|
20
|
+
`if TYPE_CHECKING:` is where files that defer their annotations keep their
|
|
21
|
+
typing imports.
|
|
22
|
+
"""
|
|
23
|
+
for stmt in statements:
|
|
24
|
+
yield stmt
|
|
25
|
+
body = unconditional_body(stmt) if isinstance(stmt, If) else None
|
|
26
|
+
if body is not None:
|
|
27
|
+
yield from _module_scope_statements(body.statements)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def scan_typing_imports(cu: CompilationUnit) -> Tuple[Dict[str, str], Set[str]]:
|
|
31
|
+
"""Map how this file can reference typing members.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
A tuple of:
|
|
35
|
+
- exposed name -> typing member, for ``from typing import member [as alias]``
|
|
36
|
+
- the set of names bound to the typing module itself, for
|
|
37
|
+
``import typing [as alias]``
|
|
38
|
+
"""
|
|
39
|
+
members: Dict[str, str] = {}
|
|
40
|
+
module_refs: Set[str] = set()
|
|
41
|
+
for stmt in _module_scope_statements(cu.statements):
|
|
42
|
+
if isinstance(stmt, MultiImport):
|
|
43
|
+
if stmt.from_ is not None:
|
|
44
|
+
if get_name_string(stmt.from_) == "typing":
|
|
45
|
+
for imp in stmt.names:
|
|
46
|
+
name = get_qualid_name(imp.qualid)
|
|
47
|
+
members.setdefault(get_alias_name(imp) or name, name)
|
|
48
|
+
else:
|
|
49
|
+
for imp in stmt.names:
|
|
50
|
+
if get_qualid_name(imp.qualid) == "typing":
|
|
51
|
+
module_refs.add(get_alias_name(imp) or "typing")
|
|
52
|
+
elif isinstance(stmt, Import):
|
|
53
|
+
if get_qualid_name(stmt.qualid) == "typing":
|
|
54
|
+
module_refs.add(get_alias_name(stmt) or "typing")
|
|
55
|
+
return members, module_refs
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def maybe_remove_typing_import(visitor: PythonVisitor, name: Optional[str] = None) -> None:
|
|
59
|
+
"""Schedule removal of a typing import once it is no longer used."""
|
|
60
|
+
maybe_remove_import(visitor, RemoveImportOptions(module="typing", name=name))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def maybe_remove_typing_module_import(visitor: PythonVisitor, module_refs: Set[str]) -> None:
|
|
64
|
+
"""Schedule removal of `import typing` once it is no longer used.
|
|
65
|
+
|
|
66
|
+
RemoveImport's usage check counts `typing` identifiers, which an aliased
|
|
67
|
+
module import doesn't produce — removal is only scheduled when an
|
|
68
|
+
unaliased `import typing` exists.
|
|
69
|
+
"""
|
|
70
|
+
if "typing" in module_refs:
|
|
71
|
+
maybe_remove_typing_import(visitor)
|
|
@@ -27,11 +27,13 @@ from rewrite.marketplace import Python
|
|
|
27
27
|
from rewrite.python.preconditions import uses_import
|
|
28
28
|
from rewrite.markers import Markers
|
|
29
29
|
from rewrite.python.visitor import PythonVisitor
|
|
30
|
-
from rewrite.python.tree import Await, YieldFrom
|
|
30
|
+
from rewrite.python.tree import Await, StatementExpression, YieldFrom
|
|
31
31
|
from rewrite.java.tree import (
|
|
32
32
|
Annotation,
|
|
33
33
|
FieldAccess,
|
|
34
34
|
Identifier,
|
|
35
|
+
J,
|
|
36
|
+
Lambda,
|
|
35
37
|
MethodDeclaration,
|
|
36
38
|
Modifier,
|
|
37
39
|
Space,
|
|
@@ -39,6 +41,8 @@ from rewrite.java.tree import (
|
|
|
39
41
|
)
|
|
40
42
|
from rewrite.utils import random_id
|
|
41
43
|
|
|
44
|
+
from ._slots import as_slot_of
|
|
45
|
+
|
|
42
46
|
# Define category path: Python > Migrate > Python 3.11
|
|
43
47
|
_Python311 = [
|
|
44
48
|
*Python,
|
|
@@ -127,33 +131,41 @@ def _add_async_modifier(method: MethodDeclaration, has_remaining_decorators: boo
|
|
|
127
131
|
|
|
128
132
|
|
|
129
133
|
class _YieldFromToAwaitVisitor(PythonVisitor[ExecutionContext]):
|
|
130
|
-
"""
|
|
131
|
-
|
|
132
|
-
In Python's AST, 'yield from expr' is represented as:
|
|
133
|
-
J.Yield(value=Py.YieldFrom(expression=expr))
|
|
134
|
+
"""Replaces ``yield from expr`` with ``await expr``.
|
|
134
135
|
|
|
135
|
-
|
|
136
|
+
The parser represents ``yield from expr`` as
|
|
137
|
+
``StatementExpression(Yield(YieldFrom(expr)))`` whether it is used as an
|
|
138
|
+
expression or as its own statement, so the wrapper is the node to replace.
|
|
136
139
|
"""
|
|
137
140
|
|
|
138
|
-
def
|
|
139
|
-
self,
|
|
140
|
-
) -> Optional[
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
141
|
+
def visit_statement_expression(
|
|
142
|
+
self, stmt_expr: StatementExpression, p: ExecutionContext
|
|
143
|
+
) -> Optional[J]:
|
|
144
|
+
stmt_expr = super().visit_statement_expression(stmt_expr, p)
|
|
145
|
+
if not isinstance(stmt_expr, StatementExpression):
|
|
146
|
+
return stmt_expr
|
|
147
|
+
|
|
148
|
+
yield_stmt = stmt_expr.statement
|
|
149
|
+
if not isinstance(yield_stmt, Yield) or not isinstance(yield_stmt.value, YieldFrom):
|
|
150
|
+
return stmt_expr
|
|
151
|
+
|
|
152
|
+
yield_from = yield_stmt.value
|
|
153
|
+
await_ = Await(
|
|
154
|
+
_id=random_id(),
|
|
155
|
+
_prefix=yield_stmt.prefix,
|
|
156
|
+
_markers=yield_stmt.markers,
|
|
157
|
+
_expression=yield_from.expression,
|
|
158
|
+
_type=yield_from.type,
|
|
159
|
+
)
|
|
160
|
+
return as_slot_of(self.cursor, await_)
|
|
161
|
+
|
|
162
|
+
# Started on the migrated function's body block, so any def or lambda met
|
|
163
|
+
# here is a nested function whose ``yield from`` must stay.
|
|
164
|
+
def visit_method_declaration(self, method: MethodDeclaration, p: ExecutionContext) -> J:
|
|
165
|
+
return method
|
|
166
|
+
|
|
167
|
+
def visit_lambda(self, lambda_: Lambda, p: ExecutionContext) -> J:
|
|
168
|
+
return lambda_
|
|
157
169
|
|
|
158
170
|
|
|
159
171
|
@categorize(_Python311)
|
|
@@ -115,7 +115,7 @@ class ReplaceGettextDeprecations(Recipe):
|
|
|
115
115
|
self._imports = FromImports("gettext")
|
|
116
116
|
|
|
117
117
|
def visit_compilation_unit(self, cu: CompilationUnit, p: ExecutionContext) -> J:
|
|
118
|
-
self._imports.scan(cu)
|
|
118
|
+
self._imports.scan(cu, self.cursor)
|
|
119
119
|
return super().visit_compilation_unit(cu, p)
|
|
120
120
|
|
|
121
121
|
def visit_method_invocation(
|
|
@@ -139,7 +139,7 @@ class ReplaceGettextDeprecations(Recipe):
|
|
|
139
139
|
# the import moves to the replacement along with the call.
|
|
140
140
|
member = self._imports.member_called(method, self.cursor)
|
|
141
141
|
new_name = GETTEXT_DEPRECATIONS.get(member) if member else None
|
|
142
|
-
if new_name is None:
|
|
142
|
+
if new_name is None or self._imports.binds(new_name):
|
|
143
143
|
return method
|
|
144
144
|
maybe_add_import(self, AddImportOptions(module="gettext", name=new_name))
|
|
145
145
|
maybe_remove_import(self, RemoveImportOptions(module="gettext", name=member))
|
|
@@ -153,7 +153,7 @@ class ReplaceLocaleResetlocale(Recipe):
|
|
|
153
153
|
self._imports = FromImports("locale")
|
|
154
154
|
|
|
155
155
|
def visit_compilation_unit(self, cu: CompilationUnit, p: ExecutionContext) -> J:
|
|
156
|
-
self._imports.scan(cu)
|
|
156
|
+
self._imports.scan(cu, self.cursor)
|
|
157
157
|
return super().visit_compilation_unit(cu, p)
|
|
158
158
|
|
|
159
159
|
def visit_method_invocation(
|
|
@@ -175,6 +175,8 @@ class ReplaceLocaleResetlocale(Recipe):
|
|
|
175
175
|
if self._imports.member_called(method, self.cursor) == "resetlocale":
|
|
176
176
|
# `setlocale` and `LC_ALL` are spelled unqualified, so each
|
|
177
177
|
# needs an import of its own.
|
|
178
|
+
if any(self._imports.binds(n) for n in ("setlocale", "LC_ALL")):
|
|
179
|
+
return method
|
|
178
180
|
for name in ("setlocale", "LC_ALL"):
|
|
179
181
|
maybe_add_import(self, AddImportOptions(module="locale", name=name))
|
|
180
182
|
maybe_remove_import(
|
|
@@ -93,7 +93,7 @@ class ReplacePlatformPopen(Recipe):
|
|
|
93
93
|
self._imports = FromImports("platform")
|
|
94
94
|
|
|
95
95
|
def visit_compilation_unit(self, cu: CompilationUnit, p: ExecutionContext) -> J:
|
|
96
|
-
self._imports.scan(cu)
|
|
96
|
+
self._imports.scan(cu, self.cursor)
|
|
97
97
|
return super().visit_compilation_unit(cu, p)
|
|
98
98
|
|
|
99
99
|
def visit_method_invocation(
|
|
@@ -92,7 +92,7 @@ class FindSslMatchHostname(Recipe):
|
|
|
92
92
|
self._imports = FromImports("ssl")
|
|
93
93
|
|
|
94
94
|
def visit_compilation_unit(self, cu: CompilationUnit, p: ExecutionContext) -> J:
|
|
95
|
-
self._imports.scan(cu)
|
|
95
|
+
self._imports.scan(cu, self.cursor)
|
|
96
96
|
return super().visit_compilation_unit(cu, p)
|
|
97
97
|
|
|
98
98
|
def visit_method_invocation(
|
|
@@ -31,6 +31,8 @@ from rewrite.python.tree import (
|
|
|
31
31
|
)
|
|
32
32
|
from rewrite.utils import random_id
|
|
33
33
|
|
|
34
|
+
from ._slots import as_slot_of
|
|
35
|
+
|
|
34
36
|
# Define category path: Python > Migrate > Python 3.6
|
|
35
37
|
_Python36 = [
|
|
36
38
|
*Python,
|
|
@@ -354,7 +356,7 @@ class ReplaceStrFormatWithFString(Recipe):
|
|
|
354
356
|
class Visitor(PythonVisitor[ExecutionContext]):
|
|
355
357
|
def visit_method_invocation(
|
|
356
358
|
self, method: MethodInvocation, p: ExecutionContext
|
|
357
|
-
) -> Optional[
|
|
359
|
+
) -> Optional[J]:
|
|
358
360
|
method = super().visit_method_invocation(method, p)
|
|
359
361
|
|
|
360
362
|
if not isinstance(method, MethodInvocation):
|
|
@@ -373,7 +375,7 @@ class ReplaceStrFormatWithFString(Recipe):
|
|
|
373
375
|
|
|
374
376
|
result = _convert_format_to_fstring(method)
|
|
375
377
|
if result is not None:
|
|
376
|
-
return result
|
|
378
|
+
return as_slot_of(self.cursor, result)
|
|
377
379
|
|
|
378
380
|
return method
|
|
379
381
|
|
|
@@ -20,14 +20,12 @@ handled with `ChangeImport` in `upgrade_to_python39`.
|
|
|
20
20
|
See: https://peps.python.org/pep-0585/
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
|
-
import ast
|
|
24
23
|
from typing import Any, ClassVar, Optional, Set, cast
|
|
25
24
|
|
|
26
25
|
from rewrite import ExecutionContext, Recipe, Tree, TreeVisitor
|
|
27
26
|
from rewrite.category import CategoryDescriptor
|
|
28
27
|
from rewrite.decorators import categorize
|
|
29
28
|
from rewrite.marketplace import Python
|
|
30
|
-
from rewrite.python.markers import Quoted
|
|
31
29
|
from rewrite.python.scope_utils import LocalBindings
|
|
32
30
|
from rewrite.visitor import Cursor
|
|
33
31
|
|
|
@@ -53,7 +51,6 @@ from rewrite.java.tree import (
|
|
|
53
51
|
Identifier,
|
|
54
52
|
Import,
|
|
55
53
|
J,
|
|
56
|
-
Literal,
|
|
57
54
|
ParameterizedType,
|
|
58
55
|
VariableDeclarations,
|
|
59
56
|
)
|
|
@@ -181,61 +178,13 @@ def _make_builtin_alias_editor(
|
|
|
181
178
|
|
|
182
179
|
result = cast(CompilationUnit, super().visit_compilation_unit(cu, p))
|
|
183
180
|
|
|
184
|
-
|
|
185
|
-
# RemoveImport's usage check; scanning the rewritten tree finds the
|
|
186
|
-
# ones that outlived the rename.
|
|
187
|
-
if self._bare_ref is not None and not self._forward_reference_survives(
|
|
188
|
-
result, self._bare_ref
|
|
189
|
-
):
|
|
181
|
+
if self._bare_ref is not None:
|
|
190
182
|
maybe_remove_typing_import(self, old_name)
|
|
191
183
|
if self._rewrote_qualified:
|
|
192
184
|
maybe_remove_typing_module_import(self, self._module_refs)
|
|
193
185
|
|
|
194
186
|
return result
|
|
195
187
|
|
|
196
|
-
@staticmethod
|
|
197
|
-
def _forward_reference_survives(cu: CompilationUnit, name: str) -> bool:
|
|
198
|
-
"""True when a string forward reference still names ``name``.
|
|
199
|
-
|
|
200
|
-
The parser leaves such a reference as text -- a string `Literal`
|
|
201
|
-
annotation, or an `Identifier` marked `Quoted` -- so its contents are
|
|
202
|
-
parsed as an expression. Prose that merely spells the name out, as a
|
|
203
|
-
docstring does, is not an expression and so is not a reference.
|
|
204
|
-
"""
|
|
205
|
-
found = False
|
|
206
|
-
|
|
207
|
-
def names_target(text: str) -> bool:
|
|
208
|
-
if name not in text:
|
|
209
|
-
return False
|
|
210
|
-
try:
|
|
211
|
-
parsed = ast.parse(text.strip(), mode="eval")
|
|
212
|
-
except (SyntaxError, ValueError):
|
|
213
|
-
return False
|
|
214
|
-
return any(
|
|
215
|
-
isinstance(node, ast.Name) and node.id == name
|
|
216
|
-
for node in ast.walk(parsed)
|
|
217
|
-
)
|
|
218
|
-
|
|
219
|
-
class ForwardReferenceScan(PythonVisitor[Any]):
|
|
220
|
-
def visit_literal(self, literal: Literal, p: Any) -> J:
|
|
221
|
-
nonlocal found
|
|
222
|
-
if not found and isinstance(literal.value, str) and names_target(literal.value):
|
|
223
|
-
found = True
|
|
224
|
-
return literal
|
|
225
|
-
|
|
226
|
-
def visit_identifier(self, ident: Identifier, p: Any) -> J:
|
|
227
|
-
nonlocal found
|
|
228
|
-
if (
|
|
229
|
-
not found
|
|
230
|
-
and ident.markers.find_first(Quoted) is not None
|
|
231
|
-
and names_target(ident.simple_name)
|
|
232
|
-
):
|
|
233
|
-
found = True
|
|
234
|
-
return ident
|
|
235
|
-
|
|
236
|
-
ForwardReferenceScan().visit(cu, None)
|
|
237
|
-
return found
|
|
238
|
-
|
|
239
188
|
def visit_field_access(self, field_access: FieldAccess, p: ExecutionContext) -> J:
|
|
240
189
|
if (
|
|
241
190
|
isinstance(field_access.target, Identifier)
|
|
@@ -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.dev20260904122505
|
|
4
4
|
Summary: OpenRewrite recipes for migrating Python codebases to newer Python versions.
|
|
5
5
|
Author-email: "Moderne Inc." <support@moderne.io>
|
|
6
6
|
License: Moderne Proprietary
|
|
@@ -21,7 +21,7 @@ Classifier: Typing :: Typed
|
|
|
21
21
|
Requires-Python: >=3.10
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
23
23
|
Provides-Extra: dev
|
|
24
|
-
Requires-Dist: openrewrite>=8.91.
|
|
24
|
+
Requires-Dist: openrewrite>=8.91.5; extra == "dev"
|
|
25
25
|
Requires-Dist: pydantic>=2.11; extra == "dev"
|
|
26
26
|
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
27
27
|
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
@@ -26,6 +26,7 @@ src/openrewrite_migrate_python/migrate/_from_imports.py
|
|
|
26
26
|
src/openrewrite_migrate_python/migrate/_import_hygiene.py
|
|
27
27
|
src/openrewrite_migrate_python/migrate/_langchain_tables.py
|
|
28
28
|
src/openrewrite_migrate_python/migrate/_markers.py
|
|
29
|
+
src/openrewrite_migrate_python/migrate/_slots.py
|
|
29
30
|
src/openrewrite_migrate_python/migrate/_typing_imports.py
|
|
30
31
|
src/openrewrite_migrate_python/migrate/aifc_migrations.py
|
|
31
32
|
src/openrewrite_migrate_python/migrate/array_deprecations.py
|
|
@@ -4,10 +4,35 @@ from rewrite.test import RecipeSpec, python
|
|
|
4
4
|
from openrewrite_migrate_python.migrate.asyncio_coroutine_to_async import (
|
|
5
5
|
MigrateAsyncioCoroutine,
|
|
6
6
|
)
|
|
7
|
+
from tests.tree_checks import assert_statement_slots_hold_statements
|
|
7
8
|
|
|
8
9
|
class TestMigrateAsyncioCoroutine:
|
|
9
10
|
"""Tests for the MigrateAsyncioCoroutine recipe."""
|
|
10
11
|
|
|
12
|
+
def test_await_lands_in_the_slot_its_yield_from_occupied(self):
|
|
13
|
+
"""A statement-level `yield from` becomes an `await` statement; an expression-level one a bare `await`."""
|
|
14
|
+
spec = RecipeSpec(recipe=MigrateAsyncioCoroutine())
|
|
15
|
+
spec.rewrite_run(
|
|
16
|
+
python(
|
|
17
|
+
"""
|
|
18
|
+
import asyncio
|
|
19
|
+
|
|
20
|
+
@asyncio.coroutine
|
|
21
|
+
def run():
|
|
22
|
+
yield from step()
|
|
23
|
+
result = yield from step()
|
|
24
|
+
""",
|
|
25
|
+
"""
|
|
26
|
+
import asyncio
|
|
27
|
+
|
|
28
|
+
async def run():
|
|
29
|
+
await step()
|
|
30
|
+
result = await step()
|
|
31
|
+
""",
|
|
32
|
+
after_recipe=assert_statement_slots_hold_statements,
|
|
33
|
+
)
|
|
34
|
+
)
|
|
35
|
+
|
|
11
36
|
def test_migrates_simple_coroutine(self):
|
|
12
37
|
"""Test migration of a simple @asyncio.coroutine function."""
|
|
13
38
|
spec = RecipeSpec(recipe=MigrateAsyncioCoroutine())
|
|
@@ -130,3 +155,30 @@ class TestMigrateAsyncioCoroutine:
|
|
|
130
155
|
""",
|
|
131
156
|
)
|
|
132
157
|
)
|
|
158
|
+
|
|
159
|
+
def test_leaves_yield_from_in_nested_def_alone(self):
|
|
160
|
+
"""A nested def or lambda keeps its yield from; await is a SyntaxError there."""
|
|
161
|
+
spec = RecipeSpec(recipe=MigrateAsyncioCoroutine())
|
|
162
|
+
spec.rewrite_run(
|
|
163
|
+
python(
|
|
164
|
+
"""
|
|
165
|
+
import asyncio
|
|
166
|
+
|
|
167
|
+
@asyncio.coroutine
|
|
168
|
+
def outer():
|
|
169
|
+
def gen():
|
|
170
|
+
yield from range(3)
|
|
171
|
+
g = lambda: (yield from range(3))
|
|
172
|
+
yield from step()
|
|
173
|
+
""",
|
|
174
|
+
"""
|
|
175
|
+
import asyncio
|
|
176
|
+
|
|
177
|
+
async def outer():
|
|
178
|
+
def gen():
|
|
179
|
+
yield from range(3)
|
|
180
|
+
g = lambda: (yield from range(3))
|
|
181
|
+
await step()
|
|
182
|
+
""",
|
|
183
|
+
)
|
|
184
|
+
)
|
|
@@ -100,3 +100,19 @@ class TestReplaceGettextDeprecations:
|
|
|
100
100
|
"""
|
|
101
101
|
)
|
|
102
102
|
)
|
|
103
|
+
|
|
104
|
+
def test_no_change_when_the_replacement_name_is_already_bound(self):
|
|
105
|
+
"""The added import would be shadowed by the file's own `gettext`."""
|
|
106
|
+
spec = RecipeSpec(recipe=ReplaceGettextDeprecations())
|
|
107
|
+
spec.rewrite_run(
|
|
108
|
+
python(
|
|
109
|
+
"""
|
|
110
|
+
from gettext import lgettext
|
|
111
|
+
|
|
112
|
+
def gettext(m):
|
|
113
|
+
return m
|
|
114
|
+
|
|
115
|
+
msg = lgettext("Hello")
|
|
116
|
+
"""
|
|
117
|
+
)
|
|
118
|
+
)
|