Skip to content

Releases

v4.3.4

Choose a tag to compare

@Pierre-Sassoulas Pierre-Sassoulas released this 08 Oct 09:36

What's new in astroid 4.3.4?

Release date: 2026-10-08

Bug Fixes

  • Fix a RecursionError when building a module from a live object that holds a
    container containing itself.

    Closes #2974
    Closes pylint-dev/pylint#10459

  • Arguments.default_value() no longer raises IndexError when a keyword-only
    argument repeats the name of *args or **kwargs, as in def f(x, *y, y).

    Closes #3259

  • Fix an infinite loop when introspecting a live class that exposes itself, or a
    sibling class, as one of its own attributes.

    Closes #3284

  • Fix a TypeError crash when inferring random.sample() on a sequence whose
    elements are inferred as Instance.

    Closes #3310

  • Catch ValueError during comparison inference (such as invalid byte values in bytes membership checks) and return Uninferable instead of raising an uncaught exception.

    Closes #3333

  • A function whose body is only ... is now inferred to return Uninferable
    instead of None, the same as a function whose body is only pass. This
    is the astroid part of the fix for a false positive not-callable in pylint
    when calling a ... property stub, such as the sqlalchemy.func helpers.

    Refs #3347
    Refs pylint-dev/pylint#8138

v4.3.3

Choose a tag to compare

@Pierre-Sassoulas Pierre-Sassoulas released this 30 Sep 05:52

What's new in astroid 4.3.3?

Release date: 2026-09-30

Bug Fixes

  • Preserve the length of inferred list and tuple concatenations when an element
    has multiple possible values. An ambiguous or uninferable element is now
    represented as unknown instead of being expanded into multiple sequence items.

    Refs #3221
    Closes pylint-dev/pylint#2621

  • Fix TypeError in ClassDef.getitem when __class_getitem__ is uninferable.

    Closes #3312

  • Fix AssertionError in NodeNG.root() when inferring Class.__bases__, which previously returned a parentless Tuple.

    Closes pylint-dev/pylint#11491

v4.3.2

Choose a tag to compare

@Pierre-Sassoulas Pierre-Sassoulas released this 25 Sep 20:53

What's new in astroid 4.3.2?

Release date: 2026-09-25

Bug Fixes

  • Fix a crash when a namedtuple or Enum type name or field name
    contains str.format markup, as in namedtuple("{0}", "abc"). The name
    is interpolated into an error message that astroid then reformats, so
    building the message raised IndexError. Inference now falls back to its
    default.

    Closes #3199

  • Infer a functional TypeVar or NewType whose name is not an identifier
    without splicing that name into the synthesized class source. A crafted value
    such as TypeVar("T(Base): #") no longer breaks out of the identifier
    position to inject bases or a body; the name is assigned to the class verbatim.

    Refs #3217

  • Raise InferenceError instead of crashing with IndexError when a class
    uses six.with_metaclass() with no positional metaclass argument, both while
    building the module and when the call is inferred.

    Refs #3248

  • ClassDef.slots() no longer crashes on a class that declares a PEP 695
    type parameter literally named __slots__ (e.g. class C[__slots__]:).
    The type parameter's TypeVar node was mistaken for the class's actual
    __slots__ value; slots() now returns None for such classes
    instead of raising AttributeError.

    Refs #3258

  • Fix a crash when inferring an f-string or str.format() call whose c format
    spec gets an out-of-range code point, such as f"{-1:c}". These now infer to
    Uninferable, like the %c case fixed in #3254.

    Closes #3301

  • The args attribute of an exception instance is now inferred as a tuple
    instance of unknown contents instead of a known empty tuple, so unpacking
    exc.args no longer looks unbalanced.

    Closes pylint-dev/pylint#11312

v4.3.1

Choose a tag to compare

@Pierre-Sassoulas Pierre-Sassoulas released this 17 Aug 08:21
4ea15d4

What's New in astroid 4.3.1?

Release date: 2026-08-17

  • Fix inference of the attributes of a namedtuple created with
    rename=True. The renamed fields were applied to _fields and to the
    class body, but the instance kept the field names as written, so an instance
    of namedtuple("Tuple", "abc def", rename=True) was inferred as having a
    def attribute instead of _1, and duplicate field names collapsed into
    a single attribute instead of being renamed.

    Closes #242

v4.3.0

Choose a tag to compare

@Pierre-Sassoulas Pierre-Sassoulas released this 07 Aug 20:27

What's New in astroid 4.3.0?

Release date: 2026-08-07

Version 4.2.0 was skipped: a v4.2.0 tag was created by mistake during an
aborted release attempt, so the changes from the 4.2.0 betas are released
as 4.3.0.

  • Fix a crash on a functional namedtuple whose field name changes under NFKC
    normalization, such as namedtuple("mu", ["µ"]). Python normalizes
    identifiers, so the parsed class stores the field under "μ" while the
    brain looked it up as written, raising KeyError on a definition that
    namedtuple itself accepts.

    Closes pylint-dev/pylint#8746

  • Fix inference of a method's first argument (self or cls) when the
    method's return value is stored on an unrelated object. This avoids inferring
    cls as the caller's class when indexing a tuple returned by a
    classmethod such as A.c()[0].

    Closes pylint-dev/pylint#11101

  • super() with no argument now resolves against the class of the object the
    method was called on, instead of the class the method is written in. One consequence
    is that a typing.Self return value survives a chain of super() calls.

    Closes #2852
    Closes pylint-dev/pylint#10807

  • typing.overload stubs no longer shadow the implementation when a special
    method is looked up in the MRO.

    Closes #2448

  • Fix a crash when the field names of a functional Enum or namedtuple
    call are bytes, as in Enum("", b""). Such a definition is invalid, so
    inference now falls back to its default instead of raising TypeError.

    Closes #3189

  • Fix a crash when the body of a typing.NamedTuple subclass contains an
    assignment whose target is not a single name, such as cat.color = "black",
    basket[0] = "apple" or apple, banana = "red", "yellow". The names bound
    by unpacking are now copied to the inferred class as well.

    Closes #3190

  • Fix a crash when a binary operation involves a class whose metaclass is not a
    class, as in class C(metaclass=sum) followed by C | None. The type of
    such a class is a function, which has no bases, so has_known_bases() now
    returns False for anything that is not a class.

    Closes #3191

  • Fix a crash when a dataclass inherits from a dataclass that annotates
    __init__ as a field, as in __init__: int. Such a base binds
    __init__ to a name instead of a function, so it no longer contributes
    arguments to the generated __init__.

    Closes #3200

  • The documentation build now fails on any Sphinx warning, so a cross-reference
    that does not resolve is caught by CI instead of quietly rendering as plain
    text. Uninferable, Position and the BadOperationMessage classes
    are documented as part of the public API, and a number of docstrings that
    Sphinx could not parse were repaired.

  • The >>> examples in the documentation are run when the documentation is
    built, so one that stops being true is noticed. Most of them could not run
    before: they printed node addresses recorded in 2018, and the multi-line ones
    were missing the ... continuation prompt. The example for Decorators
    reported the wrong line numbers.

  • Fix the example in the docstring of BoolOp, which showed the node it was
    copied from: astroid.extract_node("a and b") gives a BoolOp, not a
    BinOp.

  • Names written between single backticks in the ChangeLog render as code again,
    rather than as italics.

  • Prevent crashes while processing extension-module classes whose bases cannot
    be resolved when applying enum inference transformations.

    Closes pylint-dev/pylint#11179

  • The API documentation now covers the proxies, the objects with no node of
    their own, the inference context, the manager, the object models and the
    extension call signatures. The EvaluatedObject, Interpolation,
    NamedExpr and TemplateStr nodes were missing from the list of nodes
    and are listed now.

  • Add __required_keys__ and __optional_keys__ to the inferred
    TypedDict base class, so subclasses no longer raise a no-member
    false positive in pylint when accessing those attributes at runtime.

    Closes pylint-dev/pylint#10158

  • Comprehension conditions now constrain the inference of names used in the
    comprehension, like if statement conditions already did:
    [x for x in lst if x is not None] no longer infers None for x
    in the element expression.

    Refs #3094

  • Fix isinstance() constraints only filtering the first inferred value of
    a variable: checking a value made the isinstance classinfo uninferable
    for the checks of the following values.

  • Remove Python 2 era dead code and outdated comments.
    Notably: the internal TreeRebuilder constructor no longer takes a
    parser_module argument.

    Refs #3154

  • Fix inference of a starred target that is not last in a for loop, such as
    for a, *b, c in .... The elements following the starred one were counted
    from the target's own arity rather than from the end of the iterable, so
    b was truncated whenever the iterable was longer than the target.

  • Add qname() method to the Slice node class, returning
    "builtins.slice", so that the node can be used in contexts
    that require a qualified name (e.g. pylint's basic_checker).

    Closes #3115

  • Add brain tip for numpy.fromfile so that calls to
    np.fromfile(...) are correctly inferred as returning
    numpy.ndarray instead of Uninferable.

    Closes #600

  • Add brain for decimal that gets applied if _decimal isn't available.

  • Removed the **kwargs argument from all infer functions.
    Users upgrading their astroid versions should ensure they do no pass values other than
    context to infer.

  • Deduplicate keys when inferring dict.fromkeys. dict.fromkeys("aab")
    now infers a dict with keys "a", "b" instead of "a", "a",
    "b", matching the runtime. This also stops dict.fromkeys from
    materializing one Const node per character for a repeated string such as
    dict.fromkeys("x" * 10 ** 8), which is a single-key dict.

  • Bound str/bytes and list/tuple concatenation (a + b) during inference.

  • Bound oversized old-style (%) string/bytes formatting during inference.
    A tiny literal such as "%1000000000d" % 1 made
    _infer_old_style_string_formatting eagerly build a multi-gigabyte
    Const while inferring otherwise untrusted source. The width and
    precision are now read out of the conversion specifiers (including *
    fields) and the interpolation infers as Uninferable past 1e8,
    mirroring the repetition, concatenation and str.format caps. Bytes
    % formatting is routed through the same handler so it is bounded too;
    small format strings keep inferring their exact value.

  • Fix crash (TypeError: 'UninferableBase' object is not iterable) in the
    multiprocessing brain when a local package shadows the stdlib
    multiprocessing module.

    Closes pylint-dev/pylint#10014

  • Bound the number of nodes built when inferring list/set/tuple/
    frozenset and dict.fromkeys from a str/bytes constant. These
    built one Const node per character with no cap, so ``list(("a" * 10 ** 8)

    • "b")(concatenation is not size-bounded) materialized hundreds of millions of nodes. They now fall back to the default inference past1e8`` characters,
      matching the sequence-repetition guard.

Refs #3127

  • Bound string/bytes multiplication ("x" * n) and integer left shifts
    (1 << n) in const_infer_binary_op the same way list/tuple
    multiplication and ** already are. Inferring a constant such as
    "A" * 10 ** 10 previously materialized the multi-gigabyte result
    eagerly; these operations now infer as Uninferable when the result
    would be oversized.

    Refs #3107

  • Bound the field width and precision when inferring str.format calls.
    A template such as "{:>2000000000}".format("x") (or a width/precision
    supplied through a nested {} field) previously built the padded
    multi-gigabyte string eagerly during inference; such calls now infer as
    Uninferable when the field size would be oversized.

    Refs #3131

  • Remove the asname keyword argument from Import._infer and
    ImportFrom._infer. The alias-to-real-name translation that
    asname=True performed is now hoisted into ImportNode._infer_name,
    which runs in _infer_stmts before _infer is dispatched. Direct
    callers of Import.infer / ImportFrom.infer (previously the
    asname=False path) now consistently resolve the lookup name as-is.

    The two flows used to collapse into a single inference cache entry
    because the asname kwarg was not part of the cache key, so the
    second call returned the cached result of the first regardless of
    which one ran. With the translation hoisted upstream, the two flows
    set different lookupname values and therefore land on distinct
    cache keys, eliminating the collision.

    Refs pylint-dev/pylint#10193
    Closes #3007

  • Avoid materializing a multi-gigabyte string while inferring a small literal
    such as "{:>2000000000}".format("x") or f"{1.5:.2000000000f}".
    _infer_str_format_call and FormattedValue._infer now yield
    Uninferable when a format spec asks for a width or precision over 1e8,
    mirroring the sequence/repetition caps in astroid.protocols.

Refs #3108

  • Fix uncaught IndentationError when parsing code whose lines end in
    \r: the slice of source tokenized to compute a class or function
    position is split on \n only and could be misaligned with the AST
    line numbers. ...
Read more

v4.2.0b5

v4.2.0b5 Pre-release
Pre-release

Choose a tag to compare

@DanielNoord DanielNoord released this 27 Jul 07:04

What's New in astroid 4.2.0b5?

Release date: 2026-07-27

  • Comprehension conditions now constrain the inference of names used in the
    comprehension, like if statement conditions already did:
    [x for x in lst if x is not None] no longer infers None for x
    in the element expression.

    Refs #3094

  • Fix isinstance() constraints only filtering the first inferred value of
    a variable: checking a value made the isinstance classinfo uninferable
    for the checks of the following values.

  • Fix inference of a starred target that is not last in a for loop, such as
    for a, *b, c in .... The elements following the starred one were counted
    from the target's own arity rather than from the end of the iterable, so
    b was truncated whenever the iterable was longer than the target.

  • Add qname() method to the Slice node class, returning
    "builtins.slice", so that the node can be used in contexts
    that require a qualified name (e.g. pylint's basic_checker).

    Closes #3115

  • Add brain tip for numpy.fromfile so that calls to
    np.fromfile(...) are correctly inferred as returning
    numpy.ndarray instead of Uninferable.

    Closes #600

  • Add brain for decimal that gets applied if _decimal isn't available.

  • Removed the **kwargs argument from all infer functions.
    Users upgrading their astroid versions should ensure they do no pass values other than
    context to infer.

  • Deduplicate keys when inferring dict.fromkeys. dict.fromkeys("aab")
    now infers a dict with keys "a", "b" instead of "a", "a",
    "b", matching the runtime. This also stops dict.fromkeys from
    materializing one Const node per character for a repeated string such as
    dict.fromkeys("x" * 10 ** 8), which is a single-key dict.

  • Fix crash (TypeError: 'UninferableBase' object is not iterable) in the
    multiprocessing brain when a local package shadows the stdlib
    multiprocessing module.

    Closes pylint-dev/pylint#10014

  • Bound string/bytes multiplication ("x" * n) and integer left shifts
    (1 << n) in const_infer_binary_op the same way list/tuple
    multiplication and ** already are. Inferring a constant such as
    "A" * 10 ** 10 previously materialized the multi-gigabyte result
    eagerly; these operations now infer as Uninferable when the result
    would be oversized.

    Refs #3107

  • Remove the asname keyword argument from Import._infer and
    ImportFrom._infer. The alias-to-real-name translation that
    asname=True performed is now hoisted into ImportNode._infer_name,
    which runs in _infer_stmts before _infer is dispatched. Direct
    callers of Import.infer / ImportFrom.infer (previously the
    asname=False path) now consistently resolve the lookup name as-is.

    The two flows used to collapse into a single inference cache entry
    because the asname kwarg was not part of the cache key, so the
    second call returned the cached result of the first regardless of
    which one ran. With the translation hoisted upstream, the two flows
    set different lookupname values and therefore land on distinct
    cache keys, eliminating the collision.

    Refs pylint-dev/pylint#10193
    Closes #3007

  • Fix uncaught IndentationError when parsing code whose lines end in
    \r: the slice of source tokenized to compute a class or function
    position is split on \n only and could be misaligned with the AST
    line numbers. Such nodes now simply have no position information, as
    already done when tokenize raises TokenError.

    Closes #3091

  • Support PEP 810 lazy imports (new in Python 3.15). Import and
    ImportFrom nodes gain a lazy boolean attribute.

  • Support PEP 798 comprehension unpacking ({**d for d in dicts},
    new in Python 3.15).

  • Fix astroid bootstrap crash on PyPy 7.3.22 (TypeError: expected str, got getset_descriptor object) by also catching TypeError from
    getattr(obj, alias) in InspectBuilder.object_build. PyPy 7.3.22
    raises TypeError instead of AttributeError for unset getset
    descriptors like types.FunctionType.__text_signature__, which made
    _astroid_bootstrapping() blow up on any call into astroid.

    Refs pylint-dev/pylint#10999

  • Shorten import astroid by deferring imports only needed on cold paths.
    logging (used by modutils and raw_building solely to report
    stderr/stdout captured while importing a module) and pprint (used only
    to format debug __repr__ / repr_tree output) are now imported
    lazily, and astroid.exceptions imports astroid.typing under
    TYPE_CHECKING.

  • Fix AttributeError crash in starred_assigned_stmts when a starred
    unpacking target is an attribute (e.g. for *o.attr, x in ...) rather
    than a simple name.

    Closes #2646

  • Fix AttributeError crash in the Arguments assigned_stmts
    protocol when called without an inference context (the public
    assigned_stmts API defaults context to None). Resolving a
    function's first parameter dereferenced context.boundnode while the
    matching context and ... guard a few lines below was missing; it now
    degrades to Uninferable.

  • Fix AttributeError crash in ClassDef.infer_call_result when called
    through the public API without a context (it defaults to None) for a
    class whose metaclass defines __call__: the callee was assigned to
    context.callcontext.callee without checking that a call context exists.
    It is now guarded, matching the surrounding code.

  • Wrap assignment expressions (:=) in parentheses when emitting
    as_string output so the rendered code remains syntactically valid in
    contexts such as comparisons, where Python requires the walrus expression
    to be parenthesized.

    Closes #2668

  • Catch MemoryError/RecursionError (and ValueError) when validating
    type comments with ast.parse. Pathological type comments produced by
    fuzzers (e.g. # type: i{{{{{{{...) previously crashed parsing with a
    MemoryError or RecursionError depending on the runtime; astroid now
    treats them as invalid type comments and skips them, mirroring the f-string
    fix from #2762.

    Closes #2993

  • Fix TypeError in brain_random when random.sample is called with a
    sequence containing nodes whose __init__ does not accept lineno
    (e.g. Module). The clone helper now filters init params to those the
    class actually accepts.

    Closes #3043

  • 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

  • Fix uncaught TokenError when building a class or function whose source
    slice is malformed. tokenize.generate_tokens may raise (e.g. on an
    unterminated bracket on Python < 3.12); position computation now treats such
    a node as having no position information instead of crashing.

    Closes #2527

  • str() of a constant argument now infers the actual string value instead
    of always inferring "". When every inference path of the argument
    resolves to Const values that stringify to the same string, infer_str
    returns that string; otherwise it keeps falling back to Const("").

    Closes #2994

  • Fix AttributeError crash when looking up a special method on a class
    whose explicit metaclass infers to a non-class node (e.g. a function). Such
    a metaclass has no MRO, so the dunder lookup now raises
    AttributeInferenceError instead of crashing.

    Closes #3063

  • Fix AttributeError crash in ClassDef.getitem when __class_getitem__
    resolves to a non-callable node (e.g. an AssignName). getitem now
    raises AstroidTypeError in that case, consistent with its documented
    behaviour.

    Closes #3064

  • Fix DuplicateBasesError crash in the enum brain when inferring an enum
    class with duplicate bases (e.g. class C(enum.Enum, enum.Enum)).
    infer_enum_class now catches MroError and leaves such a malformed
    class untransformed.

    Closes #3065

  • Fix InferenceError crash in ClassDef.slots() when __slots__ is
    declared as an annotation without a value (e.g. __slots__: None). Such a
    __slots__ cannot be inferred, so slots() now returns None.

    Closes #3067

  • Fix TypeError crash in the enum brain when a functional Enum call
    has a non-string member name (e.g. Enum("e", (1,))). Such a definition
    is invalid, so inference now falls back to the default instead of crashing.

    Closes #3068

  • Fix detecting static/class methods and inspecting IntFlag types in
    GObject-based libraries (GLib, Gtk etc)

Note that this changelog also includes changes from previous betas.

v4.2.0b4

v4.2.0b4 Pre-release
Pre-release

Choose a tag to compare

@DanielNoord DanielNoord released this 04 Jul 17:06

What's New in astroid 4.2.0b4?

Release date: 2026-07-04

  • Removed the **kwargs argument from all infer functions.
    Users upgrading their astroid versions should ensure they do no pass values other than
    context to infer.

  • Fix crash (TypeError: 'UninferableBase' object is not iterable) in the
    multiprocessing brain when a local package shadows the stdlib
    multiprocessing module.

    Closes pylint-dev/pylint#10014

  • Bound string/bytes multiplication ("x" * n) and integer left shifts
    (1 << n) in const_infer_binary_op the same way list/tuple
    multiplication and ** already are. Inferring a constant such as
    "A" * 10 ** 10 previously materialized the multi-gigabyte result
    eagerly; these operations now infer as Uninferable when the result
    would be oversized.

    Refs #3107

  • Remove the asname keyword argument from Import._infer and
    ImportFrom._infer. The alias-to-real-name translation that
    asname=True performed is now hoisted into ImportNode._infer_name,
    which runs in _infer_stmts before _infer is dispatched. Direct
    callers of Import.infer / ImportFrom.infer (previously the
    asname=False path) now consistently resolve the lookup name as-is.

    The two flows used to collapse into a single inference cache entry
    because the asname kwarg was not part of the cache key, so the
    second call returned the cached result of the first regardless of
    which one ran. With the translation hoisted upstream, the two flows
    set different lookupname values and therefore land on distinct
    cache keys, eliminating the collision.

    Refs pylint-dev/pylint#10193
    Closes #3007

  • Fix uncaught IndentationError when parsing code whose lines end in
    \r: the slice of source tokenized to compute a class or function
    position is split on \n only and could be misaligned with the AST
    line numbers. Such nodes now simply have no position information, as
    already done when tokenize raises TokenError.

    Closes #3091

  • Fix astroid bootstrap crash on PyPy 7.3.22 (TypeError: expected str, got getset_descriptor object) by also catching TypeError from
    getattr(obj, alias) in InspectBuilder.object_build. PyPy 7.3.22
    raises TypeError instead of AttributeError for unset getset
    descriptors like types.FunctionType.__text_signature__, which made
    _astroid_bootstrapping() blow up on any call into astroid.

    Refs pylint-dev/pylint#10999

  • Shorten import astroid by deferring imports only needed on cold paths.
    logging (used by modutils and raw_building solely to report
    stderr/stdout captured while importing a module) and pprint (used only
    to format debug __repr__ / repr_tree output) are now imported
    lazily, and astroid.exceptions imports astroid.typing under
    TYPE_CHECKING.

  • Fix AttributeError crash in starred_assigned_stmts when a starred
    unpacking target is an attribute (e.g. for *o.attr, x in ...) rather
    than a simple name.

    Closes #2646

  • Fix AttributeError crash in the Arguments assigned_stmts
    protocol when called without an inference context (the public
    assigned_stmts API defaults context to None). Resolving a
    function's first parameter dereferenced context.boundnode while the
    matching context and ... guard a few lines below was missing; it now
    degrades to Uninferable.

  • Fix AttributeError crash in ClassDef.infer_call_result when called
    through the public API without a context (it defaults to None) for a
    class whose metaclass defines __call__: the callee was assigned to
    context.callcontext.callee without checking that a call context exists.
    It is now guarded, matching the surrounding code.

  • Wrap assignment expressions (:=) in parentheses when emitting
    as_string output so the rendered code remains syntactically valid in
    contexts such as comparisons, where Python requires the walrus expression
    to be parenthesized.

    Closes #2668

  • Catch MemoryError/RecursionError (and ValueError) when validating
    type comments with ast.parse. Pathological type comments produced by
    fuzzers (e.g. # type: i{{{{{{{...) previously crashed parsing with a
    MemoryError or RecursionError depending on the runtime; astroid now
    treats them as invalid type comments and skips them, mirroring the f-string
    fix from #2762.

    Closes #2993

  • Fix TypeError in brain_random when random.sample is called with a
    sequence containing nodes whose __init__ does not accept lineno
    (e.g. Module). The clone helper now filters init params to those the
    class actually accepts.

    Closes #3043

  • 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

  • Fix uncaught TokenError when building a class or function whose source
    slice is malformed. tokenize.generate_tokens may raise (e.g. on an
    unterminated bracket on Python < 3.12); position computation now treats such
    a node as having no position information instead of crashing.

    Closes #2527

  • str() of a constant argument now infers the actual string value instead
    of always inferring "". When every inference path of the argument
    resolves to Const values that stringify to the same string, infer_str
    returns that string; otherwise it keeps falling back to Const("").

    Closes #2994

  • Fix AttributeError crash when looking up a special method on a class
    whose explicit metaclass infers to a non-class node (e.g. a function). Such
    a metaclass has no MRO, so the dunder lookup now raises
    AttributeInferenceError instead of crashing.

    Closes #3063

  • Fix AttributeError crash in ClassDef.getitem when __class_getitem__
    resolves to a non-callable node (e.g. an AssignName). getitem now
    raises AstroidTypeError in that case, consistent with its documented
    behaviour.

    Closes #3064

  • Fix DuplicateBasesError crash in the enum brain when inferring an enum
    class with duplicate bases (e.g. class C(enum.Enum, enum.Enum)).
    infer_enum_class now catches MroError and leaves such a malformed
    class untransformed.

    Closes #3065

  • Fix InferenceError crash in ClassDef.slots() when __slots__ is
    declared as an annotation without a value (e.g. __slots__: None). Such a
    __slots__ cannot be inferred, so slots() now returns None.

    Closes #3067

  • Fix TypeError crash in the enum brain when a functional Enum call
    has a non-string member name (e.g. Enum("e", (1,))). Such a definition
    is invalid, so inference now falls back to the default instead of crashing.

    Closes #3068

Note that this changelog also includes changes from previous betas.

v4.2.0b3

v4.2.0b3 Pre-release
Pre-release

Choose a tag to compare

@jacobtylerwalls jacobtylerwalls released this 24 Apr 11:11

What's New in astroid 4.2.0b3?

Release date: 2026-04-24

  • 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

Note that this changelog also includes changes from previous betas.

v4.2.0b2

v4.2.0b2 Pre-release
Pre-release

Choose a tag to compare

@DanielNoord DanielNoord released this 23 Apr 18:57
00477a9

What's New in astroid 4.2.0b2?

Release date: 2026-04-23

  • 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

Note that this changelog also includes changes from previous betas.

v4.2.0b1

v4.2.0b1 Pre-release
Pre-release

Choose a tag to compare

@DanielNoord DanielNoord released this 23 Mar 08:12
0a8c390

What's New in astroid 4.2.0b1?

Release date: Release date: 2026-03-23

  • Changed block_range to consider else its own block, allowing pylint to apply
    disables to just the block.

    References pylint-dev/pylint#872