Skip to content

Commit f5b89af

Browse files
bpo-37163: Deprecate passing argument obj of dataclasses.replace() by keyword. (GH-13877)
1 parent 7edf8e5 commit f5b89af

File tree

3 files changed

+22
-1
lines changed

3 files changed

+22
-1
lines changed

Lib/dataclasses.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1206,7 +1206,7 @@ class C(Base):
12061206
unsafe_hash=unsafe_hash, frozen=frozen)
12071207

12081208

1209-
def replace(obj, **changes):
1209+
def replace(*args, **changes):
12101210
"""Return a new object replacing specified fields with new values.
12111211
12121212
This is especially useful for frozen classes. Example usage:
@@ -1220,6 +1220,17 @@ class C:
12201220
c1 = replace(c, x=3)
12211221
assert c1.x == 3 and c1.y == 2
12221222
"""
1223+
if len(args) > 1:
1224+
raise TypeError(f'replace() takes 1 positional argument but {len(args)} were given')
1225+
if args:
1226+
obj, = args
1227+
elif 'obj' in changes:
1228+
obj = changes.pop('obj')
1229+
import warnings
1230+
warnings.warn("Passing 'obj' as keyword argument is deprecated",
1231+
DeprecationWarning, stacklevel=2)
1232+
else:
1233+
raise TypeError("replace() missing 1 required positional argument: 'obj'")
12231234

12241235
# We're going to mutate 'changes', but that's okay because it's a
12251236
# new dict, even if called with 'replace(obj, **my_changes)'.
@@ -1255,3 +1266,4 @@ class C:
12551266
# changes that aren't fields, this will correctly raise a
12561267
# TypeError.
12571268
return obj.__class__(**changes)
1269+
replace.__text_signature__ = '(obj, /, **kwargs)'

Lib/test/test_dataclasses.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3075,6 +3075,13 @@ class C:
30753075
self.assertEqual(c1.x, 3)
30763076
self.assertEqual(c1.y, 2)
30773077

3078+
self.assertRaises(TypeError, replace)
3079+
self.assertRaises(TypeError, replace, c, c)
3080+
with self.assertWarns(DeprecationWarning):
3081+
c1 = replace(obj=c, x=3)
3082+
self.assertEqual(c1.x, 3)
3083+
self.assertEqual(c1.y, 2)
3084+
30783085
def test_frozen(self):
30793086
@dataclass(frozen=True)
30803087
class C:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Deprecated passing ``obj`` argument of :func:`dataclasses.replace` as
2+
keyword argument.

0 commit comments

Comments
 (0)