Commit 53dbe39b authored by Raymond Hettinger's avatar Raymond Hettinger

Move UserList to collections.

parent 4513ef8b
:mod:`collections` --- High-performance container datatypes :mod:`collections` --- Container datatypes
=========================================================== ==========================================
.. module:: collections .. module:: collections
:synopsis: High-performance datatypes :synopsis: Container datatypes
.. moduleauthor:: Raymond Hettinger <python@rcn.com> .. moduleauthor:: Raymond Hettinger <python@rcn.com>
.. sectionauthor:: Raymond Hettinger <python@rcn.com> .. sectionauthor:: Raymond Hettinger <python@rcn.com>
...@@ -663,3 +663,45 @@ In addition to supporting the methods and operations of mappings, ...@@ -663,3 +663,45 @@ In addition to supporting the methods and operations of mappings,
.. attribute:: UserDict.data .. attribute:: UserDict.data
A real dictionary used to store the contents of the :class:`UserDict` class. A real dictionary used to store the contents of the :class:`UserDict` class.
:class:`UserList` objects
-------------------------
This class acts as a wrapper around list objects. It is a useful base class
for your own list-like classes which can inherit from them and override
existing methods or add new ones. In this way, one can add new behaviors to
lists.
The need for this class has been partially supplanted by the ability to
subclass directly from :class:`list`; however, this class can be easier
to work with because the underlying list is accessible as an attribute.
.. class:: UserList([list])
Class that simulates a list. The instance's contents are kept in a regular
list, which is accessible via the :attr:`data` attribute of :class:`UserList`
instances. The instance's contents are initially set to a copy of *list*,
defaulting to the empty list ``[]``. *list* can be any iterable, for
example a real Python list or a :class:`UserList` object.
In addition to supporting the methods and operations of mutable sequences,
:class:`UserList` instances provide the following attribute:
.. attribute:: UserList.data
A real :class:`list` object used to store the contents of the
:class:`UserList` class.
**Subclassing requirements:** Subclasses of :class:`UserList` are expect to
offer a constructor which can be called with either no arguments or one
argument. List operations which return a new sequence attempt to create an
instance of the actual implementation class. To do so, it assumes that the
constructor can be called with a single parameter, which is a sequence object
used as a data source.
If a derived class does not wish to comply with this requirement, all of the
special methods supported by this class will need to be overridden; please
consult the sources for information about the methods which need to be provided
in that case.
...@@ -21,7 +21,7 @@ The following modules are documented in this chapter: ...@@ -21,7 +21,7 @@ The following modules are documented in this chapter:
math.rst math.rst
cmath.rst cmath.rst
decimal.rst decimal.rst
rational.rst fractions.rst
random.rst random.rst
itertools.rst itertools.rst
functools.rst functools.rst
......
:mod:`UserList` --- Class wrapper for list objects
==================================================
.. module:: UserList
:synopsis: Class wrapper for list objects.
.. note::
This module is available for backward compatibility only. If you are writing
code that does not need to work with versions of Python earlier than Python 2.2,
please consider subclassing directly from the built-in :class:`list` type.
This module defines a class that acts as a wrapper around list objects. It is a
useful base class for your own list-like classes, which can inherit from them
and override existing methods or add new ones. In this way one can add new
behaviors to lists.
The :mod:`UserList` module defines the :class:`UserList` class:
.. class:: UserList([list])
Class that simulates a list. The instance's contents are kept in a regular
list, which is accessible via the :attr:`data` attribute of
:class:`UserList`
instances. The instance's contents are initially set to a copy of *list*,
defaulting to the empty list ``[]``. *list* can be any iterable, for
example a real Python list or a :class:`UserList` object.
In addition to supporting the methods and operations of mutable sequences (see
section :ref:`typesseq`), :class:`UserList` instances provide the following
attribute:
.. attribute:: UserList.data
A real Python list object used to store the contents of the :class:`UserList`
class.
**Subclassing requirements:** Subclasses of :class:`UserList` are expect to
offer a constructor which can be called with either no arguments or one
argument. List operations which return a new sequence attempt to create an
instance of the actual implementation class. To do so, it assumes that the
constructor can be called with a single parameter, which is a sequence object
used as a data source.
If a derived class does not wish to comply with this requirement, all of the
special methods supported by this class will need to be overridden; please
consult the sources for information about the methods which need to be provided
in that case.
:mod:`UserString` --- Class wrapper for string objects :mod:`UserString` --- Class wrapper for string objects
====================================================== ======================================================
......
"""A more or less complete user-defined wrapper around list objects."""
import collections
class UserList(collections.MutableSequence):
def __init__(self, initlist=None):
self.data = []
if initlist is not None:
# XXX should this accept an arbitrary sequence?
if type(initlist) == type(self.data):
self.data[:] = initlist
elif isinstance(initlist, UserList):
self.data[:] = initlist.data[:]
else:
self.data = list(initlist)
def __repr__(self): return repr(self.data)
def __lt__(self, other): return self.data < self.__cast(other)
def __le__(self, other): return self.data <= self.__cast(other)
def __eq__(self, other): return self.data == self.__cast(other)
def __ne__(self, other): return self.data != self.__cast(other)
def __gt__(self, other): return self.data > self.__cast(other)
def __ge__(self, other): return self.data >= self.__cast(other)
def __cast(self, other):
if isinstance(other, UserList): return other.data
else: return other
def __cmp__(self, other):
return cmp(self.data, self.__cast(other))
def __contains__(self, item): return item in self.data
def __len__(self): return len(self.data)
def __getitem__(self, i): return self.data[i]
def __setitem__(self, i, item): self.data[i] = item
def __delitem__(self, i): del self.data[i]
def __add__(self, other):
if isinstance(other, UserList):
return self.__class__(self.data + other.data)
elif isinstance(other, type(self.data)):
return self.__class__(self.data + other)
else:
return self.__class__(self.data + list(other))
def __radd__(self, other):
if isinstance(other, UserList):
return self.__class__(other.data + self.data)
elif isinstance(other, type(self.data)):
return self.__class__(other + self.data)
else:
return self.__class__(list(other) + self.data)
def __iadd__(self, other):
if isinstance(other, UserList):
self.data += other.data
elif isinstance(other, type(self.data)):
self.data += other
else:
self.data += list(other)
return self
def __mul__(self, n):
return self.__class__(self.data*n)
__rmul__ = __mul__
def __imul__(self, n):
self.data *= n
return self
def append(self, item): self.data.append(item)
def insert(self, i, item): self.data.insert(i, item)
def pop(self, i=-1): return self.data.pop(i)
def remove(self, item): self.data.remove(item)
def count(self, item): return self.data.count(item)
def index(self, item, *args): return self.data.index(item, *args)
def reverse(self): self.data.reverse()
def sort(self, *args, **kwds): self.data.sort(*args, **kwds)
def extend(self, other):
if isinstance(other, UserList):
self.data.extend(other.data)
else:
self.data.extend(other)
...@@ -162,6 +162,80 @@ class UserDict(MutableMapping): ...@@ -162,6 +162,80 @@ class UserDict(MutableMapping):
################################################################################
### UserList
################################################################################
class UserList(MutableSequence):
"""A more or less complete user-defined wrapper around list objects."""
def __init__(self, initlist=None):
self.data = []
if initlist is not None:
# XXX should this accept an arbitrary sequence?
if type(initlist) == type(self.data):
self.data[:] = initlist
elif isinstance(initlist, UserList):
self.data[:] = initlist.data[:]
else:
self.data = list(initlist)
def __repr__(self): return repr(self.data)
def __lt__(self, other): return self.data < self.__cast(other)
def __le__(self, other): return self.data <= self.__cast(other)
def __eq__(self, other): return self.data == self.__cast(other)
def __ne__(self, other): return self.data != self.__cast(other)
def __gt__(self, other): return self.data > self.__cast(other)
def __ge__(self, other): return self.data >= self.__cast(other)
def __cast(self, other):
return other.data if isinstance(other, UserList) else other
def __cmp__(self, other):
return cmp(self.data, self.__cast(other))
def __contains__(self, item): return item in self.data
def __len__(self): return len(self.data)
def __getitem__(self, i): return self.data[i]
def __setitem__(self, i, item): self.data[i] = item
def __delitem__(self, i): del self.data[i]
def __add__(self, other):
if isinstance(other, UserList):
return self.__class__(self.data + other.data)
elif isinstance(other, type(self.data)):
return self.__class__(self.data + other)
return self.__class__(self.data + list(other))
def __radd__(self, other):
if isinstance(other, UserList):
return self.__class__(other.data + self.data)
elif isinstance(other, type(self.data)):
return self.__class__(other + self.data)
return self.__class__(list(other) + self.data)
def __iadd__(self, other):
if isinstance(other, UserList):
self.data += other.data
elif isinstance(other, type(self.data)):
self.data += other
else:
self.data += list(other)
return self
def __mul__(self, n):
return self.__class__(self.data*n)
__rmul__ = __mul__
def __imul__(self, n):
self.data *= n
return self
def append(self, item): self.data.append(item)
def insert(self, i, item): self.data.insert(i, item)
def pop(self, i=-1): return self.data.pop(i)
def remove(self, item): self.data.remove(item)
def count(self, item): return self.data.count(item)
def index(self, item, *args): return self.data.index(item, *args)
def reverse(self): self.data.reverse()
def sort(self, *args, **kwds): self.data.sort(*args, **kwds)
def extend(self, other):
if isinstance(other, UserList):
self.data.extend(other.data)
else:
self.data.extend(other)
################################################################################ ################################################################################
### Simple tests ### Simple tests
################################################################################ ################################################################################
......
...@@ -4,7 +4,7 @@ Common tests shared by test_str, test_unicode, test_userstring and test_string. ...@@ -4,7 +4,7 @@ Common tests shared by test_str, test_unicode, test_userstring and test_string.
import unittest, string, sys, struct import unittest, string, sys, struct
from test import test_support from test import test_support
from UserList import UserList from collections import UserList
class Sequence: class Sequence:
def __init__(self, seq='wxyz'): self.seq = seq def __init__(self, seq='wxyz'): self.seq = seq
......
import unittest import unittest
from test import test_support from test import test_support
from bisect import bisect_right, bisect_left, insort_left, insort_right, insort, bisect from bisect import bisect_right, bisect_left, insort_left, insort_right, insort, bisect
from UserList import UserList from collections import UserList
class TestBisect(unittest.TestCase): class TestBisect(unittest.TestCase):
......
...@@ -5,7 +5,7 @@ from test.test_support import fcmp, TESTFN, unlink, run_unittest, \ ...@@ -5,7 +5,7 @@ from test.test_support import fcmp, TESTFN, unlink, run_unittest, \
run_with_locale run_with_locale
from operator import neg from operator import neg
import sys, warnings, random, collections, io, rational, fractions import sys, warnings, random, collections, io, fractions
warnings.filterwarnings("ignore", "hex../oct.. of negative int", warnings.filterwarnings("ignore", "hex../oct.. of negative int",
FutureWarning, __name__) FutureWarning, __name__)
warnings.filterwarnings("ignore", "integer argument expected", warnings.filterwarnings("ignore", "integer argument expected",
...@@ -210,7 +210,7 @@ class BuiltinTest(unittest.TestCase): ...@@ -210,7 +210,7 @@ class BuiltinTest(unittest.TestCase):
# verify that circular objects are not handled # verify that circular objects are not handled
a = []; a.append(a) a = []; a.append(a)
b = []; b.append(b) b = []; b.append(b)
from UserList import UserList from collections import UserList
c = UserList(); c.append(c) c = UserList(); c.append(c)
self.assertRaises(RuntimeError, cmp, a, b) self.assertRaises(RuntimeError, cmp, a, b)
self.assertRaises(RuntimeError, cmp, b, c) self.assertRaises(RuntimeError, cmp, b, c)
......
from test.test_support import verify, verbose, TestFailed, sortdict from test.test_support import verify, verbose, TestFailed, sortdict
from UserList import UserList from collections import UserDict, UserList
from collections import UserDict
def e(a, b): def e(a, b):
print(a, b) print(a, b)
......
...@@ -5,7 +5,7 @@ from array import array ...@@ -5,7 +5,7 @@ from array import array
from weakref import proxy from weakref import proxy
from test.test_support import TESTFN, findfile, run_unittest from test.test_support import TESTFN, findfile, run_unittest
from UserList import UserList from collections import UserList
class AutoFileTests(unittest.TestCase): class AutoFileTests(unittest.TestCase):
# file tests for which a test file is automatically set up # file tests for which a test file is automatically set up
......
...@@ -7,7 +7,7 @@ from array import array ...@@ -7,7 +7,7 @@ from array import array
from weakref import proxy from weakref import proxy
from test.test_support import TESTFN, findfile, run_unittest from test.test_support import TESTFN, findfile, run_unittest
from UserList import UserList from collections import UserList
import _fileio import _fileio
......
...@@ -254,7 +254,7 @@ class MiscTest(unittest.TestCase): ...@@ -254,7 +254,7 @@ class MiscTest(unittest.TestCase):
def test_recursion(self): def test_recursion(self):
# Check that comparison for recursive objects fails gracefully # Check that comparison for recursive objects fails gracefully
from UserList import UserList from collections import UserList
a = UserList() a = UserList()
b = UserList() b = UserList()
a.append(b) a.append(b)
......
# Check every path through every method of UserList # Check every path through every method of UserList
from UserList import UserList from collections import UserList
import unittest import unittest
from test import test_support, list_tests from test import test_support, list_tests
......
import gc import gc
import sys import sys
import unittest import unittest
import UserList import collections
import weakref import weakref
from test import test_support from test import test_support
...@@ -157,7 +157,7 @@ class ReferencesTestCase(TestBase): ...@@ -157,7 +157,7 @@ class ReferencesTestCase(TestBase):
o = C() o = C()
self.check_proxy(o, weakref.proxy(o)) self.check_proxy(o, weakref.proxy(o))
L = UserList.UserList() L = collections.UserList()
p = weakref.proxy(L) p = weakref.proxy(L)
self.failIf(p, "proxy for empty UserList should be false") self.failIf(p, "proxy for empty UserList should be false")
p.append(12) p.append(12)
...@@ -171,11 +171,11 @@ class ReferencesTestCase(TestBase): ...@@ -171,11 +171,11 @@ class ReferencesTestCase(TestBase):
p[1] = 5 p[1] = 5
self.assertEqual(L[1], 5) self.assertEqual(L[1], 5)
self.assertEqual(p[1], 5) self.assertEqual(p[1], 5)
L2 = UserList.UserList(L) L2 = collections.UserList(L)
p2 = weakref.proxy(L2) p2 = weakref.proxy(L2)
self.assertEqual(p, p2) self.assertEqual(p, p2)
## self.assertEqual(repr(L2), repr(p2)) ## self.assertEqual(repr(L2), repr(p2))
L3 = UserList.UserList(range(10)) L3 = collections.UserList(range(10))
p3 = weakref.proxy(L3) p3 = weakref.proxy(L3)
self.assertEqual(L3[:], p3[:]) self.assertEqual(L3[:], p3[:])
self.assertEqual(L3[5:], p3[5:]) self.assertEqual(L3[5:], p3[5:])
......
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