openrewrite-migrate-python 0.18.0__tar.gz → 0.20.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/PKG-INFO +2 -2
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/pyproject.toml +2 -2
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/boolean_simplification.py +153 -51
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/pandas_cleanup.py +10 -2
- openrewrite_migrate_python-0.20.0/src/openrewrite_code_quality_python/codequality/_grouping.py +31 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/codequality/collapsible_if_statements.py +6 -1
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/codequality/merge_identical_branches.py +6 -1
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/_method_renames.py +13 -5
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/backoff_to_tenacity.py +74 -33
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python.egg-info/PKG-INFO +2 -2
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python.egg-info/SOURCES.txt +1 -1
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python.egg-info/requires.txt +1 -1
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_backoff_to_tenacity.py +291 -2
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_unittest_deprecations.py +32 -1
- openrewrite_migrate_python-0.20.0/tests/test_upgrade_recipes.py +743 -0
- openrewrite_migrate_python-0.18.0/tests/test_markers.py +0 -19
- openrewrite_migrate_python-0.18.0/tests/test_upgrade_recipes.py +0 -235
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/setup.cfg +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/__init__.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/__init__.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/_literals.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/_negation.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/assign_return.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/attr_access.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/collection_literals.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/comparison_simplification.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/complex_transforms.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/comprehension_cleanup.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/conditionals.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/datetime_cleanup.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/dict_cleanup.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/exception_cleanup.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/expression_simplification.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/logger_warn.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/loop_cleanup.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/merge_nested_with.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/merge_startswith_endswith.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/naming_conventions.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/negated_operators.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/none_and_identity.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/object_inheritance.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/python_best_practices.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/range_cleanup.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/redundant_code.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/remove_trailing_return_none.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/string_cleanup.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/unreachable_code.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/use_items.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/use_list_clear.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/cleanup/yoda_conditions.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/codequality/__init__.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/codequality/_reindent.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/codequality/_semantically_equal.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/codequality/_side_effects.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/codequality/_trivia.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/codequality/_truth_value.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/codequality/all_branches_identical.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/codequality/boolean_checks_not_inverted.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/codequality/code_quality.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/codequality/find_suspicious_chained_comparison.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/codequality/remove_duplicate_conditions.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/codequality/remove_self_assignment.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/codequality/remove_unconditional_value_overwrite.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/codequality/simplify_boolean_literal.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_code_quality_python/codequality/simplify_redundant_logical_expression.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/__init__.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/__init__.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/_decorators.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/_finders.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/_langchain_tables.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/_markers.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/_module_imports.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/_slots.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/aifc_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/array_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/ast_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/asyncio_coroutine_to_async.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/asyncio_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/avro_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/builtins_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/calendar_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/cgi_escape_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/cgi_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/cgi_parse_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/collections_abc_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/configparser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/ctypes_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/datetime_utc.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/distutils_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/distutils_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/functools_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/future_imports.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/gettext_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/glob_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/html_parser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/http_server_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/imp_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/importlib_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/importlib_resources_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/inspect_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/langchain_classic_imports.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/langchain_community_imports.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/langchain_provider_imports.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/locale_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/locale_getdefaultlocale_deprecation.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/macpath_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/mailcap_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/module_cached_attribute.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/nntplib_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/os_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/pathlib_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/pep594_system_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/pipes_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/pkgutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/platform_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/profile_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/pydantic_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/pydantic_fields.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/pydantic_model_fields.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/re_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/removed_modules_312.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/shutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/socket_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/sre_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/ssl_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/string_formatting.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/sys_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/sys_last_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/tarfile_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/telnetlib_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/tempfile_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/text_encoding.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/threading_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/threading_is_alive_deprecation.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/types_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/typing_callable.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/typing_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/typing_functional_syntax.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/typing_union_to_pipe.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/unittest_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/upgrade_to_langchain02.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/upgrade_to_langchain1.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/upgrade_to_pandas.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/upgrade_to_pydantic.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python310.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python311.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python312.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python313.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python314.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python315.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python38.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/upgrade_to_python39.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/urllib_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/uu_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/wave_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/webbrowser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/xdrlib_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python/migrate/xml_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python.egg-info/dependency_links.txt +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python.egg-info/entry_points.txt +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/src/openrewrite_migrate_python.egg-info/top_level.txt +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_aifc_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_array_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_ast_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_asyncio_coroutine_to_async.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_asyncio_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_avro_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_builtins_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_calendar_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_cgi_escape_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_cgi_parse_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_change_import_recipes.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_collections_abc_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_configparser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_ctypes_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_datetime_utc.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_distutils_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_distutils_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_functools_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_future_imports.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_gettext_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_glob_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_html_parser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_http_server_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_imp_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_importlib_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_importlib_resources_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_inspect_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_langchain_classic_imports.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_langchain_community_imports.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_langchain_provider_imports.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_locale_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_locale_getdefaultlocale_deprecation.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_macpath_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_mailcap_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_module_cached_attribute.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_os_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_pathlib_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_pep594_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_pep594_system_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_pkgutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_platform_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_profile_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_pydantic_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_pydantic_fields.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_pydantic_model_fields.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_re_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_recipe_conventions.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_recipe_reachability.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_removed_modules_312.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_shutil_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_socket_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_sre_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_ssl_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_string_formatting.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_sys_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_sys_last_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_tarfile_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_tempfile_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_text_encoding.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_threading_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_threading_extended.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_threading_is_alive_deprecation.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_types_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_typing_alias_moves.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_typing_callable.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_typing_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_typing_functional_syntax.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_typing_union_to_pipe.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_upgrade_to_pydantic.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_urllib_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_wave_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_webbrowser_deprecations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/tests/test_xdrlib_migrations.py +0 -0
- {openrewrite_migrate_python-0.18.0 → openrewrite_migrate_python-0.20.0}/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.
|
|
3
|
+
Version: 0.20.0
|
|
4
4
|
Summary: OpenRewrite recipes for migrating Python codebases to newer Python versions.
|
|
5
5
|
Author-email: "Moderne Inc." <support@moderne.io>
|
|
6
6
|
License: Moderne Proprietary
|
|
@@ -19,7 +19,7 @@ Classifier: Typing :: Typed
|
|
|
19
19
|
Requires-Python: >=3.12
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
Provides-Extra: dev
|
|
22
|
-
Requires-Dist: openrewrite>=8.
|
|
22
|
+
Requires-Dist: openrewrite>=8.96.3; extra == "dev"
|
|
23
23
|
Requires-Dist: pydantic>=2.11; extra == "dev"
|
|
24
24
|
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
25
25
|
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.
|
|
8
|
+
version = "0.20.0" # Updated dynamically during release
|
|
9
9
|
authors = [{ name = "Moderne Inc.", email = "support@moderne.io" }]
|
|
10
10
|
license = { text = "Moderne Proprietary" }
|
|
11
11
|
readme = "README.md"
|
|
@@ -28,7 +28,7 @@ dependencies = []
|
|
|
28
28
|
|
|
29
29
|
[project.optional-dependencies]
|
|
30
30
|
dev = [
|
|
31
|
-
"openrewrite>=8.
|
|
31
|
+
"openrewrite>=8.96.3",
|
|
32
32
|
# Needed so type-attribution tests can resolve `pydantic` types.
|
|
33
33
|
"pydantic>=2.11",
|
|
34
34
|
"pytest>=8.0.0",
|
|
@@ -14,7 +14,8 @@ unnecessary operators, literals, or indirection:
|
|
|
14
14
|
See: https://peps.python.org/pep-0008/#programming-recommendations
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
|
-
from typing import Any, List
|
|
17
|
+
from typing import AbstractSet, Any, Dict, List, NamedTuple, Tuple
|
|
18
|
+
from uuid import UUID
|
|
18
19
|
|
|
19
20
|
from rewrite import ExecutionContext, Preconditions, Recipe, TreeVisitor
|
|
20
21
|
from rewrite.markers import Markers
|
|
@@ -28,11 +29,11 @@ from rewrite.python.preconditions import uses_method
|
|
|
28
29
|
from rewrite.python.scope_utils import scope_of
|
|
29
30
|
from rewrite.python.type_utils import is_of_class_type
|
|
30
31
|
from rewrite.python.visitor import PythonVisitor
|
|
31
|
-
from rewrite.python.template import pattern, template, capture
|
|
32
|
+
from rewrite.python.template import Capture, Template, pattern, template, capture
|
|
32
33
|
from rewrite.python.template.pattern import MatchResult
|
|
33
34
|
from rewrite.java.tree import (
|
|
34
35
|
Binary as JBinary, Block, ControlParentheses, Empty, Expression, If as JIf, J,
|
|
35
|
-
Literal, MethodInvocation, Return, Ternary as JTernary, Unary,
|
|
36
|
+
Literal, MethodInvocation, Parentheses, Return, Ternary as JTernary, Unary,
|
|
36
37
|
WhileLoop as JWhileLoop,
|
|
37
38
|
)
|
|
38
39
|
from rewrite.java.support_types import JavaType, Space
|
|
@@ -80,22 +81,43 @@ _lc_not_x_template = template("not {lc_x}", lc_x=_lc_x)
|
|
|
80
81
|
|
|
81
82
|
|
|
82
83
|
# --- DeMorgan patterns/templates ---
|
|
84
|
+
class _Distributed(NamedTuple):
|
|
85
|
+
"""A De Morgan result, written alone or continuing a chain of its own operator."""
|
|
86
|
+
|
|
87
|
+
alone: Template
|
|
88
|
+
chained: Template
|
|
89
|
+
"""``{dm_z} and`` the result, which the parser nests to the left as it does ``z and a and b``."""
|
|
90
|
+
operator: JBinary.Type
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
_dm_z = capture('dm_z')
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _distributed(operator: str, left: str, right: str, captures: Dict[str, Capture]) -> _Distributed:
|
|
97
|
+
return _Distributed(
|
|
98
|
+
Template(f"{left} {operator} {right}", captures),
|
|
99
|
+
Template(f"{{dm_z}} {operator} {left} {operator} {right}", {'dm_z': _dm_z, **captures}),
|
|
100
|
+
JBinary.Type.And if operator == "and" else JBinary.Type.Or,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
|
|
83
104
|
_dm_x = capture('dm_x')
|
|
84
105
|
_dm_y = capture('dm_y')
|
|
106
|
+
_dm_xy = {'dm_x': _dm_x, 'dm_y': _dm_y}
|
|
85
107
|
_not_and_pattern = pattern("not ({dm_x} and {dm_y})", dm_x=_dm_x, dm_y=_dm_y)
|
|
86
108
|
_not_or_pattern = pattern("not ({dm_x} or {dm_y})", dm_x=_dm_x, dm_y=_dm_y)
|
|
87
|
-
|
|
88
|
-
|
|
109
|
+
_not_x_or_not_y = _distributed("or", "not {dm_x}", "not {dm_y}", _dm_xy)
|
|
110
|
+
_not_x_and_not_y = _distributed("and", "not {dm_x}", "not {dm_y}", _dm_xy)
|
|
89
111
|
# Partial-negation templates: one operand already negated by operator flip (in→not in)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
112
|
+
_not_x_or_y = _distributed("or", "not {dm_x}", "{dm_y}", _dm_xy)
|
|
113
|
+
_x_or_not_y = _distributed("or", "{dm_x}", "not {dm_y}", _dm_xy)
|
|
114
|
+
_not_x_and_y = _distributed("and", "not {dm_x}", "{dm_y}", _dm_xy)
|
|
115
|
+
_x_and_not_y = _distributed("and", "{dm_x}", "not {dm_y}", _dm_xy)
|
|
94
116
|
# Fused DeMorgan + double-negation: not (not x and not y) -> x or y
|
|
95
117
|
_not_notx_and_noty_pattern = pattern("not (not {dm_x} and not {dm_y})", dm_x=_dm_x, dm_y=_dm_y)
|
|
96
|
-
|
|
118
|
+
_x_or_y = _distributed("or", "{dm_x}", "{dm_y}", _dm_xy)
|
|
97
119
|
_not_notx_or_noty_pattern = pattern("not (not {dm_x} or not {dm_y})", dm_x=_dm_x, dm_y=_dm_y)
|
|
98
|
-
|
|
120
|
+
_x_and_y = _distributed("and", "{dm_x}", "{dm_y}", _dm_xy)
|
|
99
121
|
|
|
100
122
|
# DeMorgan with comparison operators: not (p == q and r == s) -> p != q or r != s
|
|
101
123
|
_dm_p = capture('dm_p')
|
|
@@ -105,8 +127,8 @@ _dm_s = capture('dm_s')
|
|
|
105
127
|
_not_eq_and_eq_pattern = pattern(
|
|
106
128
|
"not ({dm_p} == {dm_q} and {dm_r} == {dm_s})", dm_p=_dm_p, dm_q=_dm_q, dm_r=_dm_r, dm_s=_dm_s
|
|
107
129
|
)
|
|
108
|
-
|
|
109
|
-
"{dm_p} != {dm_q}
|
|
130
|
+
_neq_or_neq = _distributed(
|
|
131
|
+
"or", "{dm_p} != {dm_q}", "{dm_r} != {dm_s}", {'dm_p': _dm_p, 'dm_q': _dm_q, 'dm_r': _dm_r, 'dm_s': _dm_s}
|
|
110
132
|
)
|
|
111
133
|
|
|
112
134
|
def _is_bool_literal(node, expected_source: str) -> bool:
|
|
@@ -299,8 +321,11 @@ class RemoveRedundantBoolean(Recipe):
|
|
|
299
321
|
return Visitor()
|
|
300
322
|
|
|
301
323
|
|
|
302
|
-
|
|
303
|
-
|
|
324
|
+
_Distribution = Tuple[_Distributed, MatchResult]
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def _choose_demorgan(match, truth_value, both_not, left_not, right_not, neither_not) -> _Distribution | None:
|
|
328
|
+
"""Choose a DeMorgan template and its values, folding negations where possible.
|
|
304
329
|
|
|
305
330
|
For each operand, tries to absorb the ``not`` introduced by DeMorgan:
|
|
306
331
|
|
|
@@ -319,19 +344,58 @@ def _apply_demorgan(cursor, match, truth_value, both_not, left_not, right_not, n
|
|
|
319
344
|
y_negated = negated_without_not(dm_y_val, truth_value)
|
|
320
345
|
|
|
321
346
|
if x_negated and y_negated:
|
|
322
|
-
|
|
323
|
-
return neither_not.apply(cursor, values=values)
|
|
347
|
+
return neither_not, MatchResult({'dm_x': x_negated, 'dm_y': y_negated})
|
|
324
348
|
if x_negated:
|
|
325
|
-
|
|
326
|
-
return right_not.apply(cursor, values=values)
|
|
349
|
+
return right_not, MatchResult({'dm_x': x_negated, 'dm_y': dm_y_val})
|
|
327
350
|
if y_negated:
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
351
|
+
return left_not, MatchResult({'dm_x': dm_x_val, 'dm_y': y_negated})
|
|
352
|
+
return both_not, match
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def _negated_chain(unary: Unary, operator: JBinary.Type) -> JBinary | None:
|
|
356
|
+
"""The parenthesized chain of three or more ``operator`` operands that ``unary`` negates, or None."""
|
|
357
|
+
inner = unary.expression
|
|
358
|
+
if isinstance(inner, Parentheses):
|
|
359
|
+
inner = inner.tree
|
|
360
|
+
if isinstance(inner, JBinary) and inner.operator == operator \
|
|
361
|
+
and isinstance(inner.left, JBinary) and inner.left.operator == operator:
|
|
362
|
+
return inner
|
|
363
|
+
return None
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
def _operands(chain: Expression, operator: JBinary.Type) -> List[Expression]:
|
|
367
|
+
"""The operands of ``chain``, a chain of ``operator`` nested to the left."""
|
|
368
|
+
operands = []
|
|
369
|
+
while isinstance(chain, JBinary) and chain.operator == operator:
|
|
370
|
+
operands.append(chain.right)
|
|
371
|
+
chain = chain.left
|
|
372
|
+
return [chain, *operands]
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def _distributes(unary: Unary, written: Unary, made: AbstractSet[UUID], operator: JBinary.Type,
|
|
376
|
+
truth_value: bool) -> bool:
|
|
377
|
+
"""Whether ``unary``'s ``not`` distributes over its ``operator``: never over a chain ``written`` spells, unless
|
|
378
|
+
``made`` holds it, and over a chain a rewrite made only where each operand can be negated."""
|
|
379
|
+
spelled = _negated_chain(written, operator)
|
|
380
|
+
if spelled is not None and spelled.id not in made:
|
|
381
|
+
return False
|
|
382
|
+
chain = _negated_chain(unary, operator)
|
|
383
|
+
return chain is None or truth_value or not any(is_not(operand) for operand in _operands(chain, operator))
|
|
384
|
+
|
|
331
385
|
|
|
386
|
+
def _and_head(made: AbstractSet[UUID], unary: Unary, distributed: _Distributed) -> AbstractSet[UUID]:
|
|
387
|
+
"""``made`` and the left part of the chain ``unary`` negates, which ``distributed`` negates whole."""
|
|
388
|
+
negated = JBinary.Type.And if distributed.operator == JBinary.Type.Or else JBinary.Type.Or
|
|
389
|
+
chain = _negated_chain(unary, negated)
|
|
390
|
+
return made if chain is None else made | {chain.left.id}
|
|
332
391
|
|
|
333
|
-
|
|
334
|
-
|
|
392
|
+
|
|
393
|
+
def _distribution(unary: Unary, cursor: Cursor, written: Unary, made: AbstractSet[UUID]) -> _Distribution | None:
|
|
394
|
+
"""How ``unary``'s ``not`` distributes one level in, or None where it does not.
|
|
395
|
+
|
|
396
|
+
``written`` is ``unary`` as the code spells it, before its operands were rewritten, and ``made`` holds the ids
|
|
397
|
+
of the chains that rewrites made.
|
|
398
|
+
"""
|
|
335
399
|
truth_value = is_read_as_truth_value(cursor)
|
|
336
400
|
|
|
337
401
|
# not (p == q and r == s) -> p != q or r != s
|
|
@@ -340,46 +404,52 @@ def _distribute_not(unary: Unary, cursor: Cursor) -> J:
|
|
|
340
404
|
isinstance(operand, Expression) and is_comparison(operand)
|
|
341
405
|
for operand in (match[k] for k in ('dm_p', 'dm_q', 'dm_r', 'dm_s'))
|
|
342
406
|
):
|
|
343
|
-
if
|
|
344
|
-
return unary
|
|
345
|
-
return _neq_or_neq_template.apply(cursor, values=match) or unary
|
|
407
|
+
return (_neq_or_neq, match) if truth_value else None
|
|
346
408
|
|
|
347
409
|
if truth_value:
|
|
348
410
|
# Fused: not (not x and not y) -> x or y
|
|
349
411
|
match = _not_notx_and_noty_pattern.match(unary, cursor)
|
|
350
412
|
if match:
|
|
351
|
-
return
|
|
413
|
+
return _x_or_y, match
|
|
352
414
|
|
|
353
415
|
# Fused: not (not x or not y) -> x and y
|
|
354
416
|
match = _not_notx_or_noty_pattern.match(unary, cursor)
|
|
355
417
|
if match:
|
|
356
|
-
return
|
|
418
|
+
return _x_and_y, match
|
|
357
419
|
|
|
358
420
|
# not (x and y) -> not x or not y
|
|
359
|
-
#
|
|
360
|
-
#
|
|
421
|
+
# A chain the code spells, as not (a and b and c), is left alone, but one that rewriting an operand
|
|
422
|
+
# made distributes: not (a or not (b and c)) has become not (a or not b or not c) by now.
|
|
361
423
|
match = _not_and_pattern.match(unary, cursor)
|
|
362
|
-
if match:
|
|
363
|
-
|
|
364
|
-
if not (isinstance(dm_x_val, JBinary) and dm_x_val.operator == JBinary.Type.And):
|
|
365
|
-
return _apply_demorgan(
|
|
366
|
-
cursor, match, truth_value, _not_x_or_not_y_template,
|
|
367
|
-
_not_x_or_y_template, _x_or_not_y_template,
|
|
368
|
-
_x_or_y_template,
|
|
369
|
-
) or unary
|
|
424
|
+
if match and _distributes(unary, written, made, JBinary.Type.And, truth_value):
|
|
425
|
+
return _choose_demorgan(match, truth_value, _not_x_or_not_y, _not_x_or_y, _x_or_not_y, _x_or_y)
|
|
370
426
|
|
|
371
427
|
# not (x or y) -> not x and not y
|
|
372
428
|
match = _not_or_pattern.match(unary, cursor)
|
|
373
|
-
if match:
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
429
|
+
if match and _distributes(unary, written, made, JBinary.Type.Or, truth_value):
|
|
430
|
+
return _choose_demorgan(match, truth_value, _not_x_and_not_y, _not_x_and_y, _x_and_not_y, _x_and_y)
|
|
431
|
+
|
|
432
|
+
return None
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
def _ends_chain(cursor: Cursor, operator: JBinary.Type) -> bool:
|
|
436
|
+
"""Whether the value at ``cursor`` is the right operand of an ``and``/``or`` of ``operator``."""
|
|
437
|
+
node, parent = cursor.value, cursor.parent_tree_cursor().value
|
|
438
|
+
return isinstance(node, J) and isinstance(parent, JBinary) and parent.operator == operator \
|
|
439
|
+
and parent.right.id == node.id
|
|
440
|
+
|
|
381
441
|
|
|
382
|
-
|
|
442
|
+
def _respaced(chain: J, binary: JBinary) -> J:
|
|
443
|
+
"""``chain``, written by a template in place of ``binary``, with the spaces and comments ``binary`` had
|
|
444
|
+
around its left operand and its operator."""
|
|
445
|
+
head = chain.left if isinstance(chain, JBinary) else None
|
|
446
|
+
if not isinstance(head, JBinary):
|
|
447
|
+
return chain
|
|
448
|
+
return chain.replace(_left=head.replace(
|
|
449
|
+
_left=head.left.replace(_prefix=binary.left.prefix),
|
|
450
|
+
_operator=binary.padding.operator,
|
|
451
|
+
_right=head.right.replace(_prefix=binary.right.prefix),
|
|
452
|
+
))
|
|
383
453
|
|
|
384
454
|
|
|
385
455
|
@categorize(_Cleanup)
|
|
@@ -423,6 +493,11 @@ class DeMorgan(Recipe):
|
|
|
423
493
|
|
|
424
494
|
def editor(self) -> TreeVisitor[Any, ExecutionContext]:
|
|
425
495
|
class Visitor(PythonVisitor[ExecutionContext]):
|
|
496
|
+
def __init__(self, made: AbstractSet[UUID] = frozenset()):
|
|
497
|
+
super().__init__()
|
|
498
|
+
# The ids of chains that rewrites made, which this visit meets again in what a template wrote.
|
|
499
|
+
self._made = made
|
|
500
|
+
|
|
426
501
|
def visit_unary(
|
|
427
502
|
self, unary: Unary, p: ExecutionContext
|
|
428
503
|
) -> J:
|
|
@@ -431,11 +506,38 @@ class DeMorgan(Recipe):
|
|
|
431
506
|
visited.replace(_prefix=Space.EMPTY)
|
|
432
507
|
):
|
|
433
508
|
return visited
|
|
434
|
-
|
|
435
|
-
|
|
509
|
+
cursor = Cursor(self.cursor.parent, visited)
|
|
510
|
+
distribution = _distribution(visited, cursor, unary, self._made)
|
|
511
|
+
# The `and` holding `x and not (a or b)` rewrites it whole, in visit_binary.
|
|
512
|
+
if distribution is None or _ends_chain(cursor, distribution[0].operator):
|
|
513
|
+
return visited
|
|
514
|
+
distributed, values = distribution
|
|
515
|
+
result = distributed.alone.apply(cursor, values=values)
|
|
516
|
+
if result is None:
|
|
436
517
|
return visited
|
|
437
518
|
# The negations a rewrite creates may distribute in turn.
|
|
438
|
-
|
|
519
|
+
made = _and_head(self._made, visited, distributed)
|
|
520
|
+
return Visitor(made).visit(result, p, self.cursor.parent_or_throw) or result
|
|
521
|
+
|
|
522
|
+
def visit_binary(self, binary: JBinary, p: ExecutionContext) -> J:
|
|
523
|
+
visited = super().visit_binary(binary, p)
|
|
524
|
+
if not isinstance(visited, JBinary) or not isinstance(visited.right, Unary) or has_comments(
|
|
525
|
+
visited.right.replace(_prefix=Space.EMPTY)
|
|
526
|
+
):
|
|
527
|
+
return visited
|
|
528
|
+
cursor = Cursor(self.cursor.parent, visited)
|
|
529
|
+
# Read under the unvisited `and`/`or`, as visit_unary read it before leaving it here.
|
|
530
|
+
written = binary.right if isinstance(binary.right, Unary) else visited.right
|
|
531
|
+
distribution = _distribution(visited.right, Cursor(self.cursor, visited.right), written, self._made)
|
|
532
|
+
if distribution is None or distribution[0].operator != visited.operator:
|
|
533
|
+
return visited
|
|
534
|
+
distributed, values = distribution
|
|
535
|
+
result = distributed.chained.apply(cursor, values={**values.as_dict(), 'dm_z': visited.left})
|
|
536
|
+
if result is None:
|
|
537
|
+
return visited
|
|
538
|
+
result = _respaced(result, visited)
|
|
539
|
+
made = _and_head(self._made, visited.right, distributed)
|
|
540
|
+
return Visitor(made).visit(result, p, self.cursor.parent_or_throw) or result
|
|
439
541
|
|
|
440
542
|
return Visitor()
|
|
441
543
|
|
|
@@ -9,6 +9,7 @@ Both fire only where the receiver's pandas type resolves.
|
|
|
9
9
|
See: https://pandas.pydata.org/docs/whatsnew/v1.4.0.html#deprecations
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
|
+
import dataclasses
|
|
12
13
|
from typing import Any, List
|
|
13
14
|
|
|
14
15
|
from rewrite import ExecutionContext, Preconditions, Recipe, TreeVisitor
|
|
@@ -103,12 +104,19 @@ class DataframeAppendToConcat(Recipe):
|
|
|
103
104
|
):
|
|
104
105
|
return m
|
|
105
106
|
try:
|
|
106
|
-
|
|
107
|
+
concat = _concat_template.apply(
|
|
107
108
|
self.cursor, visitor=self, values={'df': select, 'x': args[0]}
|
|
108
|
-
)
|
|
109
|
+
)
|
|
109
110
|
except ValueError:
|
|
110
111
|
# The template refuses a file where `pd` is bound to something else.
|
|
111
112
|
return m
|
|
113
|
+
if not isinstance(concat, MethodInvocation):
|
|
114
|
+
return concat or m
|
|
115
|
+
# Typed as the receiver, so that an `append` on this result or taking it is migrated too.
|
|
116
|
+
method_type = concat.method_type
|
|
117
|
+
if method_type is None:
|
|
118
|
+
return concat
|
|
119
|
+
return concat.replace(_method_type=dataclasses.replace(method_type, _return_type=select.type))
|
|
112
120
|
|
|
113
121
|
# `append` does not resolve under pandas 2, so the gate names the receiver.
|
|
114
122
|
return Preconditions.check(uses_type(_DATAFRAME), Visitor())
|
openrewrite_migrate_python-0.20.0/src/openrewrite_code_quality_python/codequality/_grouping.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Grouping an ``and`` or ``or`` chain the way the parser groups it."""
|
|
2
|
+
|
|
3
|
+
from rewrite.java.support_types import Space
|
|
4
|
+
from rewrite.java.tree import Binary
|
|
5
|
+
from rewrite.utils import random_id
|
|
6
|
+
|
|
7
|
+
from openrewrite_code_quality_python.codequality._trivia import concat
|
|
8
|
+
|
|
9
|
+
_CHAINED = (Binary.Type.And, Binary.Type.Or)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def grouped_left(binary: Binary) -> Binary:
|
|
13
|
+
"""``binary`` with a chain of its own operator on its right, unparenthesized, regrouped to the left.
|
|
14
|
+
|
|
15
|
+
``a and (b and c)`` without the parentheses prints as ``a and b and c``, which the parser
|
|
16
|
+
groups as ``(a and b) and c``. Both evaluate the same, but a recipe matching the tree sees
|
|
17
|
+
other operands in each.
|
|
18
|
+
"""
|
|
19
|
+
right = binary.right
|
|
20
|
+
if binary.operator not in _CHAINED or not isinstance(right, Binary) or right.operator != binary.operator:
|
|
21
|
+
return binary
|
|
22
|
+
left = binary.replace(
|
|
23
|
+
_id=random_id(),
|
|
24
|
+
_prefix=Space.EMPTY,
|
|
25
|
+
_right=right.left.replace(_prefix=concat(right.prefix, right.left.prefix)),
|
|
26
|
+
)
|
|
27
|
+
return grouped_left(binary.replace(
|
|
28
|
+
_left=grouped_left(left),
|
|
29
|
+
_operator=right.padding.operator,
|
|
30
|
+
_right=right.right,
|
|
31
|
+
))
|
|
@@ -28,6 +28,7 @@ from rewrite.java.tree import (
|
|
|
28
28
|
)
|
|
29
29
|
from rewrite.utils import random_id
|
|
30
30
|
|
|
31
|
+
from openrewrite_code_quality_python.codequality._grouping import grouped_left
|
|
31
32
|
from openrewrite_code_quality_python.codequality._reindent import (
|
|
32
33
|
line_indent,
|
|
33
34
|
reindent,
|
|
@@ -190,8 +191,12 @@ class CollapsibleIfStatements(Recipe):
|
|
|
190
191
|
),
|
|
191
192
|
_type=None,
|
|
192
193
|
)
|
|
193
|
-
|
|
194
|
+
# An `and` chain in the inner condition continues the merged one, nested to the left
|
|
195
|
+
# as the parser nests `a and b and c`, so only its last operand is left to parenthesize.
|
|
196
|
+
combined = grouped_left(combined.replace(
|
|
194
197
|
_left=maybe_parenthesize(combined, combined.left.id, combined.left),
|
|
198
|
+
))
|
|
199
|
+
combined = combined.replace(
|
|
195
200
|
_right=maybe_parenthesize(combined, combined.right.id, combined.right),
|
|
196
201
|
)
|
|
197
202
|
|
|
@@ -27,6 +27,7 @@ from rewrite.java.tree import (
|
|
|
27
27
|
If,
|
|
28
28
|
Statement,
|
|
29
29
|
)
|
|
30
|
+
from openrewrite_code_quality_python.codequality._grouping import grouped_left
|
|
30
31
|
from openrewrite_code_quality_python.codequality._semantically_equal import SemanticallyEqual
|
|
31
32
|
from rewrite.utils import random_id
|
|
32
33
|
|
|
@@ -180,8 +181,12 @@ def _merge_conditions(first: If, second: If) -> If:
|
|
|
180
181
|
_right=_or_operand(second_cond, Space.SINGLE_SPACE),
|
|
181
182
|
_type=None,
|
|
182
183
|
)
|
|
183
|
-
|
|
184
|
+
# An `or` chain in the second condition continues the merged one, nested to the left as the
|
|
185
|
+
# parser nests `a or b or c`, so only its last operand is left to parenthesize.
|
|
186
|
+
combined = grouped_left(combined.replace(
|
|
184
187
|
_left=maybe_parenthesize(combined, combined.left.id, combined.left),
|
|
188
|
+
))
|
|
189
|
+
combined = combined.replace(
|
|
185
190
|
_right=maybe_parenthesize(combined, combined.right.id, combined.right),
|
|
186
191
|
)
|
|
187
192
|
|
|
@@ -19,16 +19,22 @@ def rename_methods(
|
|
|
19
19
|
method gives it. The patterns match overrides, since a call through a subclass to a member
|
|
20
20
|
typeshed no longer declares resolves to the subclass.
|
|
21
21
|
"""
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
# Where Python still declares `old` as an alias, `old = new`, the call resolves to `new`.
|
|
23
|
+
patterns = {
|
|
24
|
+
old: [f"{declaring_type} {old}(..)", f"{declaring_type} {new}(..)"] for old, new in renames.items()
|
|
25
|
+
}
|
|
26
|
+
calls = {
|
|
27
|
+
old: [MethodMatcher.create(pattern, match_overrides=True) for pattern in alternatives]
|
|
28
|
+
for old, alternatives in patterns.items()
|
|
29
|
+
}
|
|
24
30
|
|
|
25
31
|
class Visitor(PythonVisitor[ExecutionContext]):
|
|
26
32
|
def visit_method_invocation(self, method: MethodInvocation, p: ExecutionContext) -> J:
|
|
27
33
|
m = super().visit_method_invocation(method, p)
|
|
28
34
|
if not isinstance(m, MethodInvocation):
|
|
29
35
|
return m
|
|
30
|
-
|
|
31
|
-
if
|
|
36
|
+
matchers = calls.get(m.name.simple_name, [])
|
|
37
|
+
if not any(matcher.matches(m, cursor=self.cursor) for matcher in matchers):
|
|
32
38
|
return m
|
|
33
39
|
# The old method type names the old method, which no longer describes the call.
|
|
34
40
|
m = m.replace(
|
|
@@ -41,7 +47,9 @@ def rename_methods(
|
|
|
41
47
|
]
|
|
42
48
|
return m.padding.replace(_arguments=arguments.padding.replace(elements=elements))
|
|
43
49
|
|
|
44
|
-
gates = [
|
|
50
|
+
gates = [
|
|
51
|
+
uses_method(pattern, match_overrides=True) for alternatives in patterns.values() for pattern in alternatives
|
|
52
|
+
]
|
|
45
53
|
return Preconditions.check(gates[0] if len(gates) == 1 else Preconditions.or_(*gates), Visitor())
|
|
46
54
|
|
|
47
55
|
|