From 2da7a38a58c2a7526c8cf474c60342066f05485f Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Wed, 11 Jun 2025 16:20:00 +0200 Subject: [PATCH 1/2] Drop the brain for nose --- ChangeLog | 4 ++ astroid/brain/brain_nose.py | 79 ------------------------------------- astroid/brain/helpers.py | 2 - pyproject.toml | 1 - requirements_full.txt | 1 - tests/brain/test_nose.py | 45 --------------------- 6 files changed, 4 insertions(+), 128 deletions(-) delete mode 100644 astroid/brain/brain_nose.py delete mode 100644 tests/brain/test_nose.py diff --git a/ChangeLog b/ChangeLog index d8fdfd63e2..cce14ee90e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -42,6 +42,10 @@ Release date: TBA Closes #2608 +* The brain for nose was dropped. nose has been deprecated for 10 years and the brain required some maintenance. + + Refs #2765 + What's New in astroid 3.3.11? ============================= Release date: TBA diff --git a/astroid/brain/brain_nose.py b/astroid/brain/brain_nose.py deleted file mode 100644 index b194414d2a..0000000000 --- a/astroid/brain/brain_nose.py +++ /dev/null @@ -1,79 +0,0 @@ -# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html -# For details: https://github.com/pylint-dev/astroid/blob/main/LICENSE -# Copyright (c) https://github.com/pylint-dev/astroid/blob/main/CONTRIBUTORS.txt - -"""Hooks for nose library.""" - -import re -import textwrap - -from astroid.bases import BoundMethod -from astroid.brain.helpers import register_module_extender -from astroid.builder import AstroidBuilder -from astroid.exceptions import InferenceError -from astroid.manager import AstroidManager -from astroid.nodes import List, Module - -CAPITALS = re.compile("([A-Z])") - - -def _pep8(name, caps=CAPITALS): - return caps.sub(lambda m: "_" + m.groups()[0].lower(), name) - - -def _nose_tools_functions(): - """Get an iterator of names and bound methods.""" - module = AstroidBuilder(AstroidManager()).string_build( - textwrap.dedent( - """ - import unittest - - class Test(unittest.TestCase): - pass - a = Test() - """ - ) - ) - try: - case = next(module["a"].infer()) - except (InferenceError, StopIteration): - return - for method in case.methods(): - if method.name.startswith("assert") and "_" not in method.name: - pep8_name = _pep8(method.name) - yield pep8_name, BoundMethod(method, case) - if method.name == "assertEqual": - # nose also exports assert_equals. - yield "assert_equals", BoundMethod(method, case) - - -def _nose_tools_transform(node): - for method_name, method in _nose_tools_functions(): - node.locals[method_name] = [method] - - -def _nose_tools_trivial_transform(): - """Custom transform for the nose.tools module.""" - stub = AstroidBuilder(AstroidManager()).string_build("""__all__ = []""") - all_entries = ["ok_", "eq_"] - - for pep8_name, method in _nose_tools_functions(): - all_entries.append(pep8_name) - stub[pep8_name] = method - - # Update the __all__ variable, since nose.tools - # does this manually with .append. - all_assign = stub["__all__"].parent - all_object = List(all_entries) - all_object.parent = all_assign - all_assign.value = all_object - return stub - - -def register(manager: AstroidManager) -> None: - register_module_extender( - manager, "nose.tools.trivial", _nose_tools_trivial_transform - ) - manager.register_transform( - Module, _nose_tools_transform, lambda n: n.name == "nose.tools" - ) diff --git a/astroid/brain/helpers.py b/astroid/brain/helpers.py index 79d778b5a3..250d43883b 100644 --- a/astroid/brain/helpers.py +++ b/astroid/brain/helpers.py @@ -47,7 +47,6 @@ def register_all_brains(manager: AstroidManager) -> None: brain_mechanize, brain_multiprocessing, brain_namedtuple_enum, - brain_nose, brain_numpy_core_einsumfunc, brain_numpy_core_fromnumeric, brain_numpy_core_function_base, @@ -99,7 +98,6 @@ def register_all_brains(manager: AstroidManager) -> None: brain_mechanize.register(manager) brain_multiprocessing.register(manager) brain_namedtuple_enum.register(manager) - brain_nose.register(manager) brain_numpy_core_einsumfunc.register(manager) brain_numpy_core_fromnumeric.register(manager) brain_numpy_core_function_base.register(manager) diff --git a/pyproject.toml b/pyproject.toml index a669de1102..69de5af227 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -151,7 +151,6 @@ module = [ "_io.*", "gi.*", "importlib.*", - "nose.*", "numpy.*", "pytest", "setuptools", diff --git a/requirements_full.txt b/requirements_full.txt index 51ed016f5d..e4ac735e6e 100644 --- a/requirements_full.txt +++ b/requirements_full.txt @@ -3,7 +3,6 @@ # Packages used to run additional tests attrs -nose numpy>=1.17.0,<2; python_version<"3.12" python-dateutil PyQt6 diff --git a/tests/brain/test_nose.py b/tests/brain/test_nose.py deleted file mode 100644 index 2b615c1833..0000000000 --- a/tests/brain/test_nose.py +++ /dev/null @@ -1,45 +0,0 @@ -# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html -# For details: https://github.com/pylint-dev/astroid/blob/main/LICENSE -# Copyright (c) https://github.com/pylint-dev/astroid/blob/main/CONTRIBUTORS.txt - -from __future__ import annotations - -import unittest -import warnings - -import astroid -from astroid import builder - -try: - with warnings.catch_warnings(): - warnings.simplefilter("ignore", DeprecationWarning) - import nose # pylint: disable=unused-import - HAS_NOSE = True -except ImportError: - HAS_NOSE = False - - -@unittest.skipUnless(HAS_NOSE, "This test requires nose library.") -class NoseBrainTest(unittest.TestCase): - def test_nose_tools(self): - methods = builder.extract_node( - """ - from nose.tools import assert_equal - from nose.tools import assert_equals - from nose.tools import assert_true - assert_equal = assert_equal #@ - assert_true = assert_true #@ - assert_equals = assert_equals #@ - """ - ) - assert isinstance(methods, list) - assert_equal = next(methods[0].value.infer()) - assert_true = next(methods[1].value.infer()) - assert_equals = next(methods[2].value.infer()) - - self.assertIsInstance(assert_equal, astroid.BoundMethod) - self.assertIsInstance(assert_true, astroid.BoundMethod) - self.assertIsInstance(assert_equals, astroid.BoundMethod) - self.assertEqual(assert_equal.qname(), "unittest.case.TestCase.assertEqual") - self.assertEqual(assert_true.qname(), "unittest.case.TestCase.assertTrue") - self.assertEqual(assert_equals.qname(), "unittest.case.TestCase.assertEqual") From c77eb5016bf9ada4ebc3face535e6f1169d48421 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Fri, 27 Jun 2025 09:35:38 +0200 Subject: [PATCH 2/2] Filter warnings for the test for old namespace package based on pkg_resource It won't work when the package is removed but let's keep it for now --- tests/test_manager.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/test_manager.py b/tests/test_manager.py index 9a7bbdb7ef..6a0f791686 100644 --- a/tests/test_manager.py +++ b/tests/test_manager.py @@ -120,8 +120,15 @@ def test_ast_from_namespace_pkg_resources(self) -> None: def test_identify_old_namespace_package_protocol(self) -> None: # Like the above cases, this package follows the old namespace package protocol # astroid currently assumes such packages are in sys.modules, so import it - # pylint: disable-next=import-outside-toplevel - import tests.testdata.python3.data.path_pkg_resources_1.package.foo as _ # noqa + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + category=UserWarning, + message=".*pkg_resources is deprecated.*", + ) + + # pylint: disable-next=import-outside-toplevel + import tests.testdata.python3.data.path_pkg_resources_1.package.foo as _ # noqa self.assertTrue( util.is_namespace("tests.testdata.python3.data.path_pkg_resources_1")