Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-astroid for openSUSE:Factory 
checked in at 2026-05-12 19:26:07
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-astroid (Old)
 and      /work/SRC/openSUSE:Factory/.python-astroid.new.1966 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-astroid"

Tue May 12 19:26:07 2026 rev:67 rq:1352301 version:4.2.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-astroid/python-astroid.changes    
2026-03-24 18:48:17.441037478 +0100
+++ /work/SRC/openSUSE:Factory/.python-astroid.new.1966/python-astroid.changes  
2026-05-12 19:26:14.282017235 +0200
@@ -1,0 +2,9 @@
+Sun May  3 17:24:47 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 4.2.0:
+  * Fix ``RecursionError`` in ``_compute_mro()`` when circular
+    class hierarchies are created through runtime name rebinding.
+  * Changed `block_range` to consider `else` its own block,
+    allowing `pylint` to apply disables to just the block.
+
+-------------------------------------------------------------------

Old:
----
  astroid-4.1.2-gh.tar.gz

New:
----
  astroid-4.2.0-gh.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-astroid.spec ++++++
--- /var/tmp/diff_new_pack.zUzFZ5/_old  2026-05-12 19:26:14.802038787 +0200
+++ /var/tmp/diff_new_pack.zUzFZ5/_new  2026-05-12 19:26:14.806038953 +0200
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-astroid
-Version:        4.1.2
+Version:        4.2.0
 Release:        0
 Summary:        Representation of Python source as an AST for pylint
 License:        LGPL-2.1-or-later

++++++ astroid-4.1.2-gh.tar.gz -> astroid-4.2.0-gh.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/.github/workflows/backport.yml 
new/astroid-4.2.0/.github/workflows/backport.yml
--- old/astroid-4.1.2/.github/workflows/backport.yml    2026-03-22 
16:06:01.000000000 +0100
+++ new/astroid-4.2.0/.github/workflows/backport.yml    2026-04-28 
11:27:11.000000000 +0200
@@ -14,6 +14,7 @@
     runs-on: ubuntu-latest
     environment:
       name: Backport
+      deployment: false
     # Only react to merged PRs for security reasons.
     # See 
https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target.
     if: >
@@ -25,15 +26,15 @@
         )
       )
     steps:
-      - uses: 
actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # 
v2.2.1
+      - uses: 
actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # 
v3.1.1
         id: app-token
         with:
-          app-id: ${{ vars.BACKPORT_APP_ID }}
+          client-id: ${{ vars.BACKPORT_CLIENT_ID }}
           private-key: ${{ secrets.PRIVATE_KEY }}
           permission-contents: write # push branch to Github
           permission-pull-requests: write # create PR / add comment for manual 
backport
           permission-workflows: write # modify files in .github/workflows
-      - uses: pylint-dev/backport@6accae9e09c5ad1bc3a0b56adf37c45357e7bcdc # 
v2.1.3
+      - uses: pylint-dev/backport@3adad52e5a8ba2ea731c32037442d507eed68b4c # 
v2.1.8
         with:
           github_token: ${{ steps.app-token.outputs.token }}
           user_name: ${{ vars.BACKPORT_USER_NAME }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/.github/workflows/ci.yaml 
new/astroid-4.2.0/.github/workflows/ci.yaml
--- old/astroid-4.1.2/.github/workflows/ci.yaml 2026-03-22 16:06:01.000000000 
+0100
+++ new/astroid-4.2.0/.github/workflows/ci.yaml 2026-04-28 11:27:11.000000000 
+0200
@@ -43,7 +43,7 @@
       - &cache-python
         name: Restore Python virtual environment
         id: cache-venv
-        uses: actions/[email protected]
+        uses: actions/[email protected]
         with:
           path: venv
           key: >-
@@ -63,7 +63,7 @@
             hashFiles('.pre-commit-config.yaml') }}" >> $GITHUB_OUTPUT
       - name: Restore pre-commit environment
         id: cache-precommit
-        uses: actions/[email protected]
+        uses: actions/[email protected]
         with:
           path: ${{ env.PRE_COMMIT_CACHE }}
           key: >-
@@ -85,7 +85,8 @@
     strategy:
       fail-fast: false
       matrix:
-        python-version: &matrix-python-version ["3.10", "3.11", "3.12", 
"3.13", "3.14"]
+        python-version:
+          &matrix-python-version ["3.10", "3.11", "3.12", "3.13", "3.14", 
"3.15-dev"]
     outputs:
       python-key: ${{ steps.generate-python-key.outputs.key }}
     steps:
@@ -122,7 +123,7 @@
           . venv/bin/activate
           pytest --cov
       - name: Upload coverage artifact
-        uses: &actions-upload-artifact actions/[email protected]
+        uses: &actions-upload-artifact actions/[email protected]
         with:
           name: coverage-linux-${{ matrix.python-version }}
           path: .coverage
@@ -136,7 +137,7 @@
     strategy:
       fail-fast: false
       matrix:
-        python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
+        python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "3.15-dev"]
     steps:
       - name: Set temp directory
         run: echo "TEMP=$env:USERPROFILE\AppData\Local\Temp" >> $env:GITHUB_ENV
@@ -226,12 +227,12 @@
       - name: Install dependencies
         run: pip install -U -r requirements_minimal.txt
       - name: Download all coverage artifacts
-        uses: actions/[email protected]
+        uses: actions/[email protected]
       - name: Combine Linux coverage results
         run: |
           coverage combine coverage-linux*/.coverage
           coverage xml -o coverage-linux.xml
-      - uses: &actions-codecov codecov/codecov-action@v5
+      - uses: &actions-codecov codecov/codecov-action@v6
         with:
           token: ${{ secrets.CODECOV_TOKEN }}
           fail_ci_if_error: true
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/.github/workflows/release.yml 
new/astroid-4.2.0/.github/workflows/release.yml
--- old/astroid-4.1.2/.github/workflows/release.yml     2026-03-22 
16:06:01.000000000 +0100
+++ new/astroid-4.2.0/.github/workflows/release.yml     2026-04-28 
11:27:11.000000000 +0200
@@ -34,7 +34,7 @@
         run: |
           python -m build
       - name: Upload release assets
-        uses: actions/[email protected]
+        uses: actions/[email protected]
         with:
           name: release-assets
           path: dist/
@@ -50,7 +50,7 @@
       id-token: write
     steps:
       - name: Download release assets
-        uses: actions/[email protected]
+        uses: actions/[email protected]
         with:
           name: release-assets
           path: dist/
@@ -67,13 +67,13 @@
       id-token: write
     steps:
       - name: Download release assets
-        uses: actions/[email protected]
+        uses: actions/[email protected]
         with:
           name: release-assets
           path: dist/
       - name: Sign the dists with Sigstore and upload assets to Github release
         if: github.event_name == 'release'
