diff --git a/Lib/csv.py b/Lib/csv.py index b406d82efffd9f..1bf15177aa0d3a 100644 --- a/Lib/csv.py +++ b/Lib/csv.py @@ -125,6 +125,15 @@ def __replace__(self, /, **changes): f'argument {min(unexpected)!r}') new = object.__new__(self.__class__) new.__dict__.update(self.__dict__) + # Copy slot-backed dialect attributes from the instance's MRO, + # since __dict__ only captures attributes stored in __dict__. + for cls in type(self).__mro__: + for attr in getattr(cls, '__slots__', ()): + if attr in _dialect_attributes and attr not in new.__dict__: + try: + new.__dict__[attr] = getattr(self, attr) + except AttributeError: + pass new.__dict__.update(changes) new._validate() return new diff --git a/Misc/NEWS.d/next/Library/2026-10-25-15-33-28.gh-issue-160106.G7eA2V.rst b/Misc/NEWS.d/next/Library/2026-10-25-15-33-28.gh-issue-160106.G7eA2V.rst new file mode 100644 index 00000000000000..ff1d43731b4a3d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-10-25-15-33-28.gh-issue-160106.G7eA2V.rst @@ -0,0 +1 @@ +Fix :func:`copy.replace` on :class:`csv.Dialect` subclasses losing slot-backed attributes.