Skip to content

Commit f19478e

Browse files
authored
Update operator from 3.13.5 (RustPython#5935)
1 parent c4234c1 commit f19478e

File tree

3 files changed

+98
-9
lines changed

3 files changed

+98
-9
lines changed

Lib/operator.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ class attrgetter:
239239
"""
240240
__slots__ = ('_attrs', '_call')
241241

242-
def __init__(self, attr, *attrs):
242+
def __init__(self, attr, /, *attrs):
243243
if not attrs:
244244
if not isinstance(attr, str):
245245
raise TypeError('attribute name must be a string')
@@ -257,7 +257,7 @@ def func(obj):
257257
return tuple(getter(obj) for getter in getters)
258258
self._call = func
259259

260-
def __call__(self, obj):
260+
def __call__(self, obj, /):
261261
return self._call(obj)
262262

263263
def __repr__(self):
@@ -276,7 +276,7 @@ class itemgetter:
276276
"""
277277
__slots__ = ('_items', '_call')
278278

279-
def __init__(self, item, *items):
279+
def __init__(self, item, /, *items):
280280
if not items:
281281
self._items = (item,)
282282
def func(obj):
@@ -288,7 +288,7 @@ def func(obj):
288288
return tuple(obj[i] for i in items)
289289
self._call = func
290290

291-
def __call__(self, obj):
291+
def __call__(self, obj, /):
292292
return self._call(obj)
293293

294294
def __repr__(self):
@@ -315,7 +315,7 @@ def __init__(self, name, /, *args, **kwargs):
315315
self._args = args
316316
self._kwargs = kwargs
317317

318-
def __call__(self, obj):
318+
def __call__(self, obj, /):
319319
return getattr(obj, self._name)(*self._args, **self._kwargs)
320320

321321
def __repr__(self):

Lib/test/test_operator.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import unittest
2+
import inspect
23
import pickle
34
import sys
5+
from decimal import Decimal
6+
from fractions import Fraction
47

58
from test import support
69
from test.support import import_helper
@@ -508,6 +511,44 @@ def __getitem__(self, other): return 5 # so that C is a sequence
508511
self.assertEqual(operator.ixor (c, 5), "ixor")
509512
self.assertEqual(operator.iconcat (c, c), "iadd")
510513

514+
def test_iconcat_without_getitem(self):
515+
operator = self.module
516+
517+
msg = "'int' object can't be concatenated"
518+
with self.assertRaisesRegex(TypeError, msg):
519+
operator.iconcat(1, 0.5)
520+
521+
def test_index(self):
522+
operator = self.module
523+
class X:
524+
def __index__(self):
525+
return 1
526+
527+
self.assertEqual(operator.index(X()), 1)
528+
self.assertEqual(operator.index(0), 0)
529+
self.assertEqual(operator.index(1), 1)
530+
self.assertEqual(operator.index(2), 2)
531+
with self.assertRaises((AttributeError, TypeError)):
532+
operator.index(1.5)
533+
with self.assertRaises((AttributeError, TypeError)):
534+
operator.index(Fraction(3, 7))
535+
with self.assertRaises((AttributeError, TypeError)):
536+
operator.index(Decimal(1))
537+
with self.assertRaises((AttributeError, TypeError)):
538+
operator.index(None)
539+
540+
def test_not_(self):
541+
operator = self.module
542+
class C:
543+
def __bool__(self):
544+
raise SyntaxError
545+
self.assertRaises(TypeError, operator.not_)
546+
self.assertRaises(SyntaxError, operator.not_, C())
547+
self.assertFalse(operator.not_(5))
548+
self.assertFalse(operator.not_([0]))
549+
self.assertTrue(operator.not_(0))
550+
self.assertTrue(operator.not_([]))
551+
511552
def test_length_hint(self):
512553
operator = self.module
513554
class X(object):
@@ -533,6 +574,13 @@ def __length_hint__(self):
533574
with self.assertRaises(LookupError):
534575
operator.length_hint(X(LookupError))
535576

577+
class Y: pass
578+
579+
msg = "'str' object cannot be interpreted as an integer"
580+
with self.assertRaisesRegex(TypeError, msg):
581+
operator.length_hint(X(2), "abc")
582+
self.assertEqual(operator.length_hint(Y(), 10), 10)
583+
536584
def test_call(self):
537585
operator = self.module
538586

@@ -555,13 +603,53 @@ def test_dunder_is_original(self):
555603
if dunder:
556604
self.assertIs(dunder, orig)
557605

606+
@support.requires_docstrings
607+
def test_attrgetter_signature(self):
608+
operator = self.module
609+
sig = inspect.signature(operator.attrgetter)
610+
self.assertEqual(str(sig), '(attr, /, *attrs)')
611+
sig = inspect.signature(operator.attrgetter('x', 'z', 'y'))
612+
self.assertEqual(str(sig), '(obj, /)')
613+
614+
@support.requires_docstrings
615+
def test_itemgetter_signature(self):
616+
operator = self.module
617+
sig = inspect.signature(operator.itemgetter)
618+
self.assertEqual(str(sig), '(item, /, *items)')
619+
sig = inspect.signature(operator.itemgetter(2, 3, 5))
620+
self.assertEqual(str(sig), '(obj, /)')
621+
622+
@support.requires_docstrings
623+
def test_methodcaller_signature(self):
624+
operator = self.module
625+
sig = inspect.signature(operator.methodcaller)
626+
self.assertEqual(str(sig), '(name, /, *args, **kwargs)')
627+
sig = inspect.signature(operator.methodcaller('foo', 2, y=3))
628+
self.assertEqual(str(sig), '(obj, /)')
629+
630+
558631
class PyOperatorTestCase(OperatorTestCase, unittest.TestCase):
559632
module = py_operator
560633

561634
@unittest.skipUnless(c_operator, 'requires _operator')
562635
class COperatorTestCase(OperatorTestCase, unittest.TestCase):
563636
module = c_operator
564637

638+
# TODO: RUSTPYTHON
639+
@unittest.expectedFailure
640+
def test_attrgetter_signature(self):
641+
super().test_attrgetter_signature()
642+
643+
# TODO: RUSTPYTHON
644+
@unittest.expectedFailure
645+
def test_itemgetter_signature(self):
646+
super().test_itemgetter_signature()
647+
648+
# TODO: RUSTPYTHON
649+
@unittest.expectedFailure
650+
def test_methodcaller_signature(self):
651+
super().test_methodcaller_signature()
652+
565653

566654
class OperatorPickleTestCase:
567655
def copy(self, obj, proto):

vm/src/stdlib/operator.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ mod _operator {
225225
.map(|v| {
226226
if !v.fast_isinstance(vm.ctx.types.int_type) {
227227
return Err(vm.new_type_error(format!(
228-
"'{}' type cannot be interpreted as an integer",
228+
"'{}' object cannot be interpreted as an integer",
229229
v.class().name()
230230
)));
231231
}
@@ -253,9 +253,10 @@ mod _operator {
253253
if !a.class().has_attr(identifier!(vm, __getitem__))
254254
|| a.fast_isinstance(vm.ctx.types.dict_type)
255255
{
256-
return Err(
257-
vm.new_type_error(format!("{} object can't be concatenated", a.class().name()))
258-
);
256+
return Err(vm.new_type_error(format!(
257+
"'{}' object can't be concatenated",
258+
a.class().name()
259+
)));
259260
}
260261
vm._iadd(&a, &b)
261262
}

0 commit comments

Comments
 (0)