Skip to content

Fix GenericRepr dropping args of a secondary inspected class with no defaults - #13478

Open
uttam12331 wants to merge 1 commit into
sqlalchemy:mainfrom
uttam12331:fix/genericrepr-zero-default-slice
Open

uttam12331 wants to merge 1 commit into
sqlalchemy:mainfrom
uttam12331:fix/genericrepr-zero-default-slice

Conversation

@uttam12331

Copy link
Copy Markdown

Summary

In GenericRepr (util/langhelpers.py), the loop over to_inspect guards the argument slice with if default_len for the first inspected class (i == 0), falling back to spec.args[1:] when a class has no default arguments. The branch for subsequent inspected classes does not:

if i == 0:
    ...
    if default_len:
        pos_args.extend(spec.args[1:-default_len])
    else:
        pos_args.extend(spec.args[1:])
else:
    kw_args.update(
        [(arg, missing) for arg in spec.args[1:-default_len]]   # no guard
    )

When a secondary inspected class has no default arguments, default_len == 0, so spec.args[1:-default_len] becomes spec.args[1:-0] == spec.args[1:0] == [], and all of that class's arguments are silently dropped from the repr.

Reproduction

class Foo:            # secondary, no defaults
    def __init__(self, a): ...

class Bar(Foo):
    def __init__(self, b=2, **kw): ...

generic_repr(Bar(a="a", b="b"), to_inspect=[Bar, Foo])
# before: "Bar(b='b')"          <- 'a' dropped
# after:  "Bar(b='b', a='a')"

Fix

Mirror the i == 0 guard:

-                    [(arg, missing) for arg in spec.args[1:-default_len]]
+                    [
+                        (arg, missing)
+                        for arg in (
+                            spec.args[1:-default_len]
+                            if default_len
+                            else spec.args[1:]
+                        )
+                    ]

Tests

Added GenericReprTest.test_multi_kw_secondary_no_defaults, which fails on the previous behavior (drops the secondary class's arg) and passes with the fix.

In GenericRepr, the i == 0 branch guards the argument slice with
`if default_len` (falling back to spec.args[1:] when a class has no default
arguments), but the branch for subsequent inspected classes uses
`spec.args[1:-default_len]` unconditionally. When such a class has no
defaults, default_len is 0 and spec.args[1:-0] == spec.args[1:0] == [], so
all of its arguments are silently dropped from the repr.

Mirror the i == 0 guard so a secondary class with no defaults keeps its
arguments, and add a regression test.
@CaselIT

CaselIT commented Aug 4, 2026

Copy link
Copy Markdown
Member

Hi,

change seems fine, even if maybe not too critical

@CaselIT
CaselIT requested a review from zzzeek August 4, 2026 19:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants