From c1b292a0dce4b6f4b48ac7d8ac111ab15702c60f Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Tue, 23 Jul 2024 18:24:20 +0100 Subject: [PATCH] Refactor NPY201 (#12479) --- .../numpy/rules/numpy_2_0_deprecation.rs | 1086 ++++++++--------- 1 file changed, 543 insertions(+), 543 deletions(-) diff --git a/crates/ruff_linter/src/rules/numpy/rules/numpy_2_0_deprecation.rs b/crates/ruff_linter/src/rules/numpy/rules/numpy_2_0_deprecation.rs index 8ddb4b320e243..eeded38dde932 100644 --- a/crates/ruff_linter/src/rules/numpy/rules/numpy_2_0_deprecation.rs +++ b/crates/ruff_linter/src/rules/numpy/rules/numpy_2_0_deprecation.rs @@ -151,553 +151,553 @@ enum Compatibility { /// The change is breaking in NumPy 2.0. Breaking, } + /// NPY201 pub(crate) fn numpy_2_0_deprecation(checker: &mut Checker, expr: &Expr) { - if !checker.semantic().seen_module(Modules::NUMPY) { + let semantic = checker.semantic(); + + if !semantic.seen_module(Modules::NUMPY) { return; } - let maybe_replacement = checker - .semantic() - .resolve_qualified_name(expr) - .and_then(|qualified_name| match qualified_name.segments() { - // NumPy's main namespace np.* members removed in 2.0 - ["numpy", "add_docstring"] => Some(Replacement { - existing: "add_docstring", - details: Details::AutoImport { - path: "numpy.lib", - name: "add_docstring", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "add_newdoc"] => Some(Replacement { - existing: "add_newdoc", - details: Details::AutoImport { - path: "numpy.lib", - name: "add_newdoc", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "add_newdoc_ufunc"] => Some(Replacement { - existing: "add_newdoc_ufunc", - details: Details::Manual { - guideline: Some("`add_newdoc_ufunc` is an internal function."), - }, - }), - ["numpy", "alltrue"] => Some(Replacement { - existing: "alltrue", - details: Details::AutoImport { - path: "numpy", - name: "all", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "asfarray"] => Some(Replacement { - existing: "asfarray", - details: Details::Manual { - guideline: Some("Use `np.asarray` with a `float` dtype instead."), - }, - }), - ["numpy", "byte_bounds"] => Some(Replacement { - existing: "byte_bounds", - details: Details::AutoImport { - path: "numpy.lib.array_utils", - name: "byte_bounds", - compatibility: Compatibility::Breaking, - }, - }), - ["numpy", "cast"] => Some(Replacement { - existing: "cast", - details: Details::Manual { - guideline: Some("Use `np.asarray(arr, dtype=dtype)` instead."), - }, - }), - ["numpy", "cfloat"] => Some(Replacement { - existing: "cfloat", - details: Details::AutoImport { - path: "numpy", - name: "complex128", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "clongfloat"] => Some(Replacement { - existing: "clongfloat", - details: Details::AutoImport { - path: "numpy", - name: "clongdouble", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "compat"] => Some(Replacement { - existing: "compat", - details: Details::Manual { - guideline: Some("Python 2 is no longer supported."), - }, - }), - ["numpy", "complex_"] => Some(Replacement { - existing: "complex_", - details: Details::AutoImport { - path: "numpy", - name: "complex128", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "cumproduct"] => Some(Replacement { - existing: "cumproduct", - details: Details::AutoImport { - path: "numpy", - name: "cumprod", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "DataSource"] => Some(Replacement { - existing: "DataSource", - details: Details::AutoImport { - path: "numpy.lib.npyio", - name: "DataSource", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "deprecate"] => Some(Replacement { - existing: "deprecate", - details: Details::Manual { - guideline: Some("Emit `DeprecationWarning` with `warnings.warn` directly, or use `typing.deprecated`."), - }, - }), - ["numpy", "deprecate_with_doc"] => Some(Replacement { - existing: "deprecate_with_doc", - details: Details::Manual { - guideline: Some("Emit `DeprecationWarning` with `warnings.warn` directly, or use `typing.deprecated`."), - }, - }), - ["numpy", "disp"] => Some(Replacement { - existing: "disp", - details: Details::Manual { - guideline: Some("Use a dedicated print function instead."), - }, - }), - ["numpy", "fastCopyAndTranspose"] => Some(Replacement { - existing: "fastCopyAndTranspose", - details: Details::Manual { - guideline: Some("Use `arr.T.copy()` instead."), - }, - }), - ["numpy", "find_common_type"] => Some(Replacement { - existing: "find_common_type", - details: Details::Manual { - guideline: Some("Use `numpy.promote_types` or `numpy.result_type` instead. To achieve semantics for the `scalar_types` argument, use `numpy.result_type` and pass the Python values `0`, `0.0`, or `0j`."), - }, - }), - ["numpy", "get_array_wrap"] => Some(Replacement { - existing: "get_array_wrap", - details: Details::Manual { - guideline: None, - }, - }), - ["numpy", "float_"] => Some(Replacement { - existing: "float_", - details: Details::AutoImport { - path: "numpy", - name: "float64", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "geterrobj"] => Some(Replacement { - existing: "geterrobj", - details: Details::Manual { - guideline: Some("Use the `np.errstate` context manager instead."), - }, - }), - ["numpy", "in1d"] => Some(Replacement { - existing: "in1d", - details: Details::AutoImport { - path: "numpy", - name: "isin", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "INF"] => Some(Replacement { - existing: "INF", - details: Details::AutoImport { - path: "numpy", - name: "inf", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "Inf"] => Some(Replacement { - existing: "Inf", - details: Details::AutoImport { - path: "numpy", - name: "inf", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "Infinity"] => Some(Replacement { - existing: "Infinity", - details: Details::AutoImport { - path: "numpy", - name: "inf", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "infty"] => Some(Replacement { - existing: "infty", - details: Details::AutoImport { - path: "numpy", - name: "inf", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "issctype"] => Some(Replacement { - existing: "issctype", - details: Details::Manual { - guideline: None, - }, - }), - ["numpy", "issubclass_"] => Some(Replacement { - existing: "issubclass_", - details: Details::AutoPurePython { - python_expr: "issubclass", - }, - }), - ["numpy", "issubsctype"] => Some(Replacement { - existing: "issubsctype", - details: Details::AutoImport { - path: "numpy", - name: "issubdtype", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "mat"] => Some(Replacement { - existing: "mat", - details: Details::AutoImport { - path: "numpy", - name: "asmatrix", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "maximum_sctype"] => Some(Replacement { - existing: "maximum_sctype", - details: Details::Manual { - guideline: None, - }, - }), - ["numpy", existing @ ("NaN" | "NAN")] => Some(Replacement { - existing, - details: Details::AutoImport { - path: "numpy", - name: "nan", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "nbytes"] => Some(Replacement { - existing: "nbytes", - details: Details::Manual { - guideline: Some("Use `np.dtype().itemsize` instead."), - }, - }), - ["numpy", "NINF"] => Some(Replacement { - existing: "NINF", - details: Details::AutoPurePython { - python_expr: "-np.inf", - }, - }), - ["numpy", "NZERO"] => Some(Replacement { - existing: "NZERO", - details: Details::AutoPurePython { - python_expr: "-0.0", - }, - }), - ["numpy", "longcomplex"] => Some(Replacement { - existing: "longcomplex", - details: Details::AutoImport { - path: "numpy", - name: "clongdouble", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "longfloat"] => Some(Replacement { - existing: "longfloat", - details: Details::AutoImport { - path: "numpy", - name: "longdouble", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "lookfor"] => Some(Replacement { - existing: "lookfor", - details: Details::Manual { - guideline: Some("Search NumPy’s documentation directly."), - }, - }), - ["numpy", "obj2sctype"] => Some(Replacement { - existing: "obj2sctype", - details: Details::Manual { - guideline: None, - }, - }), - ["numpy", "PINF"] => Some(Replacement { - existing: "PINF", - details: Details::AutoImport { - path: "numpy", - name: "inf", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "product"] => Some(Replacement { - existing: "product", - details: Details::AutoImport { - path: "numpy", - name: "prod", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "PZERO"] => Some(Replacement { - existing: "PZERO", - details: Details::AutoPurePython { python_expr: "0.0" }, - }), - ["numpy", "recfromcsv"] => Some(Replacement { - existing: "recfromcsv", - details: Details::Manual { - guideline: Some("Use `np.genfromtxt` with comma delimiter instead."), - }, - }), - ["numpy", "recfromtxt"] => Some(Replacement { - existing: "recfromtxt", - details: Details::Manual { - guideline: Some("Use `np.genfromtxt` instead."), - }, - }), - ["numpy", "round_"] => Some(Replacement { - existing: "round_", - details: Details::AutoImport { - path: "numpy", - name: "round", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "safe_eval"] => Some(Replacement { - existing: "safe_eval", - details: Details::AutoImport { - path: "ast", - name: "literal_eval", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "sctype2char"] => Some(Replacement { - existing: "sctype2char", - details: Details::Manual { - guideline: None, - }, - }), - ["numpy", "sctypes"] => Some(Replacement { - existing: "sctypes", - details: Details::Manual { - guideline: None, - }, - }), - ["numpy", "seterrobj"] => Some(Replacement { - existing: "seterrobj", - details: Details::Manual { - guideline: Some("Use the `np.errstate` context manager instead."), - }, - }), - ["numpy", "set_string_function"] => Some(Replacement { - existing: "set_string_function", - details: Details::Manual { - guideline: Some("Use `np.set_printoptions` for custom printing of NumPy objects."), - }, - }), - ["numpy", "singlecomplex"] => Some(Replacement { - existing: "singlecomplex", - details: Details::AutoImport { - path: "numpy", - name: "complex64", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "string_"] => Some(Replacement { - existing: "string_", - details: Details::AutoImport { - path: "numpy", - name: "bytes_", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "sometrue"] => Some(Replacement { - existing: "sometrue", - details: Details::AutoImport { - path: "numpy", - name: "any", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "source"] => Some(Replacement { - existing: "source", - details: Details::AutoImport { - path: "inspect", - name: "getsource", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "tracemalloc_domain"] => Some(Replacement { - existing: "tracemalloc_domain", - details: Details::AutoImport { - path: "numpy.lib", - name: "tracemalloc_domain", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "trapz"] => Some(Replacement { - existing: "trapz", - details: Details::AutoImport { - path: "numpy", - name: "trapezoid", - compatibility: Compatibility::Breaking, - }, - }), - ["numpy", "unicode_"] => Some(Replacement { - existing: "unicode_", - details: Details::AutoImport { - path: "numpy", - name: "str_", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "who"] => Some(Replacement { - existing: "who", - details: Details::Manual { - guideline: Some("Use an IDE variable explorer or `locals()` instead."), - }, - }), - ["numpy", "row_stack"] => Some(Replacement { - existing: "row_stack", - details: Details::AutoImport { - path: "numpy", - name: "vstack", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "AxisError"] => Some(Replacement { - existing: "AxisError", - details: Details::AutoImport { - path: "numpy.exceptions", - name: "AxisError", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "ComplexWarning"] => Some(Replacement { - existing: "ComplexWarning", - details: Details::AutoImport { - path: "numpy.exceptions", - name: "ComplexWarning", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "DTypePromotionError"] => Some(Replacement { - existing: "DTypePromotionError", - details: Details::AutoImport { - path: "numpy.exceptions", - name: "DTypePromotionError", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "ModuleDeprecationWarning"] => Some(Replacement { - existing: "ModuleDeprecationWarning", - details: Details::AutoImport { - path: "numpy.exceptions", - name: "ModuleDeprecationWarning", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "RankWarning"] => Some(Replacement { - existing: "RankWarning", - details: Details::AutoImport { - path: "numpy.exceptions", - name: "RankWarning", - compatibility: Compatibility::Breaking, - }, - }), - ["numpy", "TooHardError"] => Some(Replacement { - existing: "TooHardError", - details: Details::AutoImport { - path: "numpy.exceptions", - name: "TooHardError", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "VisibleDeprecationWarning"] => Some(Replacement { - existing: "VisibleDeprecationWarning", - details: Details::AutoImport { - path: "numpy.exceptions", - name: "VisibleDeprecationWarning", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "compare_chararrays"] => Some(Replacement { - existing: "compare_chararrays", - details: Details::AutoImport { - path: "numpy.char", - name: "compare_chararrays", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "chararray"] => Some(Replacement { - existing: "chararray", - details: Details::AutoImport { - path: "numpy.char", - name: "chararray", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - ["numpy", "format_parser"] => Some(Replacement { - existing: "format_parser", - details: Details::AutoImport { - path: "numpy.rec", - name: "format_parser", - compatibility: Compatibility::BackwardsCompatible, - }, - }), - _ => None, - }); + let Some(qualified_name) = semantic.resolve_qualified_name(expr) else { + return; + }; - if let Some(replacement) = maybe_replacement { - let mut diagnostic = Diagnostic::new( - Numpy2Deprecation { - existing: replacement.existing.to_string(), - migration_guide: replacement.details.guideline(), - code_action: replacement.details.code_action(), - }, - expr.range(), - ); - match replacement.details { - Details::AutoImport { - path, - name, - compatibility, - } => { - diagnostic.try_set_fix(|| { - let (import_edit, binding) = checker.importer().get_or_import_symbol( - &ImportRequest::import_from(path, name), - expr.start(), - checker.semantic(), - )?; - let replacement_edit = Edit::range_replacement(binding, expr.range()); - Ok(match compatibility { - Compatibility::BackwardsCompatible => { - Fix::safe_edits(import_edit, [replacement_edit]) - } - Compatibility::Breaking => { - Fix::unsafe_edits(import_edit, [replacement_edit]) - } - }) - }); - } - Details::AutoPurePython { python_expr } => diagnostic.set_fix(Fix::safe_edit( - Edit::range_replacement(python_expr.to_string(), expr.range()), - )), - Details::Manual { guideline: _ } => {} - }; - checker.diagnostics.push(diagnostic); - } + let replacement = match qualified_name.segments() { + // NumPy's main namespace np.* members removed in 2.0 + ["numpy", "add_docstring"] => Replacement { + existing: "add_docstring", + details: Details::AutoImport { + path: "numpy.lib", + name: "add_docstring", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "add_newdoc"] => Replacement { + existing: "add_newdoc", + details: Details::AutoImport { + path: "numpy.lib", + name: "add_newdoc", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "add_newdoc_ufunc"] => Replacement { + existing: "add_newdoc_ufunc", + details: Details::Manual { + guideline: Some("`add_newdoc_ufunc` is an internal function."), + }, + }, + ["numpy", "alltrue"] => Replacement { + existing: "alltrue", + details: Details::AutoImport { + path: "numpy", + name: "all", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "asfarray"] => Replacement { + existing: "asfarray", + details: Details::Manual { + guideline: Some("Use `np.asarray` with a `float` dtype instead."), + }, + }, + ["numpy", "byte_bounds"] => Replacement { + existing: "byte_bounds", + details: Details::AutoImport { + path: "numpy.lib.array_utils", + name: "byte_bounds", + compatibility: Compatibility::Breaking, + }, + }, + ["numpy", "cast"] => Replacement { + existing: "cast", + details: Details::Manual { + guideline: Some("Use `np.asarray(arr, dtype=dtype)` instead."), + }, + }, + ["numpy", "cfloat"] => Replacement { + existing: "cfloat", + details: Details::AutoImport { + path: "numpy", + name: "complex128", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "clongfloat"] => Replacement { + existing: "clongfloat", + details: Details::AutoImport { + path: "numpy", + name: "clongdouble", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "compat"] => Replacement { + existing: "compat", + details: Details::Manual { + guideline: Some("Python 2 is no longer supported."), + }, + }, + ["numpy", "complex_"] => Replacement { + existing: "complex_", + details: Details::AutoImport { + path: "numpy", + name: "complex128", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "cumproduct"] => Replacement { + existing: "cumproduct", + details: Details::AutoImport { + path: "numpy", + name: "cumprod", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "DataSource"] => Replacement { + existing: "DataSource", + details: Details::AutoImport { + path: "numpy.lib.npyio", + name: "DataSource", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "deprecate"] => Replacement { + existing: "deprecate", + details: Details::Manual { + guideline: Some("Emit `DeprecationWarning` with `warnings.warn` directly, or use `typing.deprecated`."), + }, + }, + ["numpy", "deprecate_with_doc"] => Replacement { + existing: "deprecate_with_doc", + details: Details::Manual { + guideline: Some("Emit `DeprecationWarning` with `warnings.warn` directly, or use `typing.deprecated`."), + }, + }, + ["numpy", "disp"] => Replacement { + existing: "disp", + details: Details::Manual { + guideline: Some("Use a dedicated print function instead."), + }, + }, + ["numpy", "fastCopyAndTranspose"] => Replacement { + existing: "fastCopyAndTranspose", + details: Details::Manual { + guideline: Some("Use `arr.T.copy()` instead."), + }, + }, + ["numpy", "find_common_type"] => Replacement { + existing: "find_common_type", + details: Details::Manual { + guideline: Some("Use `numpy.promote_types` or `numpy.result_type` instead. To achieve semantics for the `scalar_types` argument, use `numpy.result_type` and pass the Python values `0`, `0.0`, or `0j`."), + }, + }, + ["numpy", "get_array_wrap"] => Replacement { + existing: "get_array_wrap", + details: Details::Manual { + guideline: None, + }, + }, + ["numpy", "float_"] => Replacement { + existing: "float_", + details: Details::AutoImport { + path: "numpy", + name: "float64", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "geterrobj"] => Replacement { + existing: "geterrobj", + details: Details::Manual { + guideline: Some("Use the `np.errstate` context manager instead."), + }, + }, + ["numpy", "in1d"] => Replacement { + existing: "in1d", + details: Details::AutoImport { + path: "numpy", + name: "isin", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "INF"] => Replacement { + existing: "INF", + details: Details::AutoImport { + path: "numpy", + name: "inf", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "Inf"] => Replacement { + existing: "Inf", + details: Details::AutoImport { + path: "numpy", + name: "inf", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "Infinity"] => Replacement { + existing: "Infinity", + details: Details::AutoImport { + path: "numpy", + name: "inf", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "infty"] => Replacement { + existing: "infty", + details: Details::AutoImport { + path: "numpy", + name: "inf", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "issctype"] => Replacement { + existing: "issctype", + details: Details::Manual { + guideline: None, + }, + }, + ["numpy", "issubclass_"] => Replacement { + existing: "issubclass_", + details: Details::AutoPurePython { + python_expr: "issubclass", + }, + }, + ["numpy", "issubsctype"] => Replacement { + existing: "issubsctype", + details: Details::AutoImport { + path: "numpy", + name: "issubdtype", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "mat"] => Replacement { + existing: "mat", + details: Details::AutoImport { + path: "numpy", + name: "asmatrix", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "maximum_sctype"] => Replacement { + existing: "maximum_sctype", + details: Details::Manual { + guideline: None, + }, + }, + ["numpy", existing @ ("NaN" | "NAN")] => Replacement { + existing, + details: Details::AutoImport { + path: "numpy", + name: "nan", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "nbytes"] => Replacement { + existing: "nbytes", + details: Details::Manual { + guideline: Some("Use `np.dtype().itemsize` instead."), + }, + }, + ["numpy", "NINF"] => Replacement { + existing: "NINF", + details: Details::AutoPurePython { + python_expr: "-np.inf", + }, + }, + ["numpy", "NZERO"] => Replacement { + existing: "NZERO", + details: Details::AutoPurePython { + python_expr: "-0.0", + }, + }, + ["numpy", "longcomplex"] => Replacement { + existing: "longcomplex", + details: Details::AutoImport { + path: "numpy", + name: "clongdouble", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "longfloat"] => Replacement { + existing: "longfloat", + details: Details::AutoImport { + path: "numpy", + name: "longdouble", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "lookfor"] => Replacement { + existing: "lookfor", + details: Details::Manual { + guideline: Some("Search NumPy’s documentation directly."), + }, + }, + ["numpy", "obj2sctype"] => Replacement { + existing: "obj2sctype", + details: Details::Manual { + guideline: None, + }, + }, + ["numpy", "PINF"] => Replacement { + existing: "PINF", + details: Details::AutoImport { + path: "numpy", + name: "inf", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "product"] => Replacement { + existing: "product", + details: Details::AutoImport { + path: "numpy", + name: "prod", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "PZERO"] => Replacement { + existing: "PZERO", + details: Details::AutoPurePython { python_expr: "0.0" }, + }, + ["numpy", "recfromcsv"] => Replacement { + existing: "recfromcsv", + details: Details::Manual { + guideline: Some("Use `np.genfromtxt` with comma delimiter instead."), + }, + }, + ["numpy", "recfromtxt"] => Replacement { + existing: "recfromtxt", + details: Details::Manual { + guideline: Some("Use `np.genfromtxt` instead."), + }, + }, + ["numpy", "round_"] => Replacement { + existing: "round_", + details: Details::AutoImport { + path: "numpy", + name: "round", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "safe_eval"] => Replacement { + existing: "safe_eval", + details: Details::AutoImport { + path: "ast", + name: "literal_eval", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "sctype2char"] => Replacement { + existing: "sctype2char", + details: Details::Manual { + guideline: None, + }, + }, + ["numpy", "sctypes"] => Replacement { + existing: "sctypes", + details: Details::Manual { + guideline: None, + }, + }, + ["numpy", "seterrobj"] => Replacement { + existing: "seterrobj", + details: Details::Manual { + guideline: Some("Use the `np.errstate` context manager instead."), + }, + }, + ["numpy", "set_string_function"] => Replacement { + existing: "set_string_function", + details: Details::Manual { + guideline: Some("Use `np.set_printoptions` for custom printing of NumPy objects."), + }, + }, + ["numpy", "singlecomplex"] => Replacement { + existing: "singlecomplex", + details: Details::AutoImport { + path: "numpy", + name: "complex64", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "string_"] => Replacement { + existing: "string_", + details: Details::AutoImport { + path: "numpy", + name: "bytes_", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "sometrue"] => Replacement { + existing: "sometrue", + details: Details::AutoImport { + path: "numpy", + name: "any", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "source"] => Replacement { + existing: "source", + details: Details::AutoImport { + path: "inspect", + name: "getsource", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "tracemalloc_domain"] => Replacement { + existing: "tracemalloc_domain", + details: Details::AutoImport { + path: "numpy.lib", + name: "tracemalloc_domain", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "trapz"] => Replacement { + existing: "trapz", + details: Details::AutoImport { + path: "numpy", + name: "trapezoid", + compatibility: Compatibility::Breaking, + }, + }, + ["numpy", "unicode_"] => Replacement { + existing: "unicode_", + details: Details::AutoImport { + path: "numpy", + name: "str_", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "who"] => Replacement { + existing: "who", + details: Details::Manual { + guideline: Some("Use an IDE variable explorer or `locals()` instead."), + }, + }, + ["numpy", "row_stack"] => Replacement { + existing: "row_stack", + details: Details::AutoImport { + path: "numpy", + name: "vstack", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "AxisError"] => Replacement { + existing: "AxisError", + details: Details::AutoImport { + path: "numpy.exceptions", + name: "AxisError", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "ComplexWarning"] => Replacement { + existing: "ComplexWarning", + details: Details::AutoImport { + path: "numpy.exceptions", + name: "ComplexWarning", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "DTypePromotionError"] => Replacement { + existing: "DTypePromotionError", + details: Details::AutoImport { + path: "numpy.exceptions", + name: "DTypePromotionError", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "ModuleDeprecationWarning"] => Replacement { + existing: "ModuleDeprecationWarning", + details: Details::AutoImport { + path: "numpy.exceptions", + name: "ModuleDeprecationWarning", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "RankWarning"] => Replacement { + existing: "RankWarning", + details: Details::AutoImport { + path: "numpy.exceptions", + name: "RankWarning", + compatibility: Compatibility::Breaking, + }, + }, + ["numpy", "TooHardError"] => Replacement { + existing: "TooHardError", + details: Details::AutoImport { + path: "numpy.exceptions", + name: "TooHardError", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "VisibleDeprecationWarning"] => Replacement { + existing: "VisibleDeprecationWarning", + details: Details::AutoImport { + path: "numpy.exceptions", + name: "VisibleDeprecationWarning", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "compare_chararrays"] => Replacement { + existing: "compare_chararrays", + details: Details::AutoImport { + path: "numpy.char", + name: "compare_chararrays", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "chararray"] => Replacement { + existing: "chararray", + details: Details::AutoImport { + path: "numpy.char", + name: "chararray", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + ["numpy", "format_parser"] => Replacement { + existing: "format_parser", + details: Details::AutoImport { + path: "numpy.rec", + name: "format_parser", + compatibility: Compatibility::BackwardsCompatible, + }, + }, + _ => return, + }; + + let mut diagnostic = Diagnostic::new( + Numpy2Deprecation { + existing: replacement.existing.to_string(), + migration_guide: replacement.details.guideline(), + code_action: replacement.details.code_action(), + }, + expr.range(), + ); + match replacement.details { + Details::AutoImport { + path, + name, + compatibility, + } => { + diagnostic.try_set_fix(|| { + let (import_edit, binding) = checker.importer().get_or_import_symbol( + &ImportRequest::import_from(path, name), + expr.start(), + checker.semantic(), + )?; + let replacement_edit = Edit::range_replacement(binding, expr.range()); + Ok(match compatibility { + Compatibility::BackwardsCompatible => { + Fix::safe_edits(import_edit, [replacement_edit]) + } + Compatibility::Breaking => Fix::unsafe_edits(import_edit, [replacement_edit]), + }) + }); + } + Details::AutoPurePython { python_expr } => diagnostic.set_fix(Fix::safe_edit( + Edit::range_replacement(python_expr.to_string(), expr.range()), + )), + Details::Manual { guideline: _ } => {} + }; + checker.diagnostics.push(diagnostic); }