openrewrite-migrate-python 0.14.0.dev20260902170552__tar.gz → 0.14.0.dev20260903170551__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.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/PKG-INFO +1 -1
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/pyproject.toml +1 -1
- openrewrite_migrate_python-0.14.0.dev20260903170551/src/openrewrite_migrate_python/migrate/_from_imports.py +57 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/gettext_deprecations.py +26 -4
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/locale_deprecations.py +33 -8
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/locale_getdefaultlocale_deprecation.py +8 -10
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/platform_deprecations.py +47 -18
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/ssl_deprecations.py +13 -2
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python.egg-info/PKG-INFO +1 -1
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python.egg-info/SOURCES.txt +1 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_gettext_deprecations.py +16 -0
- openrewrite_migrate_python-0.14.0.dev20260903170551/tests/test_locale_deprecations.py +110 -0
- openrewrite_migrate_python-0.14.0.dev20260903170551/tests/test_locale_getdefaultlocale_deprecation.py +45 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_platform_deprecations.py +28 -8
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_ssl_deprecations.py +16 -0
- openrewrite_migrate_python-0.14.0.dev20260902170552/tests/test_locale_deprecations.py +0 -53
- openrewrite_migrate_python-0.14.0.dev20260902170552/tests/test_locale_getdefaultlocale_deprecation.py +0 -26
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/setup.cfg +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_code_quality_python/__init__.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_code_quality_python/codequality/__init__.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_code_quality_python/codequality/_reindent.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_code_quality_python/codequality/_semantically_equal.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_code_quality_python/codequality/_trivia.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_code_quality_python/codequality/all_branches_identical.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_code_quality_python/codequality/boolean_checks_not_inverted.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_code_quality_python/codequality/collapsible_if_statements.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_code_quality_python/codequality/find_suspicious_chained_comparison.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_code_quality_python/codequality/merge_identical_branches.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_code_quality_python/codequality/remove_duplicate_conditions.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_code_quality_python/codequality/remove_self_assignment.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_code_quality_python/codequality/remove_unconditional_value_overwrite.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_code_quality_python/codequality/simplify_boolean_literal.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_code_quality_python/codequality/simplify_redundant_logical_expression.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/__init__.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/__init__.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/_import_hygiene.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/_langchain_tables.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/_markers.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/_typing_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/aifc_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/array_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/ast_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/asyncio_coroutine_to_async.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/asyncio_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/avro_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/calendar_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/cgi_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/cgi_parse_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/collections_abc_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/configparser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/datetime_utc.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/distutils_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/distutils_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/functools_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/future_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/html_parser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/imp_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/langchain_classic_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/langchain_community_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/langchain_provider_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/macpath_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/mailcap_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/nntplib_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/os_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/pathlib_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/pep594_system_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/pipes_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/pkgutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/pydantic_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/pydantic_fields.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/pydantic_model_fields.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/re_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/removed_modules_312.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/shutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/socket_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/string_formatting.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/sys_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/sys_last_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/tarfile_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/telnetlib_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/tempfile_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/threading_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/threading_is_alive_deprecation.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/typing_callable.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/typing_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/typing_union_to_pipe.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/unittest_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/upgrade_to_langchain02.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/upgrade_to_langchain1.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/upgrade_to_pydantic.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/upgrade_to_python310.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/upgrade_to_python311.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/upgrade_to_python312.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/upgrade_to_python313.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/upgrade_to_python314.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/upgrade_to_python38.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/upgrade_to_python39.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/urllib_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/uu_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/xdrlib_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python/migrate/xml_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python.egg-info/dependency_links.txt +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python.egg-info/entry_points.txt +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python.egg-info/requires.txt +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/src/openrewrite_migrate_python.egg-info/top_level.txt +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_aifc_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_array_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_ast_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_asyncio_coroutine_to_async.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_asyncio_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_avro_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_calendar_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_cgi_parse_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_change_import_recipes.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_collections_abc_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_configparser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_datetime_utc.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_distutils_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_future_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_html_parser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_imp_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_langchain_classic_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_langchain_community_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_langchain_provider_imports.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_macpath_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_os_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_pep594_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_pep594_system_migrations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_pkgutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_pydantic_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_pydantic_fields.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_pydantic_model_fields.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_re_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_removed_modules_312.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_shutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_string_formatting.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_sys_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_sys_last_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_tarfile_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_threading_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_threading_extended.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_threading_is_alive_deprecation.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_typing_alias_moves.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_typing_callable.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_typing_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_typing_union_to_pipe.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_unittest_deprecations.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_upgrade_recipes.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/tests/test_upgrade_to_pydantic.py +0 -0
- {openrewrite_migrate_python-0.14.0.dev20260902170552 → openrewrite_migrate_python-0.14.0.dev20260903170551}/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.dev20260903170551
|
|
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.dev20260903170551" # 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,57 @@
|
|
|
1
|
+
"""Resolving a receiver-less call to the module member it was imported from."""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Optional
|
|
4
|
+
|
|
5
|
+
from rewrite import Cursor
|
|
6
|
+
from rewrite.java.tree import FieldAccess, Identifier, J, MethodInvocation
|
|
7
|
+
from rewrite.python.import_utils import get_alias_name, get_name_string, get_qualid_name
|
|
8
|
+
from rewrite.python.scope_utils import LocalBindings
|
|
9
|
+
from rewrite.python.tree import CompilationUnit, MultiImport
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _is_relative(from_: J) -> bool:
|
|
13
|
+
"""Whether ``from_`` is dotted, which the LST spells as an empty leading identifier."""
|
|
14
|
+
while isinstance(from_, FieldAccess):
|
|
15
|
+
from_ = from_.target
|
|
16
|
+
return isinstance(from_, Identifier) and not from_.simple_name
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class FromImports:
|
|
20
|
+
"""The members of ``module`` a file binds with ``from <module> import <member>``.
|
|
21
|
+
|
|
22
|
+
Under this form the call has no receiver, and for a symbol the typeshed in
|
|
23
|
+
use omits, no resolved declaring type either. The releases that removed
|
|
24
|
+
these APIs span many versions, so no declared version resolves them all —
|
|
25
|
+
attribution quality does not make this fallback redundant.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, module: str) -> None:
|
|
29
|
+
self._module = module
|
|
30
|
+
self._members: Dict[str, str] = {}
|
|
31
|
+
self._locals = LocalBindings()
|
|
32
|
+
|
|
33
|
+
def scan(self, cu: CompilationUnit) -> None:
|
|
34
|
+
"""Record the file's bindings; call from ``visit_compilation_unit``.
|
|
35
|
+
|
|
36
|
+
Top-level ``from`` statements only, since a guarded import's fallback may
|
|
37
|
+
bind the name to a shim rather than the module's own member.
|
|
38
|
+
"""
|
|
39
|
+
self._members = {}
|
|
40
|
+
self._locals = LocalBindings()
|
|
41
|
+
for stmt in cu.statements:
|
|
42
|
+
if not isinstance(stmt, MultiImport) or stmt.from_ is None:
|
|
43
|
+
continue
|
|
44
|
+
# `from .locale import x` binds a sibling module, which
|
|
45
|
+
# `get_name_string` renders indistinguishably from the stdlib one.
|
|
46
|
+
if _is_relative(stmt.from_) or get_name_string(stmt.from_) != self._module:
|
|
47
|
+
continue
|
|
48
|
+
for imp in stmt.names:
|
|
49
|
+
name = get_qualid_name(imp.qualid)
|
|
50
|
+
self._members.setdefault(get_alias_name(imp) or name, name)
|
|
51
|
+
|
|
52
|
+
def member_called(self, method: MethodInvocation, cursor: Cursor) -> Optional[str]:
|
|
53
|
+
"""The ``module`` member a receiver-less ``method`` calls, if it calls one."""
|
|
54
|
+
if method.select is not None or not isinstance(method.name, Identifier):
|
|
55
|
+
return None
|
|
56
|
+
name = method.name.simple_name
|
|
57
|
+
return None if self._locals.is_bound(cursor, name) else self._members.get(name)
|
|
@@ -18,9 +18,14 @@ from rewrite import ExecutionContext, Preconditions, Recipe, TreeVisitor
|
|
|
18
18
|
from rewrite.category import CategoryDescriptor
|
|
19
19
|
from rewrite.decorators import categorize
|
|
20
20
|
from rewrite.marketplace import Python
|
|
21
|
+
from rewrite.python.add_import import AddImportOptions, maybe_add_import
|
|
21
22
|
from rewrite.python.preconditions import uses_import
|
|
23
|
+
from rewrite.python.remove_import import RemoveImportOptions, maybe_remove_import
|
|
24
|
+
from rewrite.python.tree import CompilationUnit
|
|
22
25
|
from rewrite.python.visitor import PythonVisitor
|
|
23
|
-
from rewrite.java.tree import Identifier, MethodInvocation
|
|
26
|
+
from rewrite.java.tree import Identifier, J, MethodInvocation
|
|
27
|
+
|
|
28
|
+
from ._from_imports import FromImports
|
|
24
29
|
|
|
25
30
|
# Define category path: Python > Migrate > Python 3.11
|
|
26
31
|
_Python311 = [
|
|
@@ -105,6 +110,14 @@ class ReplaceGettextDeprecations(Recipe):
|
|
|
105
110
|
|
|
106
111
|
def editor(self) -> TreeVisitor[Any, ExecutionContext]:
|
|
107
112
|
class Visitor(PythonVisitor[ExecutionContext]):
|
|
113
|
+
def __init__(self) -> None:
|
|
114
|
+
super().__init__()
|
|
115
|
+
self._imports = FromImports("gettext")
|
|
116
|
+
|
|
117
|
+
def visit_compilation_unit(self, cu: CompilationUnit, p: ExecutionContext) -> J:
|
|
118
|
+
self._imports.scan(cu)
|
|
119
|
+
return super().visit_compilation_unit(cu, p)
|
|
120
|
+
|
|
108
121
|
def visit_method_invocation(
|
|
109
122
|
self, method: MethodInvocation, p: ExecutionContext
|
|
110
123
|
) -> Optional[MethodInvocation]:
|
|
@@ -115,12 +128,21 @@ class ReplaceGettextDeprecations(Recipe):
|
|
|
115
128
|
|
|
116
129
|
method_name = method.name.simple_name
|
|
117
130
|
|
|
118
|
-
#
|
|
119
|
-
|
|
131
|
+
# A receiver-less call belongs to the branch below, which moves
|
|
132
|
+
# the import as well as renaming the call.
|
|
133
|
+
if method.select is not None and method_name in GETTEXT_DEPRECATIONS:
|
|
120
134
|
if _is_gettext_method(method, method_name):
|
|
121
135
|
new_name = GETTEXT_DEPRECATIONS[method_name]
|
|
122
136
|
return _rename_method(method, new_name)
|
|
123
137
|
|
|
124
|
-
|
|
138
|
+
# `from gettext import lgettext` names the function itself, so
|
|
139
|
+
# the import moves to the replacement along with the call.
|
|
140
|
+
member = self._imports.member_called(method, self.cursor)
|
|
141
|
+
new_name = GETTEXT_DEPRECATIONS.get(member) if member else None
|
|
142
|
+
if new_name is None:
|
|
143
|
+
return method
|
|
144
|
+
maybe_add_import(self, AddImportOptions(module="gettext", name=new_name))
|
|
145
|
+
maybe_remove_import(self, RemoveImportOptions(module="gettext", name=member))
|
|
146
|
+
return _rename_method(method, new_name)
|
|
125
147
|
|
|
126
148
|
return Preconditions.check(uses_import("gettext"), Visitor())
|
|
@@ -14,12 +14,18 @@ from rewrite.category import CategoryDescriptor
|
|
|
14
14
|
from rewrite.decorators import categorize
|
|
15
15
|
from rewrite.marketplace import Python
|
|
16
16
|
from rewrite.markers import Markers
|
|
17
|
+
from rewrite.python.add_import import AddImportOptions, maybe_add_import
|
|
18
|
+
from rewrite.python.import_utils import get_name_string
|
|
17
19
|
from rewrite.python.preconditions import uses_import
|
|
20
|
+
from rewrite.python.remove_import import RemoveImportOptions, maybe_remove_import
|
|
21
|
+
from rewrite.python.tree import CompilationUnit
|
|
18
22
|
from rewrite.python.visitor import PythonVisitor
|
|
19
|
-
from rewrite.java.tree import Identifier, MethodInvocation, Literal
|
|
23
|
+
from rewrite.java.tree import Identifier, J, MethodInvocation, Literal
|
|
20
24
|
from rewrite.java.support_types import JRightPadded, Space
|
|
21
25
|
from rewrite.utils import random_id
|
|
22
26
|
|
|
27
|
+
from ._from_imports import FromImports
|
|
28
|
+
|
|
23
29
|
# Define category path: Python > Migrate > Python 3.11
|
|
24
30
|
_Python311 = [
|
|
25
31
|
*Python,
|
|
@@ -142,21 +148,40 @@ class ReplaceLocaleResetlocale(Recipe):
|
|
|
142
148
|
|
|
143
149
|
def editor(self) -> TreeVisitor[Any, ExecutionContext]:
|
|
144
150
|
class Visitor(PythonVisitor[ExecutionContext]):
|
|
151
|
+
def __init__(self) -> None:
|
|
152
|
+
super().__init__()
|
|
153
|
+
self._imports = FromImports("locale")
|
|
154
|
+
|
|
155
|
+
def visit_compilation_unit(self, cu: CompilationUnit, p: ExecutionContext) -> J:
|
|
156
|
+
self._imports.scan(cu)
|
|
157
|
+
return super().visit_compilation_unit(cu, p)
|
|
158
|
+
|
|
145
159
|
def visit_method_invocation(
|
|
146
160
|
self, method: MethodInvocation, p: ExecutionContext
|
|
147
161
|
) -> Optional[MethodInvocation]:
|
|
148
162
|
method = super().visit_method_invocation(method, p)
|
|
149
163
|
|
|
150
|
-
|
|
151
|
-
|
|
164
|
+
select = method.select
|
|
165
|
+
if select is not None and _is_locale_method(method, "resetlocale"):
|
|
152
166
|
method = _rename_method(method, "setlocale")
|
|
153
|
-
#
|
|
154
|
-
|
|
167
|
+
# LC_ALL is reached through the same name the call reached
|
|
168
|
+
# the module by, which `import locale as loc` makes `loc`.
|
|
169
|
+
return _set_arguments(
|
|
155
170
|
method,
|
|
156
|
-
("id", "
|
|
157
|
-
("str", "")
|
|
171
|
+
("id", f"{get_name_string(select)}.LC_ALL"),
|
|
172
|
+
("str", ""),
|
|
158
173
|
)
|
|
159
|
-
|
|
174
|
+
|
|
175
|
+
if self._imports.member_called(method, self.cursor) == "resetlocale":
|
|
176
|
+
# `setlocale` and `LC_ALL` are spelled unqualified, so each
|
|
177
|
+
# needs an import of its own.
|
|
178
|
+
for name in ("setlocale", "LC_ALL"):
|
|
179
|
+
maybe_add_import(self, AddImportOptions(module="locale", name=name))
|
|
180
|
+
maybe_remove_import(
|
|
181
|
+
self, RemoveImportOptions(module="locale", name="resetlocale")
|
|
182
|
+
)
|
|
183
|
+
method = _rename_method(method, "setlocale")
|
|
184
|
+
return _set_arguments(method, ("id", "LC_ALL"), ("str", ""))
|
|
160
185
|
|
|
161
186
|
return method
|
|
162
187
|
|
|
@@ -13,9 +13,10 @@ from rewrite import ExecutionContext, Preconditions, Recipe, TreeVisitor
|
|
|
13
13
|
from rewrite.category import CategoryDescriptor
|
|
14
14
|
from rewrite.decorators import categorize
|
|
15
15
|
from rewrite.marketplace import Python
|
|
16
|
+
from rewrite.python.method_matcher import MethodMatcher
|
|
16
17
|
from rewrite.python.preconditions import uses_method
|
|
17
18
|
from rewrite.python.visitor import PythonVisitor
|
|
18
|
-
from rewrite.java.tree import
|
|
19
|
+
from rewrite.java.tree import MethodInvocation
|
|
19
20
|
from ._markers import mark_deprecated
|
|
20
21
|
|
|
21
22
|
# Define category path: Python > Migrate > Python 3.11
|
|
@@ -25,6 +26,11 @@ _Python311 = [
|
|
|
25
26
|
CategoryDescriptor(display_name="Python 3.11"),
|
|
26
27
|
]
|
|
27
28
|
|
|
29
|
+
# One pattern covers `import locale`, `import locale as loc` and the from-import
|
|
30
|
+
# form, since the owner resolves the same for each. Once the scheduled removal
|
|
31
|
+
# lands this needs the `_from_imports` fallback the sibling recipes carry.
|
|
32
|
+
_GETDEFAULTLOCALE = MethodMatcher.create("locale getdefaultlocale(..)")
|
|
33
|
+
|
|
28
34
|
|
|
29
35
|
@categorize(_Python311)
|
|
30
36
|
class FindLocaleGetdefaultlocale(Recipe):
|
|
@@ -73,15 +79,7 @@ class FindLocaleGetdefaultlocale(Recipe):
|
|
|
73
79
|
) -> Optional[MethodInvocation]:
|
|
74
80
|
method = super().visit_method_invocation(method, p)
|
|
75
81
|
|
|
76
|
-
if not
|
|
77
|
-
return method
|
|
78
|
-
if method.name.simple_name != "getdefaultlocale":
|
|
79
|
-
return method
|
|
80
|
-
|
|
81
|
-
select = method.select
|
|
82
|
-
if not isinstance(select, Identifier):
|
|
83
|
-
return method
|
|
84
|
-
if select.simple_name != "locale":
|
|
82
|
+
if not _GETDEFAULTLOCALE.matches(method):
|
|
85
83
|
return method
|
|
86
84
|
|
|
87
85
|
return mark_deprecated(
|
|
@@ -14,15 +14,17 @@ from rewrite.category import CategoryDescriptor
|
|
|
14
14
|
from rewrite.decorators import categorize
|
|
15
15
|
from rewrite.marketplace import Python
|
|
16
16
|
from rewrite.markers import Markers
|
|
17
|
-
from rewrite.python.preconditions import
|
|
17
|
+
from rewrite.python.preconditions import uses_import
|
|
18
18
|
from rewrite.python.visitor import PythonVisitor
|
|
19
19
|
|
|
20
20
|
from rewrite.python.type_utils import is_of_class_type
|
|
21
21
|
from rewrite.java.support_types import JLeftPadded, JRightPadded, Space
|
|
22
|
-
from rewrite.java.tree import Identifier,
|
|
23
|
-
from rewrite.python.tree import NamedArgument
|
|
22
|
+
from rewrite.java.tree import Identifier, J, MethodInvocation
|
|
23
|
+
from rewrite.python.tree import CompilationUnit, NamedArgument
|
|
24
24
|
from rewrite.utils import random_id
|
|
25
25
|
|
|
26
|
+
from ._from_imports import FromImports
|
|
27
|
+
|
|
26
28
|
# Define category path: Python > Migrate > Python 3.8
|
|
27
29
|
_Python38 = [
|
|
28
30
|
*Python,
|
|
@@ -31,6 +33,22 @@ _Python38 = [
|
|
|
31
33
|
]
|
|
32
34
|
|
|
33
35
|
|
|
36
|
+
def _qualify(method: MethodInvocation, module: str) -> MethodInvocation:
|
|
37
|
+
"""``method`` called through ``module`` as its receiver."""
|
|
38
|
+
select = Identifier(
|
|
39
|
+
_id=random_id(),
|
|
40
|
+
_prefix=Space.EMPTY,
|
|
41
|
+
_markers=Markers.EMPTY,
|
|
42
|
+
_annotations=[],
|
|
43
|
+
_simple_name=module,
|
|
44
|
+
_type=None,
|
|
45
|
+
_field_type=None,
|
|
46
|
+
)
|
|
47
|
+
return method.padding.replace(
|
|
48
|
+
_select=JRightPadded(select, Space.EMPTY, Markers.EMPTY)
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
34
52
|
@categorize(_Python38)
|
|
35
53
|
class ReplacePlatformPopen(Recipe):
|
|
36
54
|
"""
|
|
@@ -70,6 +88,14 @@ class ReplacePlatformPopen(Recipe):
|
|
|
70
88
|
|
|
71
89
|
def editor(self) -> TreeVisitor[Any, ExecutionContext]:
|
|
72
90
|
class Visitor(PythonVisitor[ExecutionContext]):
|
|
91
|
+
def __init__(self) -> None:
|
|
92
|
+
super().__init__()
|
|
93
|
+
self._imports = FromImports("platform")
|
|
94
|
+
|
|
95
|
+
def visit_compilation_unit(self, cu: CompilationUnit, p: ExecutionContext) -> J:
|
|
96
|
+
self._imports.scan(cu)
|
|
97
|
+
return super().visit_compilation_unit(cu, p)
|
|
98
|
+
|
|
73
99
|
def visit_method_invocation(
|
|
74
100
|
self, method: MethodInvocation, p: ExecutionContext
|
|
75
101
|
) -> Optional[MethodInvocation]:
|
|
@@ -77,23 +103,26 @@ class ReplacePlatformPopen(Recipe):
|
|
|
77
103
|
|
|
78
104
|
if not isinstance(method.name, Identifier):
|
|
79
105
|
return method
|
|
80
|
-
if method.name.simple_name != "popen":
|
|
81
|
-
return method
|
|
82
106
|
|
|
83
107
|
select = method.select
|
|
84
|
-
if
|
|
108
|
+
if select is None:
|
|
109
|
+
if self._imports.member_called(method, self.cursor) != "popen":
|
|
110
|
+
return method
|
|
111
|
+
method = _qualify(method, "subprocess")
|
|
112
|
+
elif (
|
|
113
|
+
method.name.simple_name == "popen"
|
|
114
|
+
and isinstance(select, Identifier)
|
|
115
|
+
# Confirm the receiver resolves to the `platform` module (by
|
|
116
|
+
# type, so an aliased import works and a same-named variable is
|
|
117
|
+
# not rewritten into a destructive `subprocess.check_output`).
|
|
118
|
+
and is_of_class_type(select.type, "platform")
|
|
119
|
+
):
|
|
120
|
+
new_select = select.replace(_simple_name="subprocess")
|
|
121
|
+
old_padded_select = method.padding.select
|
|
122
|
+
new_padded_select = old_padded_select.replace(_element=new_select)
|
|
123
|
+
method = method.padding.replace(_select=new_padded_select)
|
|
124
|
+
else:
|
|
85
125
|
return method
|
|
86
|
-
# Confirm the receiver resolves to the `platform` module (by
|
|
87
|
-
# type, so an aliased import works and a same-named variable is
|
|
88
|
-
# not rewritten into a destructive `subprocess.check_output`).
|
|
89
|
-
if not is_of_class_type(select.type, "platform"):
|
|
90
|
-
return method
|
|
91
|
-
|
|
92
|
-
# Replace platform with subprocess
|
|
93
|
-
new_select = select.replace(_simple_name="subprocess")
|
|
94
|
-
old_padded_select = method.padding.select
|
|
95
|
-
new_padded_select = old_padded_select.replace(_element=new_select)
|
|
96
|
-
method = method.padding.replace(_select=new_padded_select)
|
|
97
126
|
|
|
98
127
|
# Rename popen -> check_output
|
|
99
128
|
new_name = method.name.replace(_simple_name="check_output")
|
|
@@ -141,4 +170,4 @@ class ReplacePlatformPopen(Recipe):
|
|
|
141
170
|
|
|
142
171
|
return method
|
|
143
172
|
|
|
144
|
-
return Preconditions.check(
|
|
173
|
+
return Preconditions.check(uses_import("platform"), Visitor())
|
|
@@ -15,8 +15,10 @@ from rewrite.category import CategoryDescriptor
|
|
|
15
15
|
from rewrite.decorators import categorize
|
|
16
16
|
from rewrite.marketplace import Python
|
|
17
17
|
from rewrite.python.preconditions import uses_import
|
|
18
|
+
from rewrite.python.tree import CompilationUnit
|
|
18
19
|
from rewrite.python.visitor import PythonVisitor
|
|
19
|
-
from rewrite.java.tree import Identifier, MethodInvocation
|
|
20
|
+
from rewrite.java.tree import Identifier, J, MethodInvocation
|
|
21
|
+
from ._from_imports import FromImports
|
|
20
22
|
from ._markers import mark_deprecated
|
|
21
23
|
|
|
22
24
|
# Define category path: Python > Migrate > Python 3.12
|
|
@@ -85,12 +87,21 @@ class FindSslMatchHostname(Recipe):
|
|
|
85
87
|
|
|
86
88
|
def editor(self) -> TreeVisitor[Any, ExecutionContext]:
|
|
87
89
|
class Visitor(PythonVisitor[ExecutionContext]):
|
|
90
|
+
def __init__(self) -> None:
|
|
91
|
+
super().__init__()
|
|
92
|
+
self._imports = FromImports("ssl")
|
|
93
|
+
|
|
94
|
+
def visit_compilation_unit(self, cu: CompilationUnit, p: ExecutionContext) -> J:
|
|
95
|
+
self._imports.scan(cu)
|
|
96
|
+
return super().visit_compilation_unit(cu, p)
|
|
97
|
+
|
|
88
98
|
def visit_method_invocation(
|
|
89
99
|
self, method: MethodInvocation, p: ExecutionContext
|
|
90
100
|
) -> Optional[MethodInvocation]:
|
|
91
101
|
method = super().visit_method_invocation(method, p)
|
|
92
102
|
|
|
93
|
-
if _is_ssl_method(method, "match_hostname")
|
|
103
|
+
if (_is_ssl_method(method, "match_hostname")
|
|
104
|
+
or self._imports.member_called(method, self.cursor) == "match_hostname"):
|
|
94
105
|
return mark_deprecated(
|
|
95
106
|
method,
|
|
96
107
|
"ssl.match_hostname() is deprecated",
|
|
@@ -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.dev20260903170551
|
|
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
|
|
@@ -22,6 +22,7 @@ src/openrewrite_migrate_python.egg-info/entry_points.txt
|
|
|
22
22
|
src/openrewrite_migrate_python.egg-info/requires.txt
|
|
23
23
|
src/openrewrite_migrate_python.egg-info/top_level.txt
|
|
24
24
|
src/openrewrite_migrate_python/migrate/__init__.py
|
|
25
|
+
src/openrewrite_migrate_python/migrate/_from_imports.py
|
|
25
26
|
src/openrewrite_migrate_python/migrate/_import_hygiene.py
|
|
26
27
|
src/openrewrite_migrate_python/migrate/_langchain_tables.py
|
|
27
28
|
src/openrewrite_migrate_python/migrate/_markers.py
|
|
@@ -57,6 +57,22 @@ class TestReplaceGettextDeprecations:
|
|
|
57
57
|
)
|
|
58
58
|
)
|
|
59
59
|
|
|
60
|
+
def test_replaces_from_import_form(self):
|
|
61
|
+
"""The call and the import both move off the removed name."""
|
|
62
|
+
spec = RecipeSpec(recipe=ReplaceGettextDeprecations())
|
|
63
|
+
spec.rewrite_run(
|
|
64
|
+
python(
|
|
65
|
+
"""
|
|
66
|
+
from gettext import lgettext
|
|
67
|
+
msg = lgettext("Hello")
|
|
68
|
+
""",
|
|
69
|
+
"""
|
|
70
|
+
from gettext import gettext
|
|
71
|
+
msg = gettext("Hello")
|
|
72
|
+
""",
|
|
73
|
+
)
|
|
74
|
+
)
|
|
75
|
+
|
|
60
76
|
def test_no_change_when_already_correct(self):
|
|
61
77
|
"""Test that already-correct functions are not changed."""
|
|
62
78
|
spec = RecipeSpec(recipe=ReplaceGettextDeprecations())
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""Tests for locale deprecation migration recipes."""
|
|
2
|
+
|
|
3
|
+
from rewrite.test import RecipeSpec, python
|
|
4
|
+
from openrewrite_migrate_python.migrate.locale_deprecations import (
|
|
5
|
+
ReplaceLocaleResetlocale,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
class TestReplaceLocaleResetlocale:
|
|
9
|
+
"""Tests for the ReplaceLocaleResetlocale recipe."""
|
|
10
|
+
|
|
11
|
+
def test_replaces_locale_resetlocale(self):
|
|
12
|
+
"""Test that locale.resetlocale() is replaced with setlocale."""
|
|
13
|
+
spec = RecipeSpec(recipe=ReplaceLocaleResetlocale())
|
|
14
|
+
spec.rewrite_run(
|
|
15
|
+
python(
|
|
16
|
+
"""
|
|
17
|
+
import locale
|
|
18
|
+
locale.resetlocale()
|
|
19
|
+
""",
|
|
20
|
+
"""
|
|
21
|
+
import locale
|
|
22
|
+
locale.setlocale(locale.LC_ALL, "")
|
|
23
|
+
""",
|
|
24
|
+
)
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
def test_replacement_follows_the_import_form(self):
|
|
28
|
+
"""`setlocale` and `LC_ALL` are spelled the way the file reaches `locale`."""
|
|
29
|
+
spec = RecipeSpec(recipe=ReplaceLocaleResetlocale())
|
|
30
|
+
spec.rewrite_run(
|
|
31
|
+
python(
|
|
32
|
+
"""
|
|
33
|
+
from locale import resetlocale
|
|
34
|
+
resetlocale()
|
|
35
|
+
""",
|
|
36
|
+
"""
|
|
37
|
+
from locale import LC_ALL, setlocale
|
|
38
|
+
setlocale(LC_ALL, "")
|
|
39
|
+
""",
|
|
40
|
+
)
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
spec.rewrite_run(
|
|
44
|
+
python(
|
|
45
|
+
"""
|
|
46
|
+
import locale as loc
|
|
47
|
+
loc.resetlocale()
|
|
48
|
+
""",
|
|
49
|
+
"""
|
|
50
|
+
import locale as loc
|
|
51
|
+
loc.setlocale(loc.LC_ALL, "")
|
|
52
|
+
""",
|
|
53
|
+
)
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
def test_no_change_when_setlocale(self):
|
|
57
|
+
"""Test that locale.setlocale() is not marked."""
|
|
58
|
+
spec = RecipeSpec(recipe=ReplaceLocaleResetlocale())
|
|
59
|
+
spec.rewrite_run(
|
|
60
|
+
python(
|
|
61
|
+
"""
|
|
62
|
+
import locale
|
|
63
|
+
locale.setlocale(locale.LC_ALL, "")
|
|
64
|
+
"""
|
|
65
|
+
)
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
def test_no_change_when_locally_shadowed(self):
|
|
69
|
+
"""A local `resetlocale` is not the module's, however the module is imported."""
|
|
70
|
+
spec = RecipeSpec(recipe=ReplaceLocaleResetlocale())
|
|
71
|
+
spec.rewrite_run(
|
|
72
|
+
python(
|
|
73
|
+
"""
|
|
74
|
+
from locale import resetlocale
|
|
75
|
+
|
|
76
|
+
def reset():
|
|
77
|
+
def resetlocale():
|
|
78
|
+
pass
|
|
79
|
+
resetlocale()
|
|
80
|
+
"""
|
|
81
|
+
)
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
def test_no_change_on_a_relative_import(self):
|
|
85
|
+
"""`from .locale import` binds a sibling module, not the stdlib one."""
|
|
86
|
+
spec = RecipeSpec(recipe=ReplaceLocaleResetlocale())
|
|
87
|
+
spec.rewrite_run(
|
|
88
|
+
python(
|
|
89
|
+
"""
|
|
90
|
+
from .locale import resetlocale
|
|
91
|
+
resetlocale()
|
|
92
|
+
"""
|
|
93
|
+
)
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
def test_no_change_when_different_module(self):
|
|
97
|
+
"""Test that resetlocale on a different object is not marked."""
|
|
98
|
+
spec = RecipeSpec(recipe=ReplaceLocaleResetlocale())
|
|
99
|
+
spec.rewrite_run(
|
|
100
|
+
python(
|
|
101
|
+
"""
|
|
102
|
+
class MyLocale:
|
|
103
|
+
def resetlocale(self):
|
|
104
|
+
pass
|
|
105
|
+
|
|
106
|
+
obj = MyLocale()
|
|
107
|
+
obj.resetlocale()
|
|
108
|
+
"""
|
|
109
|
+
)
|
|
110
|
+
)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Tests for locale.getdefaultlocale() deprecation recipe."""
|
|
2
|
+
|
|
3
|
+
from rewrite.test import RecipeSpec, python
|
|
4
|
+
|
|
5
|
+
from openrewrite_migrate_python.migrate.locale_getdefaultlocale_deprecation import (
|
|
6
|
+
FindLocaleGetdefaultlocale,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
_MARKER = "/*~~(locale.getdefaultlocale() was deprecated in Python 3.11. Use locale.setlocale(), locale.getlocale(), or locale.getpreferredencoding(False) instead.)~~>*/"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TestFindLocaleGetdefaultlocale:
|
|
13
|
+
"""Tests for FindLocaleGetdefaultlocale recipe."""
|
|
14
|
+
|
|
15
|
+
def test_finds_locale_getdefaultlocale(self):
|
|
16
|
+
spec = RecipeSpec(recipe=FindLocaleGetdefaultlocale())
|
|
17
|
+
spec.rewrite_run(
|
|
18
|
+
python(
|
|
19
|
+
"import locale\nlang, enc = locale.getdefaultlocale()",
|
|
20
|
+
f"import locale\nlang, enc = {_MARKER}locale.getdefaultlocale()",
|
|
21
|
+
)
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
def test_finds_from_import_and_aliased_forms(self):
|
|
25
|
+
"""The import form does not decide whether the call is `locale`'s."""
|
|
26
|
+
spec = RecipeSpec(recipe=FindLocaleGetdefaultlocale())
|
|
27
|
+
spec.rewrite_run(
|
|
28
|
+
python(
|
|
29
|
+
"from locale import getdefaultlocale\nlang, enc = getdefaultlocale()",
|
|
30
|
+
f"from locale import getdefaultlocale\nlang, enc = {_MARKER}getdefaultlocale()",
|
|
31
|
+
)
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
spec.rewrite_run(
|
|
35
|
+
python(
|
|
36
|
+
"import locale as loc\nlang, enc = loc.getdefaultlocale()",
|
|
37
|
+
f"import locale as loc\nlang, enc = {_MARKER}loc.getdefaultlocale()",
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
def test_no_change_when_using_getlocale(self):
|
|
42
|
+
spec = RecipeSpec(recipe=FindLocaleGetdefaultlocale())
|
|
43
|
+
spec.rewrite_run(
|
|
44
|
+
python("import locale\nlang, enc = locale.getlocale()")
|
|
45
|
+
)
|
|
@@ -25,40 +25,60 @@ class TestReplacePlatformPopen:
|
|
|
25
25
|
)
|
|
26
26
|
)
|
|
27
27
|
|
|
28
|
-
def
|
|
28
|
+
def test_replaces_from_import_form(self):
|
|
29
|
+
"""A receiver-less call bound by `from platform import popen` is rewritten."""
|
|
29
30
|
spec = RecipeSpec(recipe=ReplacePlatformPopen())
|
|
30
31
|
spec.rewrite_run(
|
|
31
32
|
python(
|
|
32
33
|
"""
|
|
33
|
-
import
|
|
34
|
-
output =
|
|
34
|
+
from platform import popen
|
|
35
|
+
output = popen('ls')
|
|
36
|
+
""",
|
|
37
|
+
"""
|
|
38
|
+
from platform import popen
|
|
39
|
+
output = subprocess.check_output('ls', shell=True)
|
|
40
|
+
""",
|
|
41
|
+
)
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
def test_no_change_on_another_platform_function(self):
|
|
45
|
+
"""`popen` is the only function of the module this recipe rewrites."""
|
|
46
|
+
spec = RecipeSpec(recipe=ReplacePlatformPopen())
|
|
47
|
+
spec.rewrite_run(
|
|
48
|
+
python(
|
|
49
|
+
"""
|
|
50
|
+
import platform
|
|
51
|
+
name = platform.system()
|
|
35
52
|
"""
|
|
36
53
|
)
|
|
37
54
|
)
|
|
38
55
|
|
|
39
56
|
def test_no_change_when_already_subprocess(self):
|
|
57
|
+
"""Re-running over this recipe's own output leaves it alone."""
|
|
40
58
|
spec = RecipeSpec(recipe=ReplacePlatformPopen())
|
|
41
59
|
spec.rewrite_run(
|
|
42
60
|
python(
|
|
43
61
|
"""
|
|
44
|
-
import
|
|
62
|
+
import platform
|
|
45
63
|
output = subprocess.check_output('ls', shell=True)
|
|
46
64
|
"""
|
|
47
65
|
)
|
|
48
66
|
)
|
|
49
67
|
|
|
50
|
-
def
|
|
51
|
-
"""
|
|
68
|
+
def test_no_change_on_another_objects_popen(self):
|
|
69
|
+
"""`popen` on something that isn't the module, in a file that imports it."""
|
|
52
70
|
spec = RecipeSpec(recipe=ReplacePlatformPopen())
|
|
53
71
|
spec.rewrite_run(
|
|
54
72
|
python(
|
|
55
73
|
"""
|
|
74
|
+
import platform
|
|
75
|
+
|
|
56
76
|
class Shell:
|
|
57
77
|
def popen(self, cmd):
|
|
58
78
|
return cmd
|
|
59
79
|
|
|
60
|
-
|
|
61
|
-
output =
|
|
80
|
+
shell = Shell()
|
|
81
|
+
output = shell.popen('ls')
|
|
62
82
|
"""
|
|
63
83
|
)
|
|
64
84
|
)
|