Skip to content

Commit

Permalink
Merge a990892 into 7b98bb7
Browse files Browse the repository at this point in the history
  • Loading branch information
andy-maier committed Jul 28, 2020
2 parents 7b98bb7 + a990892 commit dd7a8ff
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 27 deletions.
12 changes: 10 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ nocaselist - A case-insensitive list for Python
Overview
--------

Class ``NocaseList`` is a case-insensitive list that preserves
the lexical case of its items.
Class `NocaseList`_ is a case-insensitive list that preserves the lexical case
of its items.

Example:

Expand All @@ -43,6 +43,14 @@ Example:
>>> 'ALPHA' in list1 # Any lookup or comparison is case-insensitive
True
The `NocaseList`_ class supports the functionality of the built-in
`list class of Python 3.8`_, so its documentation applies completely.
Methods that have been added to the built-in ``list`` class between Python 2.7
and Python 3.8 (i.e. ``clear()`` and ``copy()``) are supported by the
`NocaseList`_ class on all Python versions it supports.

.. _list class of Python 3.8: https://docs.python.org/3.8/library/stdtypes.html#list
.. _NocaseList: https://nocaselist.readthedocs.io/en/stable/reference.html#nocaselist.NocaseList

Installation
------------
Expand Down
3 changes: 3 additions & 0 deletions docs/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ Released: not yet
* Docs: Switched links to items in the Python documentation to go to Python 3
instead of Python 2.

* Added support for the clear() method on Python 2.7 (where the built-in list
class does not support it yet). (See issue #30)

* Docs: Clarified that NocaseList supports the functionality of the built-in
list class as of Python 3.8, including all methods that have been added since
Python 2.7, on all Python versions.
Expand Down
8 changes: 8 additions & 0 deletions docs/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ Example:
>>> 'ALPHA' in list1 # Any lookup or comparison is case-insensitive
True
The :class:`~nocaselist.NocaseList` class supports the functionality of the
built-in `list class of Python 3.8`_, so its documentation applies completely.
Methods that have been added to the built-in ``list`` class between Python 2.7
and Python 3.8 (i.e. ``clear()`` and ``copy()``) are supported by the
:class:`~nocaselist.NocaseList` class on all Python versions it supports.

.. _list class of Python 3.8: https://docs.python.org/3.8/library/stdtypes.html#list


.. _`Supported environments`:

Expand Down
34 changes: 21 additions & 13 deletions nocaselist/_nocaselist.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,9 @@ class NocaseList(list):
The implementation maintains a second list with the lower-cased items of
the inherited list, and ensures that both lists are in sync.
The :class:`NocaseList` class supports the functionality of the built-in
`list class of Python 3.8`_, so its documentation applies completely.
Methods that have been added to the built-in :class:`py3:list`
class between Python 2.7 and Python 3.8 (i.e. :meth:`~NocaseList.clear` and
:meth:`~NocaseList.copy`) are supported by the :class:`NocaseList` class on
all Python versions.
The following documentation is provided only for explicit documentation of
the case-insensitive behavior, and to indicate which methods have been
implemented for maintaining the second lower-cased list.
.. _list class of Python 3.8: https://docs.python.org/3.8/library/stdtypes.html#list
""" # noqa E401
# pylint: enable=line-too-long

Expand Down Expand Up @@ -322,16 +313,33 @@ def copy(self):
Note: This method is supported on Python 2 and Python 3, even though
the built-in list class only supports it on Python 3.
"""
return NocaseList(self)
# Make sure a missing _lc_list attribute would surface
self_lc_list = self._lc_list
try:
# We first try to copy (normally cheaper than lower-casing)
new = super(NocaseList, self).copy()
# pylint: disable=protected-access
try:
new._lc_list = self_lc_list.copy()
except AttributeError:
raise AttributeError("Debug: dir(self)={!r}".format(dir(self)))
return new
except AttributeError:
return NocaseList(self)

def clear(self):
"""
Remove all items from the list (and return None).
Note: This method was introduced in Python 3.
Note: This method is supported on Python 2 and Python 3, even though
the built-in list class only supports it on Python 3.
"""
super(NocaseList, self).clear()
self._lc_list.clear()
try:
super(NocaseList, self).clear()
self._lc_list.clear()
except AttributeError:
del self[:]
del self._lc_list[:]

def index(self, value, start=0, stop=9223372036854775807):
"""
Expand Down
24 changes: 12 additions & 12 deletions tests/unittest/test_nocaselist.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
if TEST_AGAINST_LIST:
print("\nInfo: test_nocaselist.py tests run against standard list")

# Indicates that the list to be tested has a copy() method
LIST_HAS_COPY = not TEST_AGAINST_LIST or sys.version_info[0] == 3

# Indicates that the list to be tested has a clear() method
LIST_HAS_CLEAR = not TEST_AGAINST_LIST or sys.version_info[0] == 3

# The list class being tested
# pylint: disable=invalid-name
NocaseList = list if TEST_AGAINST_LIST else _NocaseList
Expand Down Expand Up @@ -749,7 +755,7 @@ def test_NocaseList_iter(testcase, nclist, exp_items):
value='',
exp_result=False,
),
None, None, False
None, None, True
),
(
"Empty list, with non-existing non-empty value (not found)",
Expand All @@ -758,7 +764,7 @@ def test_NocaseList_iter(testcase, nclist, exp_items):
value='Dog',
exp_result=False,
),
None, None, False
None, None, True
),

# Non-empty NocaseList
Expand Down Expand Up @@ -1774,14 +1780,14 @@ def test_NocaseList_count(testcase, nclist, value, exp_result):
dict(
nclist=NocaseList(),
),
None, None, True
None if LIST_HAS_COPY else AttributeError, None, True
),
(
"List with two items",
dict(
nclist=NocaseList(['Dog', 'Cat']),
),
None, None, True
None if LIST_HAS_COPY else AttributeError, None, True
),
]

Expand All @@ -1795,9 +1801,6 @@ def test_NocaseList_copy(testcase, nclist):
Test function for NocaseList.copy()
"""

if TEST_AGAINST_LIST:
pytest.skip("built-in list class does not support copy()")

# The code to be tested
nclist_copy = nclist.copy()

Expand Down Expand Up @@ -1828,14 +1831,14 @@ def test_NocaseList_copy(testcase, nclist):
dict(
nclist=NocaseList(),
),
None, None, True
None if LIST_HAS_CLEAR else AttributeError, None, True
),
(
"List with two items",
dict(
nclist=NocaseList(['Dog', 'Cat']),
),
None, None, True
None if LIST_HAS_CLEAR else AttributeError, None, True
),
]

Expand All @@ -1849,9 +1852,6 @@ def test_NocaseList_clear(testcase, nclist):
Test function for NocaseList.clear()
"""

if not hasattr(list, 'clear'):
pytest.skip("On this Python version, list does not have clear()")

# Don't change the testcase data, but a copy
nclist_copy = NocaseList(nclist)

Expand Down

0 comments on commit dd7a8ff

Please sign in to comment.