-        uses: sigstore/[email protected]
+        uses: sigstore/[email protected]
         with:
           inputs: |
             ./dist/*.tar.gz
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/.github/workflows/test-pylint.yml 
new/astroid-4.2.0/.github/workflows/test-pylint.yml
--- old/astroid-4.1.2/.github/workflows/test-pylint.yml 1970-01-01 
01:00:00.000000000 +0100
+++ new/astroid-4.2.0/.github/workflows/test-pylint.yml 2026-04-28 
11:27:11.000000000 +0200
@@ -0,0 +1,11 @@
+name: Test pylint
+
+on:
+  pull_request:
+
+jobs:
+  test-pylint-with-astroid-sha:
+    uses: pylint-dev/pylint/.github/workflows/tests.yaml@main
+    with:
+      repository: pylint-dev/pylint
+      astroid_sha: ${{ github.sha }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/.pre-commit-config.yaml 
new/astroid-4.2.0/.pre-commit-config.yaml
--- old/astroid-4.1.2/.pre-commit-config.yaml   2026-03-22 16:06:01.000000000 
+0100
+++ new/astroid-4.2.0/.pre-commit-config.yaml   2026-04-28 11:27:11.000000000 
+0200
@@ -10,7 +10,7 @@
       - id: end-of-file-fixer
         exclude: tests/testdata
   - repo: https://github.com/astral-sh/ruff-pre-commit
-    rev: "v0.15.0"
+    rev: "v0.15.11"
     hooks:
       - id: ruff-check
         args: ["--fix"]
@@ -33,7 +33,7 @@
       - id: black-disable-checker
         exclude: tests/test_nodes_lineno.py
   - repo: https://github.com/psf/black-pre-commit-mirror
-    rev: 26.1.0
+    rev: 26.3.1
     hooks:
       - id: black
         args: [--safe, --quiet]
@@ -68,7 +68,7 @@
           ]
         stages: [manual]
   - repo: https://github.com/pre-commit/mirrors-mypy
-    rev: v1.19.1
+    rev: v1.20.1
     hooks:
       - id: mypy
         language: python
@@ -76,11 +76,11 @@
         require_serial: true
         additional_dependencies: ["types-typed-ast"]
   - repo: https://github.com/rbubley/mirrors-prettier
-    rev: v3.8.1
+    rev: v3.8.3
     hooks:
       - id: prettier
         args: [--prose-wrap=always, --print-width=88]
   - repo: https://github.com/tox-dev/pyproject-fmt
-    rev: "v2.15.0"
+    rev: "v2.21.1"
     hooks:
       - id: pyproject-fmt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/CONTRIBUTORS.txt 
new/astroid-4.2.0/CONTRIBUTORS.txt
--- old/astroid-4.1.2/CONTRIBUTORS.txt  2026-03-22 16:06:01.000000000 +0100
+++ new/astroid-4.2.0/CONTRIBUTORS.txt  2026-04-28 11:27:11.000000000 +0200
@@ -31,13 +31,17 @@
 Contributors
 ------------
 - Emile Anclin <[email protected]>
+- dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
+- pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
 - Nick Drozd <[email protected]>
+- github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
 - correctmost <[email protected]>
 - Andrew Haigh <[email protected]>
 - Julien Cristau <[email protected]>
 - Artem Yurchenko <[email protected]>
 - David Liu <[email protected]>
 - Alexandre Fayolle <[email protected]>
+- pylint-backport[bot] 
<212256041+pylint-backport[bot]@users.noreply.github.com>
 - Eevee (Alex Munroe) <[email protected]>
 - Emmanuel Ferdman <[email protected]>
 - David Gilman <[email protected]>
@@ -221,6 +225,10 @@
 - Alexander Presnyakov <[email protected]>
 - Ahmed Azzaoui <[email protected]>
 - Casey Jones <[email protected]>
+- sergiochan <[email protected]>
+- Joshix-1 <[email protected]>
+- pylint-backport-bot[bot] 
<212256041+pylint-backport-bot[bot]@users.noreply.github.com>
+- Copilot <[email protected]>
 
 Co-Author
 ---------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/ChangeLog new/astroid-4.2.0/ChangeLog
--- old/astroid-4.1.2/ChangeLog 2026-03-22 16:06:01.000000000 +0100
+++ new/astroid-4.2.0/ChangeLog 2026-04-28 11:27:11.000000000 +0200
@@ -3,17 +3,35 @@
 ===================
 
 
-What's New in astroid 4.2.0?
+What's New in astroid 4.3.0?
 ============================
 Release date: TBA
 
 
-What's New in astroid 4.1.3?
+
+What's New in astroid 4.2.1?
 ============================
 Release date: TBA
 
 
 
+What's New in astroid 4.2.0?
+============================
+Release date: 2026-04-28
+
+* Fix ``RecursionError`` in ``_compute_mro()`` when circular class hierarchies
+  are created through runtime name rebinding. Circular bases are now resolved
+  to the original class instead of recursing.
+
+  Closes #3023
+  Closes pylint-dev/pylint#10821
+
+* Changed `block_range` to consider `else` its own block, allowing `pylint` to 
apply
+  disables to just the block.
+
+  References pylint-dev/pylint#872
+
+
 What's New in astroid 4.1.2?
 ============================
 Release date: 2026-03-22
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/astroid/__pkginfo__.py 
new/astroid-4.2.0/astroid/__pkginfo__.py
--- old/astroid-4.1.2/astroid/__pkginfo__.py    2026-03-22 16:06:01.000000000 
+0100
+++ new/astroid-4.2.0/astroid/__pkginfo__.py    2026-04-28 11:27:11.000000000 
+0200
@@ -2,5 +2,5 @@
 # For details: https://github.com/pylint-dev/astroid/blob/main/LICENSE
 # Copyright (c) 
https://github.com/pylint-dev/astroid/blob/main/CONTRIBUTORS.txt
 
-__version__ = "4.1.2"
+__version__ = "4.2.0"
 version = __version__
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/astroid/brain/brain_typing.py 
new/astroid-4.2.0/astroid/brain/brain_typing.py
--- old/astroid-4.1.2/astroid/brain/brain_typing.py     2026-03-22 
16:06:01.000000000 +0100
+++ new/astroid-4.2.0/astroid/brain/brain_typing.py     2026-04-28 
11:27:11.000000000 +0200
@@ -15,7 +15,7 @@
 from astroid import context, nodes
 from astroid.brain.helpers import register_module_extender
 from astroid.builder import AstroidBuilder, _extract_single_node, extract_node
-from astroid.const import PY312_PLUS, PY313_PLUS, PY314_PLUS
+from astroid.const import PY312_PLUS, PY313_PLUS, PY314_PLUS, PY315_PLUS
 from astroid.exceptions import (
     AstroidSyntaxError,
     AttributeInferenceError,
@@ -464,6 +464,13 @@
         @classmethod
         def __class_getitem__(cls, item): return cls
     """)
+    if PY315_PLUS:
+        # typing.ByteString was removed from the typing module in Python 3.15
+        # (it was deprecated since 3.12 and present at module level until 
3.14).
+        # Inject a stub so code using `typing.ByteString` can still be 
inferred.
+        code += textwrap.dedent("""
+    class ByteString: ...
+    """)
     return AstroidBuilder(AstroidManager()).string_build(code)
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/astroid/const.py 
new/astroid-4.2.0/astroid/const.py
--- old/astroid-4.1.2/astroid/const.py  2026-03-22 16:06:01.000000000 +0100
+++ new/astroid-4.2.0/astroid/const.py  2026-04-28 11:27:11.000000000 +0200
@@ -10,6 +10,7 @@
 PY313 = sys.version_info[:2] == (3, 13)
 PY313_PLUS = sys.version_info >= (3, 13)
 PY314_PLUS = sys.version_info >= (3, 14)
+PY315_PLUS = sys.version_info >= (3, 15)
 
 WIN32 = sys.platform == "win32"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/astroid/helpers.py 
new/astroid-4.2.0/astroid/helpers.py
--- old/astroid-4.1.2/astroid/helpers.py        2026-03-22 16:06:01.000000000 
+0100
+++ new/astroid-4.2.0/astroid/helpers.py        2026-04-28 11:27:11.000000000 
+0200
@@ -6,7 +6,6 @@
 
 from __future__ import annotations
 
-import warnings
 from collections.abc import Generator
 
 from astroid import bases, manager, nodes, objects, raw_building, util
@@ -20,20 +19,7 @@
 )
 from astroid.nodes import scoped_nodes
 from astroid.typing import InferenceResult
-from astroid.util import safe_infer as real_safe_infer
-
-
-def safe_infer(
-    node: nodes.NodeNG | bases.Proxy | util.UninferableBase,
-    context: InferenceContext | None = None,
-) -> InferenceResult | None:
-    # When removing, also remove the real_safe_infer alias
-    warnings.warn(
-        "Import safe_infer from astroid.util; this shim in astroid.helpers 
will be removed.",
-        DeprecationWarning,
-        stacklevel=2,
-    )
-    return real_safe_infer(node, context=context)
+from astroid.util import safe_infer
 
 
 def _build_proxy_class(cls_name: str, builtins: nodes.Module) -> 
nodes.ClassDef:
@@ -130,7 +116,7 @@
     for klass in class_seq:
         if isinstance(klass, util.UninferableBase):
             raise AstroidTypeError(
-                f"arg 2 must be a type or tuple of types, not {type(klass)!r}"
+                "arg 2 must be a type or tuple of types, not <class 
'astroid.util.UninferableBase'>"
             )
 
         for obj_subclass in obj_type.mro():
@@ -201,7 +187,7 @@
     except AttributeError:
         pass
     for base in klass.bases:
-        result = real_safe_infer(base, context=context)
+        result = safe_infer(base, context=context)
         # TODO: check for A->B->A->B pattern in class structure too?
         if (
             not isinstance(result, scoped_nodes.ClassDef)
@@ -274,7 +260,7 @@
     # pylint: disable=import-outside-toplevel; circular import
     from astroid.objects import FrozenSet
 
-    inferred_node = real_safe_infer(node, context=context)
+    inferred_node = safe_infer(node, context=context)
 
     # prevent self referential length calls from causing a recursion error
     # see https://github.com/pylint-dev/astroid/issues/777
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/astroid/interpreter/_import/spec.py 
new/astroid-4.2.0/astroid/interpreter/_import/spec.py
--- old/astroid-4.1.2/astroid/interpreter/_import/spec.py       2026-03-22 
16:06:01.000000000 +0100
+++ new/astroid-4.2.0/astroid/interpreter/_import/spec.py       2026-04-28 
11:27:11.000000000 +0200
@@ -185,7 +185,7 @@
                 and spec.loader  # type: ignore[comparison-overlap] # noqa: 
E501
                 is importlib.machinery.FrozenImporter
             ):
-                return ModuleSpec(
+                return ModuleSpec(  # type: ignore[unreachable]
                     name=modname,
                     location=getattr(spec.loader_state, "filename", None),
                     type=ModuleType.PY_FROZEN,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/astroid/interpreter/_import/util.py 
new/astroid-4.2.0/astroid/interpreter/_import/util.py
--- old/astroid-4.1.2/astroid/interpreter/_import/util.py       2026-03-22 
16:06:01.000000000 +0100
+++ new/astroid-4.2.0/astroid/interpreter/_import/util.py       2026-04-28 
11:27:11.000000000 +0200
@@ -72,10 +72,10 @@
                 # Workaround for "py" module
                 # https://github.com/pytest-dev/apipkg/issues/13
                 return False
-        except KeyError:
-            # Intermediate steps might raise KeyErrors
-            # https://github.com/python/cpython/issues/93334
-            # TODO: update if fixed in importlib
+        # PY314: When dropping support for 3.14, replace with just
+        # except ModuleNotFoundError:
+        except (KeyError, ModuleNotFoundError):
+            # Intermediate steps might raise ModuleNotFoundError
             # For tree a > b > c.py
             # >>> from importlib.machinery import PathFinder
             # >>> PathFinder.find_spec('a.b', ['a'])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/astroid/modutils.py 
new/astroid-4.2.0/astroid/modutils.py
--- old/astroid-4.1.2/astroid/modutils.py       2026-03-22 16:06:01.000000000 
+0100
+++ new/astroid-4.2.0/astroid/modutils.py       2026-04-28 11:27:11.000000000 
+0200
@@ -26,7 +26,6 @@
 import sys
 import sysconfig
 import types
-import warnings
 from collections.abc import Callable, Iterable, Sequence
 from contextlib import redirect_stderr, redirect_stdout
 from functools import lru_cache
@@ -550,47 +549,6 @@
     return any(filename.startswith(_cache_normalize_path(entry)) for entry in 
path)
 
 
-def is_standard_module(modname: str, std_path: Iterable[str] | None = None) -> 
bool:
-    """Try to guess if a module is a standard python module (by default,
-    see `std_path` parameter's description).
-
-    :param modname: name of the module we are interested in
-
-    :param std_path: list of path considered has standard
-
-    :return:
-      true if the module:
-      - is located on the path listed in one of the directory in `std_path`
-      - is a built-in module
-    """
-    warnings.warn(
-        "is_standard_module() is deprecated. Use, is_stdlib_module() or 
module_in_path() instead",
-        DeprecationWarning,
-        stacklevel=2,
-    )
-
-    modname = modname.split(".")[0]
-    try:
-        filename = file_from_modpath([modname])
-    except ImportError:
-        # import failed, i'm probably not so wrong by supposing it's
-        # not standard...
-        return False
-    # modules which are not living in a file are considered standard
-    # (sys and __builtin__ for instance)
-    if filename is None:
-        # we assume there are no namespaces in stdlib
-        return not util.is_namespace(modname)
-    filename = _normalize_path(filename)
-    for path in EXT_LIB_DIRS:
-        if filename.startswith(_cache_normalize_path(path)):
-            return False
-    if std_path is None:
-        std_path = STD_LIB_DIRS
-
-    return any(filename.startswith(_cache_normalize_path(path)) for path in 
std_path)
-
-
 def is_relative(modname: str, from_file: str) -> bool:
     """Return true if the given module name is relative to the given
     file name.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/astroid/nodes/_base_nodes.py 
new/astroid-4.2.0/astroid/nodes/_base_nodes.py
--- old/astroid-4.1.2/astroid/nodes/_base_nodes.py      2026-03-22 
16:06:01.000000000 +0100
+++ new/astroid-4.2.0/astroid/nodes/_base_nodes.py      2026-04-28 
11:27:11.000000000 +0200
@@ -237,22 +237,51 @@
 class MultiLineWithElseBlockNode(MultiLineBlockNode):
     """Base node for multi-line blocks that can have else statements."""
 
+    body: list[NodeNG]
+    """The contents of the block."""
+
+    orelse: list[NodeNG]
+    """The contents of the ``else`` block."""
+
     @cached_property
     def blockstart_tolineno(self):
         return self.lineno
 
+    def block_range(self, lineno: int) -> tuple[int, int]:
+        """Get a range from the given line number to where this node ends.
+
+        :param lineno: The line number to start the range at.
+
+        :returns: The range of line numbers that this node belongs to,
+            starting at the given line number.
+        """
+        if lineno < self.fromlineno:
+            return lineno, self.tolineno
+        if lineno == self.body[0].fromlineno:
+            return lineno, lineno
+        if lineno <= self.body[-1].tolineno:
+            return lineno, self.body[-1].tolineno
+        return self._elsed_block_range(lineno, self.orelse, 
self.body[0].fromlineno - 1)
+
     def _elsed_block_range(
         self, lineno: int, orelse: list[nodes.NodeNG], last: int | None = None
     ) -> tuple[int, int]:
         """Handle block line numbers range for try/finally, for, if and while
         statements.
         """
-        if lineno == self.fromlineno:
+        # If at the end of the node, return same line
+        if lineno == self.tolineno:
             return lineno, lineno
         if orelse:
-            if lineno >= orelse[0].fromlineno:
+            # If the lineno is beyond the body of the node we check the orelse
+            if lineno >= self.body[-1].tolineno + 1:
+                # If the orelse has a scope of its own we determine the block 
range there
+                if isinstance(orelse[0], MultiLineWithElseBlockNode):
+                    return orelse[0]._elsed_block_range(lineno, 
orelse[0].orelse)
+                # Return last line of orelse
                 return lineno, orelse[-1].tolineno
-            return lineno, orelse[0].fromlineno - 1
+            # If the lineno is within the body we take the last line of the 
body
+            return lineno, self.body[-1].tolineno
         return lineno, last or self.tolineno
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/astroid/nodes/node_classes.py 
new/astroid-4.2.0/astroid/nodes/node_classes.py
--- old/astroid-4.1.2/astroid/nodes/node_classes.py     2026-03-22 
16:06:01.000000000 +0100
+++ new/astroid-4.2.0/astroid/nodes/node_classes.py     2026-04-28 
11:27:11.000000000 +0200
@@ -597,9 +597,6 @@
         return _infer_stmts(stmts, context, frame)
 
 
-DEPRECATED_ARGUMENT_DEFAULT = "DEPRECATED_ARGUMENT_DEFAULT"
-
-
 class Arguments(
     _base_nodes.AssignTypeNode
 ):  # pylint: disable=too-many-instance-attributes
@@ -969,7 +966,7 @@
             return True
         return self.find_argname(name)[1] is not None
 
-    def find_argname(self, argname, rec=DEPRECATED_ARGUMENT_DEFAULT):
+    def find_argname(self, argname):
         """Get the index and :class:`AssignName` node for given name.
 
         :param argname: The name of the argument to search for.
@@ -978,12 +975,6 @@
         :returns: The index and node for the argument.
         :rtype: tuple(str or None, AssignName or None)
         """
-        if rec != DEPRECATED_ARGUMENT_DEFAULT:  # pragma: no cover
-            warnings.warn(
-                "The rec argument will be removed in astroid 3.1.",
-                DeprecationWarning,
-                stacklevel=2,
-            )
         if self.arguments:
             index, argument = _find_arg(argname, self.arguments)
             if argument:
@@ -3061,20 +3052,6 @@
         """
         return self.test.tolineno
 
-    def block_range(self, lineno: int) -> tuple[int, int]:
-        """Get a range from the given line number to where this node ends.
-
-        :param lineno: The line number to start the range at.
-
-        :returns: The range of line numbers that this node belongs to,
-            starting at the given line number.
-        """
-        if lineno == self.body[0].fromlineno:
-            return lineno, lineno
-        if lineno <= self.body[-1].tolineno:
-            return lineno, self.body[-1].tolineno
-        return self._elsed_block_range(lineno, self.orelse, 
self.body[0].fromlineno - 1)
-
     def get_children(self):
         yield self.test
 
@@ -3915,27 +3892,20 @@
 
     def block_range(self, lineno: int) -> tuple[int, int]:
         """Get a range from a given line number to where this node ends."""
-        if lineno == self.fromlineno:
-            return lineno, lineno
-        if self.body and self.body[0].fromlineno <= lineno <= 
self.body[-1].tolineno:
-            # Inside try body - return from lineno till end of try body
-            return lineno, self.body[-1].tolineno
         for exhandler in self.handlers:
             if exhandler.type and lineno == exhandler.type.fromlineno:
-                return lineno, lineno
+                return lineno, exhandler.tolineno
             if exhandler.body[0].fromlineno <= lineno <= 
exhandler.body[-1].tolineno:
                 return lineno, exhandler.body[-1].tolineno
-        if self.orelse:
-            if self.orelse[0].fromlineno - 1 == lineno:
-                return lineno, lineno
-            if self.orelse[0].fromlineno <= lineno <= self.orelse[-1].tolineno:
-                return lineno, self.orelse[-1].tolineno
         if self.finalbody:
             if self.finalbody[0].fromlineno - 1 == lineno:
-                return lineno, lineno
+                return lineno, self.finalbody[0].tolineno
             if self.finalbody[0].fromlineno <= lineno <= 
self.finalbody[-1].tolineno:
                 return lineno, self.finalbody[-1].tolineno
-        return lineno, self.tolineno
+
+        # If not within any of the ExceptHandlers or `finally` body, fall back 
to regular
+        # handling of block_range for nodes with a potential `else` statement.
+        return super().block_range(lineno)
 
     def get_children(self):
         yield from self.body
@@ -4014,35 +3984,28 @@
     def _infer_name(self, frame, name):
         return name
 
+    def get_children(self):
+        yield from self.body
+        yield from self.handlers
+        yield from self.orelse
+        yield from self.finalbody
+
     def block_range(self, lineno: int) -> tuple[int, int]:
         """Get a range from a given line number to where this node ends."""
-        if lineno == self.fromlineno:
-            return lineno, lineno
-        if self.body and self.body[0].fromlineno <= lineno <= 
self.body[-1].tolineno:
-            # Inside try body - return from lineno till end of try body
-            return lineno, self.body[-1].tolineno
         for exhandler in self.handlers:
             if exhandler.type and lineno == exhandler.type.fromlineno:
-                return lineno, lineno
+                return lineno, exhandler.tolineno
             if exhandler.body[0].fromlineno <= lineno <= 
exhandler.body[-1].tolineno:
                 return lineno, exhandler.body[-1].tolineno
-        if self.orelse:
-            if self.orelse[0].fromlineno - 1 == lineno:
-                return lineno, lineno
-            if self.orelse[0].fromlineno <= lineno <= self.orelse[-1].tolineno:
-                return lineno, self.orelse[-1].tolineno
         if self.finalbody:
             if self.finalbody[0].fromlineno - 1 == lineno:
-                return lineno, lineno
+                return lineno, self.finalbody[0].tolineno
             if self.finalbody[0].fromlineno <= lineno <= 
self.finalbody[-1].tolineno:
                 return lineno, self.finalbody[-1].tolineno
-        return lineno, self.tolineno
 
-    def get_children(self):
-        yield from self.body
-        yield from self.handlers
-        yield from self.orelse
-        yield from self.finalbody
+        # If not within any of the ExceptHandlers or `finally` body, fall back 
to regular
+        # handling of block_range for nodes with a potential `else` statement.
+        return super().block_range(lineno)
 
 
 class Tuple(BaseContainer):
@@ -4472,16 +4435,6 @@
         """
         return self.test.tolineno
 
-    def block_range(self, lineno: int) -> tuple[int, int]:
-        """Get a range from the given line number to where this node ends.
-
-        :param lineno: The line number to start the range at.
-
-        :returns: The range of line numbers that this node belongs to,
-            starting at the given line number.
-        """
-        return self._elsed_block_range(lineno, self.orelse)
-
     def get_children(self):
         yield self.test
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/astroid-4.1.2/astroid/nodes/scoped_nodes/scoped_nodes.py 
new/astroid-4.2.0/astroid/nodes/scoped_nodes/scoped_nodes.py
--- old/astroid-4.1.2/astroid/nodes/scoped_nodes/scoped_nodes.py        
2026-03-22 16:06:01.000000000 +0100
+++ new/astroid-4.2.0/astroid/nodes/scoped_nodes/scoped_nodes.py        
2026-04-28 11:27:11.000000000 +0200
@@ -2812,7 +2812,12 @@
     def slots(self):
         return self._all_slots
 
-    def _inferred_bases(self, context: InferenceContext | None = None):
+    def _inferred_bases(
+        self,
+        context: InferenceContext | None = None,
+        *,
+        base_classes: frozenset[ClassDef] = frozenset(),
+    ):
         # Similar with .ancestors, but the difference is when one base is 
inferred,
         # only the first object is wanted. That's because
         # we aren't interested in superclasses, as in the following
@@ -2841,7 +2846,7 @@
                 baseobj = baseobj._proxied
             if not isinstance(baseobj, ClassDef):
                 continue
-            if baseobj is self:
+            if baseobj is self or baseobj in base_classes:
                 # Circular base due to name rebinding (e.g. pdb.Pdb = CustomPdb
                 # where CustomPdb inherits from pdb.Pdb). Fall back to the
                 # first non-circular inferred value from the base expression.
@@ -2876,17 +2881,25 @@
             pass
         return None
 
-    def _compute_mro(self, context: InferenceContext | None = None):
+    def _compute_mro(
+        self,
+        context: InferenceContext,
+        *,
+        base_chain: frozenset[ClassDef] = frozenset(),
+    ):
         if self.qname() == "builtins.object":
             return [self]
 
-        inferred_bases = list(self._inferred_bases(context=context))
+        inferred_bases = list(
+            self._inferred_bases(context=context, base_classes=base_chain)
+        )
         bases_mro = []
+        base_chain |= {self}
         for base in inferred_bases:
-            if base is self:
+            if base in base_chain:
                 continue
 
-            mro = base._compute_mro(context=context)
+            mro = base._compute_mro(context=context, base_chain=base_chain)
             bases_mro.append(mro)
 
         unmerged_mro: list[list[ClassDef]] = [[self], *bases_mro, 
inferred_bases]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/astroid/protocols.py 
new/astroid-4.2.0/astroid/protocols.py
--- old/astroid-4.1.2/astroid/protocols.py      2026-03-22 16:06:01.000000000 
+0100
+++ new/astroid-4.2.0/astroid/protocols.py      2026-04-28 11:27:11.000000000 
+0200
@@ -545,7 +545,7 @@
 """)))
         assigned = objects.ExceptionInstance(eg)
         assigned.instance_attrs["exceptions"] = [
-            nodes.List.from_elements(_generate_assigned())
+            nodes.Tuple.from_elements(_generate_assigned())
         ]
         yield assigned
     else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/astroid/rebuilder.py 
new/astroid-4.2.0/astroid/rebuilder.py
--- old/astroid-4.1.2/astroid/rebuilder.py      2026-03-22 16:06:01.000000000 
+0100
+++ new/astroid-4.2.0/astroid/rebuilder.py      2026-04-28 11:27:11.000000000 
+0200
@@ -120,7 +120,6 @@
         end_lineno = node.end_lineno
         if node.body:
             end_lineno = node.body[0].lineno
-        # pylint: disable-next=unsubscriptable-object
         data = "\n".join(self._data[node.lineno - 1 : end_lineno])
 
         start_token: TokenInfo | None = None
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/astroid/util.py 
new/astroid-4.2.0/astroid/util.py
--- old/astroid-4.1.2/astroid/util.py   2026-03-22 16:06:01.000000000 +0100
+++ new/astroid-4.2.0/astroid/util.py   2026-04-28 11:27:11.000000000 +0200
@@ -108,19 +108,6 @@
         return msg.format(self.op, self.left_type.name, self.right_type.name)
 
 
-def _instancecheck(cls, other) -> bool:
-    wrapped = cls.__wrapped__
-    other_cls = other.__class__
-    is_instance_of = wrapped is other_cls or issubclass(other_cls, wrapped)
-    warnings.warn(
-        "%r is deprecated and slated for removal in astroid "
-        "2.0, use %r instead" % (cls.__class__.__name__, wrapped.__name__),
-        PendingDeprecationWarning,
-        stacklevel=2,
-    )
-    return is_instance_of
-
-
 def check_warnings_filter() -> bool:
     """Return True if any other than the default DeprecationWarning filter is 
enabled.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/pyproject.toml 
new/astroid-4.2.0/pyproject.toml
--- old/astroid-4.1.2/pyproject.toml    2026-03-22 16:06:01.000000000 +0100
+++ new/astroid-4.2.0/pyproject.toml    2026-04-28 11:27:11.000000000 +0200
@@ -34,8 +34,8 @@
 ]
 urls."Bug tracker" = "https://github.com/pylint-dev/astroid/issues";
 urls."Discord server" = "https://discord.gg/Egy6P8AMB5";
-urls."Docs" = "https://pylint.readthedocs.io/projects/astroid/en/latest/";
 urls."Source Code" = "https://github.com/pylint-dev/astroid";
+urls.Docs = "https://pylint.readthedocs.io/projects/astroid/en/latest/";
 
 [tool.setuptools]
 dynamic.version = { attr = "astroid.__pkginfo__.__version__" }
@@ -76,12 +76,6 @@
 [tool.pyproject-fmt]
 max_supported_python = "3.14"
 
-[tool.pytest]
-ini_options.addopts = '-m "not acceptance"'
-ini_options.python_files = [ "*test_*.py" ]
-ini_options.testpaths = [ "tests" ]
-ini_options.filterwarnings = "error"
-
 [tool.mypy]
 python_version = "3.10"
 files = [
@@ -135,6 +129,7 @@
 strict = true
 warn_redundant_casts = true
 warn_unreachable = true
+warn_unused_configs = false
 
 [[tool.mypy.overrides]]
 # Importlib typeshed stubs do not include the private functions we use
@@ -148,5 +143,11 @@
 ]
 ignore_missing_imports = true
 
+[tool.pytest]
+ini_options.addopts = '-m "not acceptance"'
+ini_options.python_files = [ "*test_*.py" ]
+ini_options.testpaths = [ "tests" ]
+ini_options.filterwarnings = "error"
+
 [tool.aliases]
 test = "pytest"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/requirements_minimal.txt 
new/astroid-4.2.0/requirements_minimal.txt
--- old/astroid-4.1.2/requirements_minimal.txt  2026-03-22 16:06:01.000000000 
+0100
+++ new/astroid-4.2.0/requirements_minimal.txt  2026-04-28 11:27:11.000000000 
+0200
@@ -1,9 +1,9 @@
 # Tools used when releasing
-contributors-txt>=1.0.1
+contributors-txt>=1.0.2
 tbump~=6.11
 
 # Tools used to run tests
 coverage~=7.13
 pytest
-pytest-cov~=7.0
+pytest-cov~=7.1
 mypy; platform_python_implementation!="PyPy"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/script/.contributors_aliases.json 
new/astroid-4.2.0/script/.contributors_aliases.json
--- old/astroid-4.1.2/script/.contributors_aliases.json 2026-03-22 
16:06:01.000000000 +0100
+++ new/astroid-4.2.0/script/.contributors_aliases.json 2026-04-28 
11:27:11.000000000 +0200
@@ -24,8 +24,8 @@
   },
   "[email protected]": {
     "mails": [
-      "[email protected]",
-      "[email protected]"
+      "[email protected]",
+      "[email protected]"
     ],
     "name": "Artem Yurchenko"
   },
@@ -68,26 +68,16 @@
   },
   "[email protected]": {
     "mails": [
+      "[email protected]",
       "[email protected]",
-      "[email protected]",
       "[email protected]",
-      "[email protected]"
+      "[email protected]"
     ],
     "name": "Ashley Whetter",
     "team": "Maintainers"
   },
-  "[email protected]": {
-    "mails": [
-      "66853113+pre-commit-ci[bot]@users.noreply.github.com",
-      "49699333+dependabot[bot]@users.noreply.github.com",
-      "41898282+github-actions[bot]@users.noreply.github.com",
-      "212256041+pylint-backport[bot]@users.noreply.github.com",
-      "212256041+pylint-backport-bot[bot]@users.noreply.github.com"
-    ],
-    "name": "bot"
-  },
   "[email protected]": {
-    "mails": ["[email protected]", "[email protected]"],
+    "mails": ["[email protected]", "[email protected]"],
     "name": "Bryce Guinta",
     "team": "Maintainers"
   },
@@ -124,8 +114,8 @@
   },
   "[email protected]": {
     "mails": [
-      "[email protected]",
-      "[email protected]"
+      "[email protected]",
+      "[email protected]"
     ],
     "name": "Hugo van Kemenade"
   },
@@ -151,7 +141,7 @@
     "name": "Keichi Takahashi"
   },
   "[email protected]": {
-    "mails": ["[email protected]", "[email protected]"],
+    "mails": ["[email protected]", "[email protected]"],
     "name": "Mario Corchero"
   },
   "[email protected]": {
@@ -173,10 +163,10 @@
   },
   "[email protected]": {
     "mails": [
-      "[email protected]",
-      "[email protected]",
       "[email protected]",
-      "[email protected]"
+      "[email protected]",
+      "[email protected]",
+      "[email protected]"
     ],
     "name": "Google, Inc."
   },
@@ -186,12 +176,12 @@
     "team": "Ex-maintainers"
   },
   "[email protected]": {
-    "mails": ["[email protected]", "[email protected]"],
+    "mails": ["[email protected]", "[email protected]"],
     "name": "Pierre Sassoulas",
     "team": "Maintainers"
   },
   "[email protected]": {
-    "mails": ["[email protected]", "[email protected]"],
+    "mails": ["[email protected]", "[email protected]"],
     "name": "Raphael Gaschignard"
   },
   "[email protected]": {
@@ -209,14 +199,14 @@
     "name": "Stefan Scherfke"
   },
   "[email protected]": {
-    "mails": ["[email protected]", "[email protected]"],
+    "mails": ["[email protected]", "[email protected]"],
     "name": "Sylvain Thénault",
     "team": "Ex-maintainers"
   },
   "[email protected]": {
     "mails": [
-      "[email protected]",
-      "[email protected]"
+      "[email protected]",
+      "[email protected]"
     ],
     "name": "Tushar Sadhwani"
   },
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/tbump.toml new/astroid-4.2.0/tbump.toml
--- old/astroid-4.1.2/tbump.toml        2026-03-22 16:06:01.000000000 +0100
+++ new/astroid-4.2.0/tbump.toml        2026-04-28 11:27:11.000000000 +0200
@@ -1,7 +1,7 @@
 github_url = "https://github.com/pylint-dev/astroid";
 
 [version]
-current = "4.1.2"
+current = "4.2.0"
 regex = '''
 ^(?P<major>0|[1-9]\d*)
 \.
@@ -34,7 +34,7 @@
 
 [[before_commit]]
 name = "Upgrade the contributors list"
-cmd = "python3 script/create_contributor_list.py"
+cmd = "python3 script/create_contributor_list.py --no-bots"
 
 [[before_commit]]
 name = "Apply pre-commit"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/tests/brain/test_brain.py 
new/astroid-4.2.0/tests/brain/test_brain.py
--- old/astroid-4.1.2/tests/brain/test_brain.py 2026-03-22 16:06:01.000000000 
+0100
+++ new/astroid-4.2.0/tests/brain/test_brain.py 2026-04-28 11:27:11.000000000 
+0200
@@ -15,7 +15,7 @@
 from astroid import MANAGER, builder, nodes, objects, test_utils, util
 from astroid.bases import Instance
 from astroid.brain.brain_namedtuple_enum import _get_namedtuple_fields
-from astroid.const import PY312_PLUS, PY313_PLUS
+from astroid.const import PY312_PLUS, PY313_PLUS, PY315_PLUS
 from astroid.exceptions import (
     AttributeInferenceError,
     InferenceError,
@@ -787,7 +787,10 @@
         typing.ByteString
         """)
         inferred = next(right_node.infer())
-        check_metaclass_is_abc(inferred)
+        # From Python 3.15 we add a stub definition of `ByteString`. It 
doesn't need all properties
+        # of the original implementation.
+        if not PY315_PLUS:
+            check_metaclass_is_abc(inferred)
         with self.assertRaises(AttributeInferenceError):
             self.assertIsInstance(
                 inferred.getattr("__class_getitem__")[0], nodes.FunctionDef
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/tests/test_group_exceptions.py 
new/astroid-4.2.0/tests/test_group_exceptions.py
--- old/astroid-4.1.2/tests/test_group_exceptions.py    2026-03-22 
16:06:01.000000000 +0100
+++ new/astroid-4.2.0/tests/test_group_exceptions.py    2026-04-28 
11:27:11.000000000 +0200
@@ -41,7 +41,7 @@
     assert isinstance(node, nodes.Try)
     handler = node.handlers[0]
     assert node.block_range(lineno=1) == (1, 9)
-    assert node.block_range(lineno=2) == (2, 2)
+    assert node.block_range(lineno=2) == (2, 3)
     assert node.block_range(lineno=5) == (5, 9)
     assert isinstance(handler, nodes.ExceptHandler)
     assert handler.type.name == "ExceptionGroup"
@@ -72,15 +72,15 @@
     assert node.as_string() == code.replace('"', "'").strip()
     assert isinstance(node.body[0], nodes.Raise)
     assert node.block_range(1) == (1, 11)
-    assert node.block_range(2) == (2, 2)
+    assert node.block_range(2) == (2, 3)
     assert node.block_range(3) == (3, 3)
-    assert node.block_range(4) == (4, 4)
+    assert node.block_range(4) == (4, 5)
     assert node.block_range(5) == (5, 5)
-    assert node.block_range(6) == (6, 6)
+    assert node.block_range(6) == (6, 7)
     assert node.block_range(7) == (7, 7)
-    assert node.block_range(8) == (8, 8)
+    assert node.block_range(8) == (8, 9)
     assert node.block_range(9) == (9, 9)
-    assert node.block_range(10) == (10, 10)
+    assert node.block_range(10) == (10, 11)
     assert node.block_range(11) == (11, 11)
     assert node.handlers
     handler = node.handlers[0]
@@ -126,12 +126,12 @@
     assert isinstance(node, nodes.TryStar)
     inferred_ve = next(node.handlers[0].statement().name.infer())
     assert inferred_ve.name == "ExceptionGroup"
-    assert isinstance(inferred_ve.getattr("exceptions")[0], nodes.List)
+    assert isinstance(inferred_ve.getattr("exceptions")[0], nodes.Tuple)
     assert (
         inferred_ve.getattr("exceptions")[0].elts[0].pytype() == 
"builtins.ValueError"
     )
 
     inferred_te = next(node.handlers[1].statement().name.infer())
     assert inferred_te.name == "ExceptionGroup"
-    assert isinstance(inferred_te.getattr("exceptions")[0], nodes.List)
+    assert isinstance(inferred_te.getattr("exceptions")[0], nodes.Tuple)
     assert inferred_te.getattr("exceptions")[0].elts[0].pytype() == 
"builtins.TypeError"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/tests/test_helpers.py 
new/astroid-4.2.0/tests/test_helpers.py
--- old/astroid-4.1.2/tests/test_helpers.py     2026-03-22 16:06:01.000000000 
+0100
+++ new/astroid-4.2.0/tests/test_helpers.py     2026-04-28 11:27:11.000000000 
+0200
@@ -11,7 +11,6 @@
 from astroid.builder import AstroidBuilder
 from astroid.const import IS_PYPY
 from astroid.exceptions import InferenceError, _NonDeducibleTypeHierarchy
-from astroid.nodes.node_classes import UNATTACHED_UNKNOWN
 
 
 class TestHelpers(unittest.TestCase):
@@ -245,16 +244,6 @@
     assert util.safe_infer(util.Uninferable) == uninfer
 
 
-def test_safe_infer_shim() -> None:
-    with pytest.warns(DeprecationWarning) as records:
-        helpers.safe_infer(UNATTACHED_UNKNOWN)
-
-    assert (
-        "Import safe_infer from astroid.util; this shim in astroid.helpers 
will be removed."
-        in records[0].message.args[0]
-    )
-
-
 def test_class_to_container() -> None:
     node = builder.extract_node("""isinstance(3, int)""")
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/tests/test_modutils.py 
new/astroid-4.2.0/tests/test_modutils.py
--- old/astroid-4.1.2/tests/test_modutils.py    2026-03-22 16:06:01.000000000 
+0100
+++ new/astroid-4.2.0/tests/test_modutils.py    2026-04-28 11:27:11.000000000 
+0200
@@ -13,7 +13,6 @@
 import unittest
 import xml
 from pathlib import Path
-from xml import etree
 from xml.etree import ElementTree
 
 import pytest
@@ -377,81 +376,6 @@
             )
 
 
-class IsStandardModuleTest(resources.SysPathSetup, unittest.TestCase):
-    """
-    Return true if the module may be considered as a module from the standard
-    library.
-    """
-
-    def test_datetime(self) -> None:
-        # This is an interesting example, since datetime, on pypy,
-        # is under lib_pypy, rather than the usual Lib directory.
-        with pytest.warns(DeprecationWarning):
-            assert modutils.is_standard_module("datetime")
-
-    def test_builtins(self) -> None:
-        with pytest.warns(DeprecationWarning):
-            assert not modutils.is_standard_module("__builtin__")
-        with pytest.warns(DeprecationWarning):
-            assert modutils.is_standard_module("builtins")
-
-    def test_builtin(self) -> None:
-        with pytest.warns(DeprecationWarning):
-            assert modutils.is_standard_module("sys")
-        with pytest.warns(DeprecationWarning):
-            assert modutils.is_standard_module("marshal")
-
-    def test_nonstandard(self) -> None:
-        with pytest.warns(DeprecationWarning):
-            assert not modutils.is_standard_module("astroid")
-
-    def test_unknown(self) -> None:
-        with pytest.warns(DeprecationWarning):
-            assert not modutils.is_standard_module("unknown")
-
-    def test_4(self) -> None:
-        with pytest.warns(DeprecationWarning):
-            assert modutils.is_standard_module("hashlib")
-        with pytest.warns(DeprecationWarning):
-            assert modutils.is_standard_module("pickle")
-        with pytest.warns(DeprecationWarning):
-            assert modutils.is_standard_module("email")
-        with pytest.warns(DeprecationWarning):
-            assert modutils.is_standard_module("io")
-        with pytest.warns(DeprecationWarning):
-            assert not modutils.is_standard_module("StringIO")
-        with pytest.warns(DeprecationWarning):
-            assert modutils.is_standard_module("unicodedata")
-
-    def test_custom_path(self) -> None:
-        datadir = resources.find("")
-        if any(datadir.startswith(p) for p in modutils.EXT_LIB_DIRS):
-            self.skipTest("known breakage of is_standard_module on installed 
package")
-
-        with pytest.warns(DeprecationWarning):
-            assert modutils.is_standard_module("data.module", (datadir,))
-        with pytest.warns(DeprecationWarning):
-            assert modutils.is_standard_module(
-                "data.module", (os.path.abspath(datadir),)
-            )
-        # "" will evaluate to cwd
-        with pytest.warns(DeprecationWarning):
-            assert modutils.is_standard_module("data.module", ("",))
-
-    def test_failing_edge_cases(self) -> None:
-        # using a subpackage/submodule path as std_path argument
-        with pytest.warns(DeprecationWarning):
-            assert not modutils.is_standard_module("xml.etree", etree.__path__)
-        # using a module + object name as modname argument
-        with pytest.warns(DeprecationWarning):
-            assert modutils.is_standard_module("sys.path")
-        # this is because only the first package/module is considered
-        with pytest.warns(DeprecationWarning):
-            assert modutils.is_standard_module("sys.whatever")
-        with pytest.warns(DeprecationWarning):
-            assert not modutils.is_standard_module("xml.whatever", 
etree.__path__)
-
-
 class IsStdLibModuleTest(resources.SysPathSetup, unittest.TestCase):
     """
     Return true if the module is path of the standard library
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/tests/test_nodes.py 
new/astroid-4.2.0/tests/test_nodes.py
--- old/astroid-4.1.2/tests/test_nodes.py       2026-03-22 16:06:01.000000000 
+0100
+++ new/astroid-4.2.0/tests/test_nodes.py       2026-04-28 11:27:11.000000000 
+0200
@@ -427,11 +427,22 @@
             pass
         else:
             raise
+
+        if 1:
+            print()
+        elif (
+            2
+            and 3
+        ):
+            print()
+        else:
+            # This is using else in a comment
+            raise
     """
 
     def test_if_elif_else_node(self) -> None:
         """Test transformation for If node."""
-        self.assertEqual(len(self.astroid.body), 4)
+        self.assertEqual(len(self.astroid.body), 5)
         for stmt in self.astroid.body:
             self.assertIsInstance(stmt, nodes.If)
         self.assertFalse(self.astroid.body[0].orelse)  # simple If
@@ -440,13 +451,50 @@
         self.assertIsInstance(self.astroid.body[3].orelse[0].orelse[0], 
nodes.If)
 
     def test_block_range(self) -> None:
-        # XXX ensure expected values
-        self.assertEqual(self.astroid.block_range(1), (0, 22))
-        self.assertEqual(self.astroid.block_range(10), (0, 22))  # XXX (10, 
22) ?
+        """Test block_range of various scope constructs"""
+        # Module
+        self.assertEqual(self.astroid.block_range(1), (0, 33))
+        # NOTE: Module does not consider the lineno argument. It would be more 
consistent to make
+        # this return (10, 33) but without a use case it seems better to not 
change behaviour.
+        self.assertEqual(self.astroid.block_range(10), (0, 33))
+
+        # if
+        self.assertEqual(self.astroid.body[0].block_range(2), (2, 3))
+        self.assertEqual(self.astroid.body[0].block_range(3), (3, 3))
+
+        # if ... else
         self.assertEqual(self.astroid.body[1].block_range(5), (5, 6))
         self.assertEqual(self.astroid.body[1].block_range(6), (6, 6))
-        self.assertEqual(self.astroid.body[1].orelse[0].block_range(7), (7, 8))
-        self.assertEqual(self.astroid.body[1].orelse[0].block_range(8), (8, 8))
+        self.assertEqual(self.astroid.body[1].block_range(7), (7, 8))
+        self.assertEqual(self.astroid.body[1].block_range(8), (8, 8))
+
+        # if ... elif
+        self.assertEqual(self.astroid.body[2].block_range(10), (10, 11))
+        self.assertEqual(self.astroid.body[2].block_range(11), (11, 11))
+        self.assertEqual(self.astroid.body[2].block_range(12), (12, 13))
+        self.assertEqual(self.astroid.body[2].block_range(13), (13, 13))
+
+        # if ... elif ... elif ... else
+        self.assertEqual(self.astroid.body[3].block_range(15), (15, 16))
+        self.assertEqual(self.astroid.body[3].block_range(16), (16, 16))
+        self.assertEqual(self.astroid.body[3].block_range(17), (17, 18))
+        self.assertEqual(self.astroid.body[3].block_range(18), (18, 18))
+        self.assertEqual(self.astroid.body[3].block_range(19), (19, 20))
+        self.assertEqual(self.astroid.body[3].block_range(20), (20, 20))
+        self.assertEqual(self.astroid.body[3].block_range(21), (21, 22))
+        self.assertEqual(self.astroid.body[3].block_range(22), (22, 22))
+
+        # if ... elif ... else
+        self.assertEqual(self.astroid.body[4].block_range(24), (24, 25))
+        self.assertEqual(self.astroid.body[4].block_range(25), (25, 25))
+        self.assertEqual(self.astroid.body[4].block_range(26), (26, 30))
+        self.assertEqual(self.astroid.body[4].block_range(27), (27, 30))
+        self.assertEqual(self.astroid.body[4].block_range(28), (28, 30))
+        self.assertEqual(self.astroid.body[4].block_range(29), (29, 30))
+        self.assertEqual(self.astroid.body[4].block_range(30), (30, 30))
+        self.assertEqual(self.astroid.body[4].block_range(31), (31, 33))
+        self.assertEqual(self.astroid.body[4].block_range(32), (32, 33))
+        self.assertEqual(self.astroid.body[4].block_range(33), (33, 33))
 
 
 class TryNodeTest(_NodeTest):
@@ -466,81 +514,18 @@
     def test_block_range(self) -> None:
         try_node = self.astroid.body[0]
         assert try_node.block_range(1) == (1, 11)
-        assert try_node.block_range(2) == (2, 2)
+        assert try_node.block_range(2) == (2, 3)
         assert try_node.block_range(3) == (3, 3)
-        assert try_node.block_range(4) == (4, 4)
+        assert try_node.block_range(4) == (4, 5)
         assert try_node.block_range(5) == (5, 5)
-        assert try_node.block_range(6) == (6, 6)
+        assert try_node.block_range(6) == (6, 7)
         assert try_node.block_range(7) == (7, 7)
-        assert try_node.block_range(8) == (8, 8)
+        assert try_node.block_range(8) == (8, 9)
         assert try_node.block_range(9) == (9, 9)
-        assert try_node.block_range(10) == (10, 10)
+        assert try_node.block_range(10) == (10, 11)
         assert try_node.block_range(11) == (11, 11)
 
 
-class TryExceptNodeTest(_NodeTest):
-    CODE = """
-        try:
-            print ('pouet')
-        except IOError:
-            pass
-        except UnicodeError:
-            print()
-        else:
-            print()
-    """
-
-    def test_block_range(self) -> None:
-        # XXX ensure expected values
-        self.assertEqual(self.astroid.body[0].block_range(1), (1, 9))
-        self.assertEqual(self.astroid.body[0].block_range(2), (2, 2))
-        self.assertEqual(self.astroid.body[0].block_range(3), (3, 3))
-        self.assertEqual(self.astroid.body[0].block_range(4), (4, 4))
-        self.assertEqual(self.astroid.body[0].block_range(5), (5, 5))
-        self.assertEqual(self.astroid.body[0].block_range(6), (6, 6))
-        self.assertEqual(self.astroid.body[0].block_range(7), (7, 7))
-        self.assertEqual(self.astroid.body[0].block_range(8), (8, 8))
-        self.assertEqual(self.astroid.body[0].block_range(9), (9, 9))
-
-
-class TryFinallyNodeTest(_NodeTest):
-    CODE = """
-        try:
-            print ('pouet')
-        finally:
-            print ('pouet')
-    """
-
-    def test_block_range(self) -> None:
-        # XXX ensure expected values
-        self.assertEqual(self.astroid.body[0].block_range(1), (1, 5))
-        self.assertEqual(self.astroid.body[0].block_range(2), (2, 2))
-        self.assertEqual(self.astroid.body[0].block_range(3), (3, 3))
-        self.assertEqual(self.astroid.body[0].block_range(4), (4, 4))
-        self.assertEqual(self.astroid.body[0].block_range(5), (5, 5))
-
-
-class TryExceptFinallyNodeTest(_NodeTest):
-    CODE = """
-        try:
-            print('pouet')
-        except Exception:
-            print ('oops')
-        finally:
-            print ('pouet')
-    """
-
-    def test_block_range(self) -> None:
-        # XXX ensure expected values
-        self.assertEqual(self.astroid.body[0].block_range(1), (1, 7))
-        self.assertEqual(self.astroid.body[0].block_range(2), (2, 2))
-        self.assertEqual(self.astroid.body[0].block_range(3), (3, 3))
-        self.assertEqual(self.astroid.body[0].block_range(4), (4, 4))
-        self.assertEqual(self.astroid.body[0].block_range(5), (5, 5))
-        self.assertEqual(self.astroid.body[0].block_range(6), (6, 6))
-        self.assertEqual(self.astroid.body[0].block_range(7), (7, 7))
-
-
 class ImportNodeTest(resources.SysPathSetup, unittest.TestCase):
     def setUp(self) -> None:
         super().setUp()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/tests/test_nodes_lineno.py 
new/astroid-4.2.0/tests/test_nodes_lineno.py
--- old/astroid-4.1.2/tests/test_nodes_lineno.py        2026-03-22 
16:06:01.000000000 +0100
+++ new/astroid-4.2.0/tests/test_nodes_lineno.py        2026-04-28 
11:27:11.000000000 +0200
@@ -878,6 +878,10 @@
         assert (w1.body[0].end_lineno, w1.body[0].end_col_offset) == (2, 8)
         assert (w1.orelse[0].lineno, w1.orelse[0].col_offset) == (4, 4)
         assert (w1.orelse[0].end_lineno, w1.orelse[0].end_col_offset) == (4, 8)
+        assert w1.block_range(1) == (1, 2)
+        assert w1.block_range(2) == (2, 2)
+        assert w1.block_range(3) == (3, 4)
+        assert w1.block_range(4) == (4, 4)
 
     @staticmethod
     def test_end_lineno_string() -> None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/tests/test_raw_building.py 
new/astroid-4.2.0/tests/test_raw_building.py
--- old/astroid-4.1.2/tests/test_raw_building.py        2026-03-22 
16:06:01.000000000 +0100
+++ new/astroid-4.2.0/tests/test_raw_building.py        2026-04-28 
11:27:11.000000000 +0200
@@ -10,7 +10,7 @@
 
 from __future__ import annotations
 
-import _io  # pylint: disable=wrong-import-order
+import _io
 import logging
 import os
 import sys
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/tests/test_regrtest.py 
new/astroid-4.2.0/tests/test_regrtest.py
--- old/astroid-4.1.2/tests/test_regrtest.py    2026-03-22 16:06:01.000000000 
+0100
+++ new/astroid-4.2.0/tests/test_regrtest.py    2026-04-28 11:27:11.000000000 
+0200
@@ -12,7 +12,7 @@
 
 from astroid import MANAGER, Instance, bases, manager, nodes, parse, test_utils
 from astroid.builder import AstroidBuilder, _extract_single_node, extract_node
-from astroid.const import PY312_PLUS
+from astroid.const import PY312_PLUS, PY315_PLUS
 from astroid.context import InferenceContext
 from astroid.exceptions import AstroidSyntaxError, InferenceError
 from astroid.manager import AstroidManager
@@ -529,6 +529,9 @@
     assert inferred.value == Uninferable
 
 
+# On Python 3.15+ the parser emits a regular SyntaxError instead of a 
MemoryError for deeply nested
+# parentheses, so the special-case test here is no longer needed.
[email protected](PY315_PLUS, reason="No longer a MemoryError on Python 
3.15+")
 def test_regression_parse_deeply_nested_parentheses() -> None:
     """Regression test for issue #2643."""
     with pytest.raises(AstroidSyntaxError, match="Parsing Python code 
failed:") as ctx:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/tests/test_scoped_nodes.py 
new/astroid-4.2.0/tests/test_scoped_nodes.py
--- old/astroid-4.1.2/tests/test_scoped_nodes.py        2026-03-22 
16:06:01.000000000 +0100
+++ new/astroid-4.2.0/tests/test_scoped_nodes.py        2026-04-28 
11:27:11.000000000 +0200
@@ -1719,6 +1719,30 @@
             ["CustomPdb", "Pdb", "Bdb", "Cmd", "object"],
         )
 
+    def test_mro_circular_name_rebinding_with_gap(self) -> None:
+        """MRO computation should handle circular name rebinding.
+
+        The MRO computation should resolve the cycle by falling back
+        to the original class.
+
+        Regression test for https://github.com/pylint-dev/pylint/issues/10821
+        """
+        astroid = builder.parse("""
+        import pdb
+
+        class PatchedPdb(pdb.Pdb):
+            pass
+
+        class CustomPdb(PatchedPdb):
+            pass
+
+        pdb.Pdb = CustomPdb
+        """)
+        self.assertEqualMro(
+            astroid["CustomPdb"],
+            ["CustomPdb", "PatchedPdb", "Pdb", "Bdb", "Cmd", "object"],
+        )
+
     def test_mro_with_factories(self) -> None:
         cls = builder.extract_node("""
         def MixinFactory(cls):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/astroid-4.1.2/tox.ini new/astroid-4.2.0/tox.ini
--- old/astroid-4.1.2/tox.ini   2026-03-22 16:06:01.000000000 +0100
+++ new/astroid-4.2.0/tox.ini   2026-04-28 11:27:11.000000000 +0200
@@ -1,5 +1,5 @@
 [tox]
-envlist = py{39,310,311,312,313,314}
+envlist = py{39,310,311,312,313,314,315}
 skip_missing_interpreters = true
 isolated_build = true
 

Reply via email to