Commit 89e12963 authored by Raymond Hettinger's avatar Raymond Hettinger

As discussed on python-dev, remove several operator functions

isSequenceType(), isMappingType(), and isNumberType() in favor
of using abstract base classes.  Also, remove repeat() and irepeat()
in favor of mul() and imul().

After the buildbots have had a go at this.  Will backport to Py3.0.1.
For Py2.7, will just mark as deprecated.
parent d0005ff4
...@@ -221,12 +221,6 @@ Operations which work with sequences include: ...@@ -221,12 +221,6 @@ Operations which work with sequences include:
Return the index of the first of occurrence of *b* in *a*. Return the index of the first of occurrence of *b* in *a*.
.. function:: repeat(a, b)
__repeat__(a, b)
Return ``a * b`` where *a* is a sequence and *b* is an integer.
.. function:: setitem(a, b, c) .. function:: setitem(a, b, c)
__setitem__(a, b, c) __setitem__(a, b, c)
...@@ -294,13 +288,6 @@ example, the :term:`statement` ``x += y`` is equivalent to ...@@ -294,13 +288,6 @@ example, the :term:`statement` ``x += y`` is equivalent to
``a = ipow(a, b)`` is equivalent to ``a **= b``. ``a = ipow(a, b)`` is equivalent to ``a **= b``.
.. function:: irepeat(a, b)
__irepeat__(a, b)
``a = irepeat(a, b)`` is equivalent to ``a *= b`` where *a* is a sequence and
*b* is an integer.
.. function:: irshift(a, b) .. function:: irshift(a, b)
__irshift__(a, b) __irshift__(a, b)
...@@ -324,67 +311,6 @@ example, the :term:`statement` ``x += y`` is equivalent to ...@@ -324,67 +311,6 @@ example, the :term:`statement` ``x += y`` is equivalent to
``a = ixor(a, b)`` is equivalent to ``a ^= b``. ``a = ixor(a, b)`` is equivalent to ``a ^= b``.
The :mod:`operator` module also defines a few predicates to test the type of
objects.
.. XXX just remove them?
.. note::
Be careful not to misinterpret the results of these functions; none have any
measure of reliability with instance objects.
For example:
>>> class C:
... pass
...
>>> import operator
>>> obj = C()
>>> operator.isMappingType(obj)
True
.. note::
Since there are now abstract classes for collection types, you should write,
for example, ``isinstance(obj, collections.Mapping)`` and ``isinstance(obj,
collections.Sequence)``.
.. function:: isMappingType(obj)
Returns true if the object *obj* supports the mapping interface. This is true for
dictionaries and all instance objects defining :meth:`__getitem__`.
.. warning::
There is no reliable way to test if an instance supports the complete mapping
protocol since the interface itself is ill-defined. This makes this test less
useful than it otherwise might be.
.. function:: isNumberType(obj)
Returns true if the object *obj* represents a number. This is true for all
numeric types implemented in C.
.. warning::
There is no reliable way to test if an instance supports the complete numeric
interface since the interface itself is ill-defined. This makes this test less
useful than it otherwise might be.
.. function:: isSequenceType(obj)
Returns true if the object *obj* supports the sequence protocol. This returns true
for all objects which define sequence methods in C, and for all instance objects
defining :meth:`__getitem__`.
.. warning::
There is no reliable way to test if an instance supports the complete sequence
interface since the interface itself is ill-defined. This makes this test less
useful than it otherwise might be.
Example: Build a dictionary that maps the ordinals from ``0`` to ``255`` to Example: Build a dictionary that maps the ordinals from ``0`` to ``255`` to
their character equivalents. their character equivalents.
...@@ -513,8 +439,6 @@ Python syntax and the functions in the :mod:`operator` module. ...@@ -513,8 +439,6 @@ Python syntax and the functions in the :mod:`operator` module.
+-----------------------+-------------------------+---------------------------------+ +-----------------------+-------------------------+---------------------------------+
| Right Shift | ``a >> b`` | ``rshift(a, b)`` | | Right Shift | ``a >> b`` | ``rshift(a, b)`` |
+-----------------------+-------------------------+---------------------------------+ +-----------------------+-------------------------+---------------------------------+
| Sequence Repetition | ``seq * i`` | ``repeat(seq, i)`` |
+-----------------------+-------------------------+---------------------------------+
| String Formatting | ``s % obj`` | ``mod(s, obj)`` | | String Formatting | ``s % obj`` | ``mod(s, obj)`` |
+-----------------------+-------------------------+---------------------------------+ +-----------------------+-------------------------+---------------------------------+
| Subtraction | ``a - b`` | ``sub(a, b)`` | | Subtraction | ``a - b`` | ``sub(a, b)`` |
......
...@@ -187,7 +187,7 @@ def format(percent, value, grouping=False, monetary=False, *additional): ...@@ -187,7 +187,7 @@ def format(percent, value, grouping=False, monetary=False, *additional):
formatted = _group(formatted, monetary=monetary)[0] formatted = _group(formatted, monetary=monetary)[0]
return formatted return formatted
import re, operator import re, collections
_percent_re = re.compile(r'%(?:\((?P<key>.*?)\))?' _percent_re = re.compile(r'%(?:\((?P<key>.*?)\))?'
r'(?P<modifiers>[-#0-9 +*.hlL]*?)[eEfFgGdiouxXcrs%]') r'(?P<modifiers>[-#0-9 +*.hlL]*?)[eEfFgGdiouxXcrs%]')
...@@ -207,7 +207,7 @@ def format_string(f, val, grouping=False): ...@@ -207,7 +207,7 @@ def format_string(f, val, grouping=False):
del new_val[i+1:i+1+starcount] del new_val[i+1:i+1+starcount]
i += (1 + starcount) i += (1 + starcount)
val = tuple(new_val) val = tuple(new_val)
elif operator.isMappingType(val): elif isinstance(val, collections.Mapping):
for perc in percents: for perc in percents:
key = perc.group("key") key = perc.group("key")
val[key] = format(perc.group(), val[key], grouping) val[key] = format(perc.group(), val[key], grouping)
......
...@@ -725,8 +725,6 @@ class BaseTest(unittest.TestCase): ...@@ -725,8 +725,6 @@ class BaseTest(unittest.TestCase):
self.assertRaises(BufferError, operator.setitem, a, slice(0, 0), a) self.assertRaises(BufferError, operator.setitem, a, slice(0, 0), a)
self.assertRaises(BufferError, operator.delitem, a, 0) self.assertRaises(BufferError, operator.delitem, a, 0)
self.assertRaises(BufferError, operator.delitem, a, slice(0, 1)) self.assertRaises(BufferError, operator.delitem, a, slice(0, 1))
self.assertRaises(BufferError, operator.irepeat, a, 2)
self.assertRaises(BufferError, operator.irepeat, a, 0)
def test_weakref(self): def test_weakref(self):
s = array.array(self.typecode, self.example) s = array.array(self.typecode, self.example)
......
...@@ -245,16 +245,10 @@ class BoolTest(unittest.TestCase): ...@@ -245,16 +245,10 @@ class BoolTest(unittest.TestCase):
import operator import operator
self.assertIs(operator.truth(0), False) self.assertIs(operator.truth(0), False)
self.assertIs(operator.truth(1), True) self.assertIs(operator.truth(1), True)
self.assertIs(operator.isNumberType(None), False)
self.assertIs(operator.isNumberType(0), True)
self.assertIs(operator.not_(1), False) self.assertIs(operator.not_(1), False)
self.assertIs(operator.not_(0), True) self.assertIs(operator.not_(0), True)
self.assertIs(operator.isSequenceType(0), False)
self.assertIs(operator.isSequenceType([]), True)
self.assertIs(operator.contains([], 1), False) self.assertIs(operator.contains([], 1), False)
self.assertIs(operator.contains([1], 1), True) self.assertIs(operator.contains([1], 1), True)
self.assertIs(operator.isMappingType(1), False)
self.assertIs(operator.isMappingType({}), True)
self.assertIs(operator.lt(0, 0), False) self.assertIs(operator.lt(0, 0), False)
self.assertIs(operator.lt(0, 1), True) self.assertIs(operator.lt(0, 1), True)
self.assertIs(operator.is_(True, True), True) self.assertIs(operator.is_(True, True), True)
......
...@@ -164,31 +164,6 @@ class OperatorTestCase(unittest.TestCase): ...@@ -164,31 +164,6 @@ class OperatorTestCase(unittest.TestCase):
self.failUnlessRaises(TypeError, operator.invert, None) self.failUnlessRaises(TypeError, operator.invert, None)
self.assertEqual(operator.inv(4), -5) self.assertEqual(operator.inv(4), -5)
def test_isMappingType(self):
self.failUnlessRaises(TypeError, operator.isMappingType)
self.failIf(operator.isMappingType(1))
self.failIf(operator.isMappingType(operator.isMappingType))
self.failUnless(operator.isMappingType(operator.__dict__))
self.failUnless(operator.isMappingType({}))
def test_isNumberType(self):
self.failUnlessRaises(TypeError, operator.isNumberType)
self.failUnless(operator.isNumberType(8))
self.failUnless(operator.isNumberType(8j))
self.failUnless(operator.isNumberType(8))
self.failUnless(operator.isNumberType(8.3))
self.failIf(operator.isNumberType(dir()))
def test_isSequenceType(self):
self.failUnlessRaises(TypeError, operator.isSequenceType)
self.failUnless(operator.isSequenceType(dir()))
self.failUnless(operator.isSequenceType(()))
self.failUnless(operator.isSequenceType(range(10)))
self.failUnless(operator.isSequenceType('yeahbuddy'))
self.failIf(operator.isSequenceType(3))
class Dict(dict): pass
self.failIf(operator.isSequenceType(Dict()))
def test_lshift(self): def test_lshift(self):
self.failUnlessRaises(TypeError, operator.lshift) self.failUnlessRaises(TypeError, operator.lshift)
self.failUnlessRaises(TypeError, operator.lshift, None, 42) self.failUnlessRaises(TypeError, operator.lshift, None, 42)
...@@ -235,31 +210,6 @@ class OperatorTestCase(unittest.TestCase): ...@@ -235,31 +210,6 @@ class OperatorTestCase(unittest.TestCase):
self.assertRaises(TypeError, operator.pow, 1) self.assertRaises(TypeError, operator.pow, 1)
self.assertRaises(TypeError, operator.pow, 1, 2, 3) self.assertRaises(TypeError, operator.pow, 1, 2, 3)
def test_repeat(self):
a = list(range(3))
self.failUnlessRaises(TypeError, operator.repeat)
self.failUnlessRaises(TypeError, operator.repeat, a, None)
self.failUnless(operator.repeat(a, 2) == a+a)
self.failUnless(operator.repeat(a, 1) == a)
self.failUnless(operator.repeat(a, 0) == [])
a = (1, 2, 3)
self.failUnless(operator.repeat(a, 2) == a+a)
self.failUnless(operator.repeat(a, 1) == a)
self.failUnless(operator.repeat(a, 0) == ())
a = '123'
self.failUnless(operator.repeat(a, 2) == a+a)
self.failUnless(operator.repeat(a, 1) == a)
self.failUnless(operator.repeat(a, 0) == '')
a = Seq1([4, 5, 6])
self.failUnless(operator.repeat(a, 2) == [4, 5, 6, 4, 5, 6])
self.failUnless(operator.repeat(a, 1) == [4, 5, 6])
self.failUnless(operator.repeat(a, 0) == [])
a = Seq2([4, 5, 6])
self.failUnless(operator.repeat(a, 2) == [4, 5, 6, 4, 5, 6])
self.failUnless(operator.repeat(a, 1) == [4, 5, 6])
self.failUnless(operator.repeat(a, 0) == [])
self.failUnlessRaises(TypeError, operator.repeat, 6, 7)
def test_rshift(self): def test_rshift(self):
self.failUnlessRaises(TypeError, operator.rshift) self.failUnlessRaises(TypeError, operator.rshift)
self.failUnlessRaises(TypeError, operator.rshift, None, 42) self.failUnlessRaises(TypeError, operator.rshift, None, 42)
...@@ -443,7 +393,6 @@ class OperatorTestCase(unittest.TestCase): ...@@ -443,7 +393,6 @@ class OperatorTestCase(unittest.TestCase):
self.assertEqual(operator.itruediv (c, 5), "itruediv") self.assertEqual(operator.itruediv (c, 5), "itruediv")
self.assertEqual(operator.ixor (c, 5), "ixor") self.assertEqual(operator.ixor (c, 5), "ixor")
self.assertEqual(operator.iconcat (c, c), "iadd") self.assertEqual(operator.iconcat (c, c), "iadd")
self.assertEqual(operator.irepeat (c, 5), "imul")
self.assertEqual(operator.__iadd__ (c, 5), "iadd") self.assertEqual(operator.__iadd__ (c, 5), "iadd")
self.assertEqual(operator.__iand__ (c, 5), "iand") self.assertEqual(operator.__iand__ (c, 5), "iand")
self.assertEqual(operator.__ifloordiv__(c, 5), "ifloordiv") self.assertEqual(operator.__ifloordiv__(c, 5), "ifloordiv")
...@@ -457,7 +406,6 @@ class OperatorTestCase(unittest.TestCase): ...@@ -457,7 +406,6 @@ class OperatorTestCase(unittest.TestCase):
self.assertEqual(operator.__itruediv__ (c, 5), "itruediv") self.assertEqual(operator.__itruediv__ (c, 5), "itruediv")
self.assertEqual(operator.__ixor__ (c, 5), "ixor") self.assertEqual(operator.__ixor__ (c, 5), "ixor")
self.assertEqual(operator.__iconcat__ (c, c), "iadd") self.assertEqual(operator.__iconcat__ (c, c), "iadd")
self.assertEqual(operator.__irepeat__ (c, 5), "imul")
def test_main(verbose=None): def test_main(verbose=None):
import sys import sys
......
...@@ -144,6 +144,10 @@ Core and Builtins ...@@ -144,6 +144,10 @@ Core and Builtins
Library Library
------- -------
- Removed isSequenceType(), isMappingType, and isNumberType() from the
operator module; use the abstract base classes instead. Also removed
the repeat() function; use mul() instead.
- Issue #4863: distutils.mwerkscompiler has been removed. - Issue #4863: distutils.mwerkscompiler has been removed.
- Fix and properly document the multiprocessing module's logging - Fix and properly document the multiprocessing module's logging
......
...@@ -65,7 +65,6 @@ used for special class methods; variants without leading and trailing\n\ ...@@ -65,7 +65,6 @@ used for special class methods; variants without leading and trailing\n\
if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \ if(! PyArg_UnpackTuple(a,#OP,2,2,&a1,&a2)) return NULL; \
return PyObject_RichCompare(a1,a2,A); } return PyObject_RichCompare(a1,a2,A); }
spami(isNumberType , PyNumber_Check)
spami(truth , PyObject_IsTrue) spami(truth , PyObject_IsTrue)
spam2(op_add , PyNumber_Add) spam2(op_add , PyNumber_Add)
spam2(op_sub , PyNumber_Subtract) spam2(op_sub , PyNumber_Subtract)
...@@ -95,15 +94,11 @@ spam2(op_irshift , PyNumber_InPlaceRshift) ...@@ -95,15 +94,11 @@ spam2(op_irshift , PyNumber_InPlaceRshift)
spam2(op_iand , PyNumber_InPlaceAnd) spam2(op_iand , PyNumber_InPlaceAnd)
spam2(op_ixor , PyNumber_InPlaceXor) spam2(op_ixor , PyNumber_InPlaceXor)
spam2(op_ior , PyNumber_InPlaceOr) spam2(op_ior , PyNumber_InPlaceOr)
spami(isSequenceType , PySequence_Check)
spam2(op_concat , PySequence_Concat) spam2(op_concat , PySequence_Concat)
spamoi(op_repeat , PySequence_Repeat)
spam2(op_iconcat , PySequence_InPlaceConcat) spam2(op_iconcat , PySequence_InPlaceConcat)
spamoi(op_irepeat , PySequence_InPlaceRepeat)
spami2b(op_contains , PySequence_Contains) spami2b(op_contains , PySequence_Contains)
spamn2(indexOf , PySequence_Index) spamn2(indexOf , PySequence_Index)
spamn2(countOf , PySequence_Count) spamn2(countOf , PySequence_Count)
spami(isMappingType , PyMapping_Check)
spam2(op_getitem , PyObject_GetItem) spam2(op_getitem , PyObject_GetItem)
spam2n(op_delitem , PyObject_DelItem) spam2n(op_delitem , PyObject_DelItem)
spam3n(op_setitem , PyObject_SetItem) spam3n(op_setitem , PyObject_SetItem)
...@@ -173,10 +168,6 @@ is_not(PyObject *s, PyObject *a) ...@@ -173,10 +168,6 @@ is_not(PyObject *s, PyObject *a)
static struct PyMethodDef operator_methods[] = { static struct PyMethodDef operator_methods[] = {
spam1o(isNumberType,
"isNumberType(a) -- Return True if a has a numeric type, False otherwise.")
spam1o(isSequenceType,
"isSequenceType(a) -- Return True if a has a sequence type, False otherwise.")
spam1o(truth, spam1o(truth,
"truth(a) -- Return True if a is true, False otherwise.") "truth(a) -- Return True if a is true, False otherwise.")
spam2(contains,__contains__, spam2(contains,__contains__,
...@@ -185,8 +176,6 @@ spam1(indexOf, ...@@ -185,8 +176,6 @@ spam1(indexOf,
"indexOf(a, b) -- Return the first index of b in a.") "indexOf(a, b) -- Return the first index of b in a.")
spam1(countOf, spam1(countOf,
"countOf(a, b) -- Return the number of times b occurs in a.") "countOf(a, b) -- Return the number of times b occurs in a.")
spam1o(isMappingType,
"isMappingType(a) -- Return True if a has a mapping type, False otherwise.")
spam1(is_, "is_(a, b) -- Same as a is b.") spam1(is_, "is_(a, b) -- Same as a is b.")
spam1(is_not, "is_not(a, b) -- Same as a is not b.") spam1(is_not, "is_not(a, b) -- Same as a is not b.")
...@@ -221,12 +210,8 @@ spam2(ixor,__ixor__, "ixor(a, b) -- Same as a ^= b.") ...@@ -221,12 +210,8 @@ spam2(ixor,__ixor__, "ixor(a, b) -- Same as a ^= b.")
spam2(ior,__ior__, "ior(a, b) -- Same as a |= b.") spam2(ior,__ior__, "ior(a, b) -- Same as a |= b.")
spam2(concat,__concat__, spam2(concat,__concat__,
"concat(a, b) -- Same as a + b, for a and b sequences.") "concat(a, b) -- Same as a + b, for a and b sequences.")
spam2(repeat,__repeat__,
"repeat(a, b) -- Return a * b, where a is a sequence, and b is an integer.")
spam2(iconcat,__iconcat__, spam2(iconcat,__iconcat__,
"iconcat(a, b) -- Same as a += b, for a and b sequences.") "iconcat(a, b) -- Same as a += b, for a and b sequences.")
spam2(irepeat,__irepeat__,
"irepeat(a, b) -- Same as a *= b, where a is a sequence, and b is an integer.")
spam2(getitem,__getitem__, spam2(getitem,__getitem__,
"getitem(a, b) -- Same as a[b].") "getitem(a, b) -- Same as a[b].")
spam2(setitem,__setitem__, spam2(setitem,__setitem__,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment