You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@impala.apache.org by jo...@apache.org on 2020/05/05 15:13:40 UTC

[impala] branch master updated: IMPALA-9720: Update bitarray 0.9.0 -> 1.2.1

This is an automated email from the ASF dual-hosted git repository.

joemcdonnell pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git


The following commit(s) were added to refs/heads/master by this push:
     new 537c30d  IMPALA-9720: Update bitarray 0.9.0 -> 1.2.1
537c30d is described below

commit 537c30dd063934373d171bdd9ad03835ee8febfc
Author: David Knupp <dk...@cloudera.com>
AuthorDate: Thu Apr 30 01:02:17 2020 -0700

    IMPALA-9720: Update bitarray 0.9.0 -> 1.2.1
    
    This is needed for python3 compatibility.
    
    Tested by running gerrit-verify-dryrun.
    
    Change-Id: I0641b03e880314a424d9d5a0651945c4f51273bc
    Reviewed-on: http://gerrit.cloudera.org:8080/15858
    Reviewed-by: Impala Public Jenkins <im...@cloudera.com>
    Tested-by: Impala Public Jenkins <im...@cloudera.com>
---
 LICENSE.txt                                        |    2 +-
 bin/rat_exclude_files.txt                          |    2 +-
 shell/.gitignore                                   |    5 +-
 shell/ext-py/bitarray-0.9.0/PKG-INFO               |  593 -----------
 shell/ext-py/bitarray-0.9.0/bitarray/__init__.py   |  116 ---
 shell/ext-py/bitarray-1.2.1/AUTHORS                |   22 +
 shell/ext-py/bitarray-1.2.1/CHANGE_LOG             |  254 +++++
 shell/ext-py/bitarray-1.2.1/LICENSE                |   48 +
 shell/ext-py/bitarray-1.2.1/README.md              |  695 +++++++++++++
 shell/ext-py/bitarray-1.2.1/TODO                   |   95 ++
 shell/ext-py/bitarray-1.2.1/bitarray/__init__.py   |   91 ++
 .../bitarray/_bitarray.c                           |  662 +++++++-----
 shell/ext-py/bitarray-1.2.1/bitarray/_util.c       |  422 ++++++++
 .../bitarray/test_bitarray.py                      | 1085 ++++++++++++--------
 shell/ext-py/bitarray-1.2.1/bitarray/test_util.py  |  590 +++++++++++
 shell/ext-py/bitarray-1.2.1/bitarray/util.py       |  274 +++++
 .../{bitarray-0.9.0 => bitarray-1.2.1}/setup.py    |    8 +-
 shell/ext-py/bitarray-1.2.1/update_readme.py       |  112 ++
 shell/packaging/requirements.txt                   |    2 +-
 19 files changed, 3651 insertions(+), 1427 deletions(-)

diff --git a/LICENSE.txt b/LICENSE.txt
index 1d832c8..b4cedd9 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -398,7 +398,7 @@ www/DataTables* and www/datatables*: MIT license
 
 Parts of be/src/runtime/string-search.h: Python Software License V2
 Parts of shell/impala_shell.py: Python Software License V2
-shell/ext-py/bit-array*: Python Software License V2
+shell/ext-py/bitarray*: Python Software License V2
 
   Copyright (c) 2001 - 2016 Python Software Foundation; All Rights Reserved
 
diff --git a/bin/rat_exclude_files.txt b/bin/rat_exclude_files.txt
index d0c4968..e0e78f9 100644
--- a/bin/rat_exclude_files.txt
+++ b/bin/rat_exclude_files.txt
@@ -42,7 +42,7 @@ www/favicon.ico
 tests/comparison/leopard/static/css/bootstrap*
 tests/comparison/leopard/static/fonts/glyphicons-halflings*
 tests/comparison/leopard/static/js/bootstrap*
-shell/ext-py/bitarray-0.9.0/*
+shell/ext-py/bitarray-1.2.1/*
 shell/ext-py/prettytable-0.7.1/*
 shell/ext-py/sasl-0.1.1/*
 shell/ext-py/six-1.14.0/*
diff --git a/shell/.gitignore b/shell/.gitignore
index 97f2c41..0d96453 100644
--- a/shell/.gitignore
+++ b/shell/.gitignore
@@ -11,8 +11,8 @@ ext-py/prettytable-0.7.1/prettytable.egg-info
 ext-py/sqlparse-0.3.1/dist/
 ext-py/sqlparse-0.3.1/build/
 ext-py/sqlparse-0.3.1/sqlparse.egg-info/
-ext-py/bitarray-0.9.0/bitarray.egg-info/
-ext-py/bitarray-0.9.0/dist/
+ext-py/bitarray-1.2.1/bitarray.egg-info/
+ext-py/bitarray-1.2.1/dist/
 ext-py/thrift_sasl-0.4.2/dist/
 ext-py/thrift_sasl-0.4.2/build/
 ext-py/thrift_sasl-0.4.2/six.egg-info/
@@ -21,6 +21,7 @@ ext-py/thrift_sasl-0.4.2/six.egg-info/
 # clean phase. Previous version of deps should be kept here for cleaning otherwise they
 # may cause a build failure. Also the ignore path must be changed to the root folder
 # so "git clean -Xdf" will work.
+ext-py/bitarray-0.9.0/
 ext-py/six-1.11.0/
 ext-py/sqlparse-0.1.7/
 ext-py/sqlparse-0.1.19/
diff --git a/shell/ext-py/bitarray-0.9.0/PKG-INFO b/shell/ext-py/bitarray-0.9.0/PKG-INFO
deleted file mode 100644
index b867d86..0000000
--- a/shell/ext-py/bitarray-0.9.0/PKG-INFO
+++ /dev/null
@@ -1,593 +0,0 @@
-Metadata-Version: 1.1
-Name: bitarray
-Version: 0.9.0
-Summary: efficient arrays of booleans -- C extension
-Home-page: https://github.com/ilanschnell/bitarray
-Author: Ilan Schnell
-Author-email: ilanschnell@gmail.com
-License: PSF
-Description: ======================================
-        bitarray: efficient arrays of booleans
-        ======================================
-        
-        This module provides an object type which efficiently represents an array
-        of booleans.  Bitarrays are sequence types and behave very much like usual
-        lists.  Eight bits are represented by one byte in a contiguous block of
-        memory.  The user can select between two representations: little-endian
-        and big-endian.  All of the functionality is implemented in C.
-        Methods for accessing the machine representation are provided.
-        This can be useful when bit level access to binary files is required,
-        such as portable bitmap image files (.pbm).  Also, when dealing with
-        compressed data which uses variable bit length encoding, you may find
-        this module useful.
-        
-        
-        Key features
-        ------------
-        
-         * All functionality implemented in C.
-        
-         * Bitarray objects behave very much like a list object, in particular
-           slicing (including slice assignment and deletion) is supported.
-        
-         * The bit endianness can be specified for each bitarray object, see below.
-        
-         * On 32bit systems, a bitarray object can contain up to 2^34 elements,
-           that is 16 Gbits (on 64bit machines up to 2^63 elements in theory --
-           on Python 2.4 only 2^31 elements,
-           see `PEP 353 <http://www.python.org/dev/peps/pep-0353/>`_
-           (added in Python 2.5)).
-        
-         * Packing and unpacking to other binary data formats,
-           e.g. `numpy.ndarray <http://www.scipy.org/Tentative_NumPy_Tutorial>`_,
-           is possible.
-        
-         * Fast methods for encoding and decoding variable bit length prefix codes
-        
-         * Sequential search (as list or iterator)
-        
-         * Bitwise operations: ``&, |, ^, &=, |=, ^=, ~``
-        
-         * Pickling and unpickling of bitarray objects possible.
-        
-         * Bitarray objects support the buffer protocol (Python 2.7 only)
-        
-        
-        Installation
-        ------------
-        
-        bitarray can be installed from source::
-        
-           $ tar xzf bitarray-0.9.0.tar.gz
-           $ cd bitarray-0.9.0
-           $ python setup.py install
-        
-        On Unix systems, the latter command may have to be executed with root
-        privileges.
-        If you have `distribute <http://pypi.python.org/pypi/distribute/>`_
-        installed, you can easy_install bitarray.
-        Once you have installed the package, you may want to test it::
-        
-           $ python -c 'import bitarray; bitarray.test()'
-           bitarray is installed in: /usr/local/lib/python2.7/site-packages/bitarray
-           bitarray version: 0.9.0
-           2.7.2 (r271:86832, Nov 29 2010) [GCC 4.2.1 (SUSE Linux)]
-           .........................................................................
-           ...........................................
-           ----------------------------------------------------------------------
-           Ran 134 tests in 1.396s
-           
-           OK
-        
-        You can always import the function test,
-        and ``test().wasSuccessful()`` will return True when the test went well.
-        
-        
-        
-        Using the module
-        ----------------
-        
-        As mentioned above, bitarray objects behave very much like lists, so
-        there is not too much to learn.  The biggest difference from list objects
-        is the ability to access the machine representation of the object.
-        When doing so, the bit endianness is of importance; this issue is
-        explained in detail in the section below.  Here, we demonstrate the
-        basic usage of bitarray objects:
-        
-           >>> from bitarray import bitarray
-           >>> a = bitarray()            # create empty bitarray
-           >>> a.append(True)
-           >>> a.extend([False, True, True])
-           >>> a
-           bitarray('1011')
-        
-        Bitarray objects can be instantiated in different ways:
-        
-           >>> a = bitarray(2**20)       # bitarray of length 1048576 (uninitialized)
-           >>> bitarray('1001011')       # from a string
-           bitarray('1001011')
-           >>> lst = [True, False, False, True, False, True, True]
-           >>> bitarray(lst)             # from list, tuple, iterable
-           bitarray('1001011')
-        
-        Bits can be assigned from any Python object, if the value can be interpreted
-        as a truth value.  You can think of this as Python's built-in function bool()
-        being applied, whenever casting an object:
-        
-           >>> a = bitarray([42, '', True, {}, 'foo', None])
-           >>> a
-           bitarray('101010')
-           >>> a.append(a)      # note that bool(a) is True
-           >>> a.count(42)      # counts occurrences of True (not 42)
-           4L
-           >>> a.remove('')     # removes first occurrence of False
-           >>> a
-           bitarray('110101')
-        
-        Like lists, bitarray objects support slice assignment and deletion:
-        
-           >>> a = bitarray(50)
-           >>> a.setall(False)
-           >>> a[11:37:3] = 9 * bitarray([True])
-           >>> a
-           bitarray('00000000000100100100100100100100100100000000000000')
-           >>> del a[12::3]
-           >>> a
-           bitarray('0000000000010101010101010101000000000')
-           >>> a[-6:] = bitarray('10011')
-           >>> a
-           bitarray('000000000001010101010101010100010011')
-           >>> a += bitarray('000111')
-           >>> a[9:]
-           bitarray('001010101010101010100010011000111')
-        
-        In addition, slices can be assigned to booleans, which is easier (and
-        faster) than assigning to a bitarray in which all values are the same:
-        
-           >>> a = 20 * bitarray('0')
-           >>> a[1:15:3] = True
-           >>> a
-           bitarray('01001001001001000000')
-        
-        This is easier and faster than:
-        
-           >>> a = 20 * bitarray('0')
-           >>> a[1:15:3] = 5 * bitarray('1')
-           >>> a
-           bitarray('01001001001001000000')
-        
-        Note that in the latter we have to create a temporary bitarray whose length
-        must be known or calculated.
-        
-        
-        Bit endianness
-        --------------
-        
-        Since a bitarray allows addressing of individual bits, where the machine
-        represents 8 bits in one byte, there are two obvious choices for this
-        mapping: little- and big-endian.
-        When creating a new bitarray object, the endianness can always be
-        specified explicitly:
-        
-           >>> a = bitarray(endian='little')
-           >>> a.frombytes(b'A')
-           >>> a
-           bitarray('10000010')
-           >>> b = bitarray('11000010', endian='little')
-           >>> b.tobytes()
-           'C'
-        
-        Here, the low-bit comes first because little-endian means that increasing
-        numeric significance corresponds to an increasing address (index).
-        So a[0] is the lowest and least significant bit, and a[7] is the highest
-        and most significant bit.
-        
-           >>> a = bitarray(endian='big')
-           >>> a.frombytes(b'A')
-           >>> a
-           bitarray('01000001')
-           >>> a[6] = 1
-           >>> a.tobytes()
-           'C'
-        
-        Here, the high-bit comes first because big-endian
-        means "most-significant first".
-        So a[0] is now the lowest and most significant bit, and a[7] is the highest
-        and least significant bit.
-        
-        The bit endianness is a property attached to each bitarray object.
-        When comparing bitarray objects, the endianness (and hence the machine
-        representation) is irrelevant; what matters is the mapping from indices
-        to bits:
-        
-           >>> bitarray('11001', endian='big') == bitarray('11001', endian='little')
-           True
-        
-        Bitwise operations (``&, |, ^, &=, |=, ^=, ~``) are implemented efficiently
-        using the corresponding byte operations in C, i.e. the operators act on the
-        machine representation of the bitarray objects.  Therefore, one has to be
-        cautious when applying the operation to bitarrays with different endianness.
-        
-        When converting to and from machine representation, using
-        the ``tobytes``, ``frombytes``, ``tofile`` and ``fromfile`` methods,
-        the endianness matters:
-        
-           >>> a = bitarray(endian='little')
-           >>> a.frombytes(b'\x01')
-           >>> a
-           bitarray('10000000')
-           >>> b = bitarray(endian='big')
-           >>> b.frombytes(b'\x80')
-           >>> b
-           bitarray('10000000')
-           >>> a == b
-           True
-           >>> a.tobytes() == b.tobytes()
-           False
-        
-        The endianness can not be changed once an object is created.
-        However, since creating a bitarray from another bitarray just copies the
-        memory representing the data, you can create a new bitarray with different
-        endianness:
-        
-           >>> a = bitarray('11100000', endian='little')
-           >>> a
-           bitarray('11100000')
-           >>> b = bitarray(a, endian='big')
-           >>> b
-           bitarray('00000111')
-           >>> a == b
-           False
-           >>> a.tobytes() == b.tobytes()
-           True
-        
-        The default bit endianness is currently big-endian; however, this may change
-        in the future, and when dealing with the machine representation of bitarray
-        objects, it is recommended to always explicitly specify the endianness.
-        
-        Unless explicitly converting to machine representation, using
-        the ``tobytes``, ``frombytes``, ``tofile`` and ``fromfile`` methods,
-        the bit endianness will have no effect on any computation, and one
-        can safely ignore setting the endianness, and other details of this section.
-        
-        
-        Buffer protocol
-        ---------------
-        
-        Python 2.7 provides memoryview objects, which allow Python code to access
-        the internal data of an object that supports the buffer protocol without
-        copying.  Bitarray objects support this protocol, with the memory being
-        interpreted as simple bytes.
-        
-           >>> a = bitarray('01000001' '01000010' '01000011', endian='big')
-           >>> v = memoryview(a)
-           >>> len(v)
-           3
-           >>> v[-1]
-           'C'
-           >>> v[:2].tobytes()
-           'AB'
-           >>> v.readonly  # changing a bitarray's memory is also possible
-           False
-           >>> v[1] = 'o'
-           >>> a
-           bitarray('010000010110111101000011')
-        
-        
-        Variable bit length prefix codes
-        --------------------------------
-        
-        The method ``encode`` takes a dictionary mapping symbols to bitarrays
-        and an iterable, and extends the bitarray object with the encoded symbols
-        found while iterating.  For example:
-        
-           >>> d = {'H':bitarray('111'), 'e':bitarray('0'),
-           ...      'l':bitarray('110'), 'o':bitarray('10')}
-           ...
-           >>> a = bitarray()
-           >>> a.encode(d, 'Hello')
-           >>> a
-           bitarray('111011011010')
-        
-        Note that the string ``'Hello'`` is an iterable, but the symbols are not
-        limited to characters, in fact any immutable Python object can be a symbol.
-        Taking the same dictionary, we can apply the ``decode`` method which will
-        return a list of the symbols:
-        
-           >>> a.decode(d)
-           ['H', 'e', 'l', 'l', 'o']
-           >>> ''.join(a.decode(d))
-           'Hello'
-        
-        Since symbols are not limited to being characters, it is necessary to return
-        them as elements of a list, rather than simply returning the joined string.
-        
-        
-        Reference
-        ---------
-        
-        **The bitarray class:**
-        
-        ``bitarray([initial], [endian=string])``
-           Return a new bitarray object whose items are bits initialized from
-           the optional initial, and endianness.
-           If no object is provided, the bitarray is initialized to have length zero.
-           The initial object may be of the following types:
-           
-           int, long
-               Create bitarray of length given by the integer.  The initial values
-               in the array are random, because only the memory allocated.
-           
-           string
-               Create bitarray from a string of '0's and '1's.
-           
-           list, tuple, iterable
-               Create bitarray from a sequence, each element in the sequence is
-               converted to a bit using truth value value.
-           
-           bitarray
-               Create bitarray from another bitarray.  This is done by copying the
-               memory holding the bitarray data, and is hence very fast.
-           
-           The optional keyword arguments 'endian' specifies the bit endianness of the
-           created bitarray object.
-           Allowed values are 'big' and 'little' (default is 'big').
-           
-           Note that setting the bit endianness only has an effect when accessing the
-           machine representation of the bitarray, i.e. when using the methods: tofile,
-           fromfile, tobytes, frombytes.
-        
-        
-        **A bitarray object supports the following methods:**
-        
-        ``all()`` -> bool
-           Returns True when all bits in the array are True.
-        
-        
-        ``any()`` -> bool
-           Returns True when any bit in the array is True.
-        
-        
-        ``append(item)``
-           Append the value bool(item) to the end of the bitarray.
-        
-        
-        ``buffer_info()`` -> tuple
-           Return a tuple (address, size, endianness, unused, allocated) giving the
-           current memory address, the size (in bytes) used to hold the bitarray's
-           contents, the bit endianness as a string, the number of unused bits
-           (e.g. a bitarray of length 11 will have a buffer size of 2 bytes and
-           5 unused bits), and the size (in bytes) of the allocated memory.
-        
-        
-        ``bytereverse()``
-           For all bytes representing the bitarray, reverse the bit order (in-place).
-           Note: This method changes the actual machine values representing the
-           bitarray; it does not change the endianness of the bitarray object.
-        
-        
-        ``copy()`` -> bitarray
-           Return a copy of the bitarray.
-        
-        
-        ``count([value])`` -> int
-           Return number of occurrences of value (defaults to True) in the bitarray.
-        
-        
-        ``decode(code)`` -> list
-           Given a prefix code (a dict mapping symbols to bitarrays),
-           decode the content of the bitarray and return the list of symbols.
-        
-        
-        ``encode(code, iterable)``
-           Given a prefix code (a dict mapping symbols to bitarrays),
-           iterate over the iterable object with symbols, and extend the bitarray
-           with the corresponding bitarray for each symbols.
-        
-        
-        ``endian()`` -> string
-           Return the bit endianness as a string (either 'little' or 'big').
-        
-        
-        ``extend(object)``
-           Append bits to the end of the bitarray.  The objects which can be passed
-           to this method are the same iterable objects which can given to a bitarray
-           object upon initialization.
-        
-        
-        ``fill()`` -> int
-           Adds zeros to the end of the bitarray, such that the length of the bitarray
-           will be a multiple of 8.  Returns the number of bits added (0..7).
-        
-        
-        ``frombytes(bytes)``
-           Append from a byte string, interpreted as machine values.
-        
-        
-        ``fromfile(f, [n])``
-           Read n bytes from the file object f and append them to the bitarray
-           interpreted as machine values.  When n is omitted, as many bytes are
-           read until EOF is reached.
-        
-        
-        ``fromstring(string)``
-           Append from a string, interpreting the string as machine values.
-           Deprecated since version 0.4.0, use ``frombytes()`` instead.
-        
-        
-        ``index(value, [start, [stop]])`` -> int
-           Return index of the first occurrence of bool(value) in the bitarray.
-           Raises ValueError if the value is not present.
-        
-        
-        ``insert(i, item)``
-           Insert bool(item) into the bitarray before position i.
-        
-        
-        ``invert()``
-           Invert all bits in the array (in-place),
-           i.e. convert each 1-bit into a 0-bit and vice versa.
-        
-        
-        ``iterdecode(code)`` -> iterator
-           Given a prefix code (a dict mapping symbols to bitarrays),
-           decode the content of the bitarray and iterate over the symbols.
-        
-        
-        ``itersearch(bitarray)`` -> iterator
-           Searches for the given a bitarray in self, and return an iterator over
-           the start positions where bitarray matches self.
-        
-        
-        ``length()`` -> int
-           Return the length, i.e. number of bits stored in the bitarray.
-           This method is preferred over __len__ (used when typing ``len(a)``),
-           since __len__ will fail for a bitarray object with 2^31 or more elements
-           on a 32bit machine, whereas this method will return the correct value,
-           on 32bit and 64bit machines.
-        
-        
-        ``pack(bytes)``
-           Extend the bitarray from a byte string, where each characters corresponds to
-           a single bit.  The character b'\x00' maps to bit 0 and all other characters
-           map to bit 1.
-           This method, as well as the unpack method, are meant for efficient
-           transfer of data between bitarray objects to other python objects
-           (for example NumPy's ndarray object) which have a different view of memory.
-        
-        
-        ``pop([i])`` -> item
-           Return the i-th (default last) element and delete it from the bitarray.
-           Raises IndexError if bitarray is empty or index is out of range.
-        
-        
-        ``remove(item)``
-           Remove the first occurrence of bool(item) in the bitarray.
-           Raises ValueError if item is not present.
-        
-        
-        ``reverse()``
-           Reverse the order of bits in the array (in-place).
-        
-        
-        ``search(bitarray, [limit])`` -> list
-           Searches for the given a bitarray in self, and returns the start positions
-           where bitarray matches self as a list.
-           The optional argument limits the number of search results to the integer
-           specified.  By default, all search results are returned.
-        
-        
-        ``setall(value)``
-           Set all bits in the bitarray to bool(value).
-        
-        
-        ``sort(reverse=False)``
-           Sort the bits in the array (in-place).
-        
-        
-        ``to01()`` -> string
-           Return a string containing '0's and '1's, representing the bits in the
-           bitarray object.
-           Note: To extend a bitarray from a string containing '0's and '1's,
-           use the extend method.
-        
-        
-        ``tobytes()`` -> bytes
-           Return the byte representation of the bitarray.
-           When the length of the bitarray is not a multiple of 8, the few remaining
-           bits (1..7) are set to 0.
-        
-        
-        ``tofile(f)``
-           Write all bits (as machine values) to the file object f.
-           When the length of the bitarray is not a multiple of 8,
-           the remaining bits (1..7) are set to 0.
-        
-        
-        ``tolist()`` -> list
-           Return an ordinary list with the items in the bitarray.
-           Note that the list object being created will require 32 or 64 times more
-           memory than the bitarray object, which may cause a memory error if the
-           bitarray is very large.
-           Also note that to extend a bitarray with elements from a list,
-           use the extend method.
-        
-        
-        ``tostring()`` -> string
-           Return the string representing (machine values) of the bitarray.
-           When the length of the bitarray is not a multiple of 8, the few remaining
-           bits (1..7) are set to 0.
-           Deprecated since version 0.4.0, use ``tobytes()`` instead.
-        
-        
-        ``unpack(zero=b'\x00', one=b'\xff')`` -> bytes
-           Return a byte string containing one character for each bit in the bitarray,
-           using the specified mapping.
-           See also the pack method.
-        
-        
-        **Functions defined in the module:**
-        
-        ``test(verbosity=1, repeat=1)`` -> TextTestResult
-           Run self-test, and return unittest.runner.TextTestResult object.
-        
-        
-        ``bitdiff(a, b)`` -> int
-           Return the difference between two bitarrays a and b.
-           This is function does the same as (a ^ b).count(), but is more memory
-           efficient, as no intermediate bitarray object gets created
-        
-        
-        ``bits2bytes(n)`` -> int
-           Return the number of bytes necessary to store n bits.
-        
-        
-        Change log
-        ----------
-        
-        **0.9.0** (2019-04-22):
-        
-          * more efficient decode and iterdecode by using C-level binary tree
-            instead of a python one, #54
-          * added buffer protocol support for Python 3, #55
-          * fixed invalid pointer exceptions in pypy, #47
-          * made all examples Py3k compatible
-          * add gene sequence example
-          * add official Python 3.7 support
-          * drop Python 2.4, 3.1 and 3.2 support
-        
-        
-        **0.8.3** (2018-07-06):
-        
-          * add exception to setup.py when README.rst cannot be opened
-        
-        
-        **0.8.2** (2018-05-30):
-        
-          * add official Python 3.6 support (although it was already working)
-          * fix description of fill(), #52
-          * handle extending self correctly, #28
-          * copy_n: fast copy with memmove fixed, #43
-          * minor clarity/wording changes to README, #23
-        
-        
-        Please find the complete change log
-        `here <https://github.com/ilanschnell/bitarray/blob/master/CHANGE_LOG>`_.
-        
-Platform: UNKNOWN
-Classifier: License :: OSI Approved :: Python Software Foundation License
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Intended Audience :: Developers
-Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: C
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.5
-Classifier: Programming Language :: Python :: 2.6
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.3
-Classifier: Programming Language :: Python :: 3.4
-Classifier: Programming Language :: Python :: 3.5
-Classifier: Programming Language :: Python :: 3.6
-Classifier: Programming Language :: Python :: 3.7
-Classifier: Topic :: Utilities
diff --git a/shell/ext-py/bitarray-0.9.0/bitarray/__init__.py b/shell/ext-py/bitarray-0.9.0/bitarray/__init__.py
deleted file mode 100644
index 6a97795..0000000
--- a/shell/ext-py/bitarray-0.9.0/bitarray/__init__.py
+++ /dev/null
@@ -1,116 +0,0 @@
-"""
-This package defines an object type which can efficiently represent
-a bitarray.  Bitarrays are sequence types and behave very much like lists.
-
-Please find a description of this package at:
-
-    http://pypi.python.org/pypi/bitarray/
-
-Author: Ilan Schnell
-"""
-from bitarray._bitarray import _bitarray, bitdiff, bits2bytes, _sysinfo
-
-__version__ = '0.9.0'
-
-
-def _check_codedict(codedict):
-    if not isinstance(codedict, dict):
-        raise TypeError("dictionary expected")
-    if len(codedict) == 0:
-        raise ValueError("prefix code empty")
-    for k, v in codedict.items():
-        if not isinstance(v, bitarray):
-            raise TypeError("bitarray expected for dictionary value")
-        if v.length() == 0:
-            raise ValueError("non-empty bitarray expected")
-
-
-class bitarray(_bitarray):
-    """bitarray([initial], [endian=string])
-
-Return a new bitarray object whose items are bits initialized from
-the optional initial, and endianness.
-If no object is provided, the bitarray is initialized to have length zero.
-The initial object may be of the following types:
-
-int, long
-    Create bitarray of length given by the integer.  The initial values
-    in the array are random, because only the memory allocated.
-
-string
-    Create bitarray from a string of '0's and '1's.
-
-list, tuple, iterable
-    Create bitarray from a sequence, each element in the sequence is
-    converted to a bit using truth value value.
-
-bitarray
-    Create bitarray from another bitarray.  This is done by copying the
-    memory holding the bitarray data, and is hence very fast.
-
-The optional keyword arguments 'endian' specifies the bit endianness of the
-created bitarray object.
-Allowed values are 'big' and 'little' (default is 'big').
-
-Note that setting the bit endianness only has an effect when accessing the
-machine representation of the bitarray, i.e. when using the methods: tofile,
-fromfile, tobytes, frombytes."""
-
-    def fromstring(self, string):
-        """fromstring(string)
-
-Append from a string, interpreting the string as machine values.
-Deprecated since version 0.4.0, use ``frombytes()`` instead."""
-        return self.frombytes(string.encode())
-
-    def tostring(self):
-        """tostring() -> string
-
-Return the string representing (machine values) of the bitarray.
-When the length of the bitarray is not a multiple of 8, the few remaining
-bits (1..7) are set to 0.
-Deprecated since version 0.4.0, use ``tobytes()`` instead."""
-        return self.tobytes().decode()
-
-    def decode(self, codedict):
-        """decode(code) -> list
-
-Given a prefix code (a dict mapping symbols to bitarrays),
-decode the content of the bitarray and return the list of symbols."""
-        _check_codedict(codedict)
-        return self._decode(codedict)
-
-    def iterdecode(self, codedict):
-        """iterdecode(code) -> iterator
-
-Given a prefix code (a dict mapping symbols to bitarrays),
-decode the content of the bitarray and iterate over the symbols."""
-        _check_codedict(codedict)
-        return self._iterdecode(codedict)
-
-    def encode(self, codedict, iterable):
-        """encode(code, iterable)
-
-Given a prefix code (a dict mapping symbols to bitarrays),
-iterate over the iterable object with symbols, and extend the bitarray
-with the corresponding bitarray for each symbols."""
-        _check_codedict(codedict)
-        self._encode(codedict, iterable)
-
-    def __int__(self):
-        raise TypeError("int() argument cannot be a bitarray")
-
-    def __long__(self):
-        raise TypeError("long() argument cannot be a bitarray")
-
-    def __float__(self):
-        raise TypeError("float() argument cannot be a bitarray")
-
-
-def test(verbosity=1, repeat=1):
-    """test(verbosity=1, repeat=1) -> TextTestResult
-
-Run self-test, and return unittest.runner.TextTestResult object.
-"""
-    from bitarray import test_bitarray
-    return test_bitarray.run(verbosity=verbosity, repeat=repeat)
diff --git a/shell/ext-py/bitarray-1.2.1/AUTHORS b/shell/ext-py/bitarray-1.2.1/AUTHORS
new file mode 100644
index 0000000..bc87e4a
--- /dev/null
+++ b/shell/ext-py/bitarray-1.2.1/AUTHORS
@@ -0,0 +1,22 @@
+bitarray is written and maintained by
+Ilan Schnell <il...@gmail.com>
+
+The author would like to thank the following people for patches, feedback,
+suggestions, and discussions:
+  - Roland Puntaier (Porting to Python 3.x)
+  - Daniel Stutzbach (for help with reference counts)
+  - Lluís Pàmies (C level itersearch)
+  - Vangelis Koukis (Python 2.4 support)
+  - Kris Kennaway
+  - Travis Oliphant
+  - Gael Varoquaux
+  - David Ormsbee
+  - David Kammeyer
+  - Bryce Hendrix
+  - Judah De Paula
+  - Corran Webster
+  - Chris Mueller
+  - Koen van de Sande
+  - Paul McGuire
+  - Chris Gohlke
+  - Ushma Bhatt
diff --git a/shell/ext-py/bitarray-1.2.1/CHANGE_LOG b/shell/ext-py/bitarray-1.2.1/CHANGE_LOG
new file mode 100644
index 0000000..f274ffc
--- /dev/null
+++ b/shell/ext-py/bitarray-1.2.1/CHANGE_LOG
@@ -0,0 +1,254 @@
+2020-01-06   1.2.1:
+-------------------
+  * simplify markdown of readme so PyPI renders better
+  * make tests for bitarray.util required (instead of warning when
+    they cannot be imported)
+
+
+2019-12-06   1.2.0:
+-------------------
+  * add bitarray.util module which provides useful utility functions
+  * deprecate `bitarray.bitdiff` in favor of `bitarray.util.count_xor`
+  * use markdown for documentation
+  * fix bug in .count() on 32bit systems in special cases when array size
+    is 2^29 bits or larger
+  * simplified tests by using bytes syntax
+  * update smallints and sieve example to use new utility module
+  * simplified mandel example to use numba
+  * use file context managers in tests
+
+
+2019-11-07   1.1.0:
+-------------------
+  * add frozenbitarray object
+  * add optional start and stop parameters to .count() method
+  * add official Python 3.8 support
+  * optimize setrange() C-function by using memset
+  * fix issue #74, bitarray is hashable on Python 2
+  * fix issue #68, `unittest.TestCase.assert_` deprecated
+  * improved test suite - tests should run in about 1 second
+  * update documentation to use positional-only syntax in docstrings
+  * update readme to pass Python 3 doctest
+  * add utils module to examples
+
+
+2019-07-19   1.0.1:
+-------------------
+  * fix readme to pass `twine check`
+
+
+2019-07-15   1.0.0:
+-------------------
+  * fix bitarrays beings created from unicode in Python 2
+  * use `PyBytes_*` in C code, treating the Py3k function names as default,
+    which also removes all redefinitions of `PyString_*`
+  * handle negative arguments of .index() method consistently with how
+    they are treated for lists
+  * add a few more comments to the C code
+  * move imports outside tests: pickle, io, etc.
+  * drop Python 2.5 support
+
+
+2019-05-20   0.9.3:
+-------------------
+  * refactor resize() - only shrink allocated memory if new size falls
+    lower than half the allocated size
+  * improve error message when trying to initialize from float or complex
+
+
+2019-04-29   0.9.2:
+-------------------
+  * fix to compile on Windows with VS 2015, issue #72
+
+
+2019-04-28   0.9.1:
+-------------------
+  * fix types to actually be types, #29
+  * check for ambiguous prefix codes when building binary tree for decoding
+  * remove Python level methods: encode, decode, iterdecode (in favor of
+    having these implemented on the C-level along with check_codedict)
+  * fix self tests for Python 2.5 and 2.6
+  * move all Huffman code related example code into examples/huffman
+  * add code to generate graphviz .dot file of Huffman tree to examples
+
+
+2019-04-22   0.9.0:
+-------------------
+  * more efficient decode and iterdecode by using C-level binary tree
+    instead of a python one, #54
+  * added buffer protocol support for Python 3, #55
+  * fixed invalid pointer exceptions in pypy, #47
+  * made all examples Py3k compatible
+  * add gene sequence example
+  * add official Python 3.7 support
+  * drop Python 2.4, 3.1 and 3.2 support
+
+
+2018-07-06   0.8.3:
+-------------------
+  * add exception to setup.py when README.rst cannot be opened
+
+
+2018-05-30   0.8.2:
+-------------------
+  * add official Python 3.6 support (although it was already working)
+  * fix description of fill(), #52
+  * handle extending self correctly, #28
+  * copy_n: fast copy with memmove fixed, #43
+  * minor clarity/wording changes to README, #23
+
+
+2013-03-30   0.8.1:
+-------------------
+  * fix issue #10, i.e. int(bitarray()) segfault
+  * added tests for using a bitarray object as an argument to functions
+    like int, long (on Python 2), float, list, tuple, dict
+
+
+2012-04-04   0.8.0:
+-------------------
+  * add Python 2.4 support
+  * add (module level) function bitdiff for calculating the difference
+    between two bitarrays
+
+
+2012-02-15   0.7.0:
+-------------------
+  * add iterdecode method (C level), which returns an iterator but is
+    otherwise like the decode method
+  * improve memory efficiency and speed of pickling large bitarray objects
+
+
+2012-02-06   0.6.0:
+-------------------
+  * add buffer protocol to bitarray objects (Python 2.7 only)
+  * allow slice assignment to 0 or 1, e.g. a[::3] = 0  (in addition to
+    booleans)
+  * moved implementation of itersearch method to C level (Lluis Pamies)
+  * search, itersearch now only except bitarray objects,
+    whereas __contains__ excepts either booleans or bitarrays
+  * use a priority queue for Huffman tree example (thanks to Ushma Bhatt)
+  * improve documentation
+
+
+2012-02-02   0.5.2:
+-------------------
+  * fixed MSVC compile error on Python 3 (thanks to Chris Gohlke)
+  * add missing start and stop optional parameters to index() method
+  * add examples/compress.py
+
+
+2012-01-31   0.5.1:
+-------------------
+  * update documentation to use tobytes and frombytes, rather than tostring
+    and fromstring (which are now deprecated)
+  * simplified how tests are run
+
+
+2012-01-23   0.5.0:
+-------------------
+  * added itersearch method
+  * added Bloom filter example
+  * minor fixes in docstrings, added more tests
+
+
+2011-12-29   0.4.0:
+-------------------
+  * porting to Python 3.x (Roland Puntaier)
+  * introduced tobytes, frombytes (tostring, fromstring are now deprecated)
+  * updated development status
+  * added sieve prime number example
+  * moved project to github: https://github.com/ilanschnell/bitarray
+
+
+2009-04-06   0.3.5:
+-------------------
+  * fixed reference counts bugs
+  * added possibility to slice assign to True or False, e.g. a[::3] = True
+    will set every third element to True
+
+
+2009-01-15   0.3.4:
+-------------------
+  * Made C code less ambiguous, such that the package compiles on
+    Visual Studio, with all tests passing.
+
+
+2008-12-14   0.3.3:
+-------------------
+  * Made changes to the C code to allow compilation with more compilers.
+    Compiles on Visual Studio, although there are still a few tests failing.
+
+
+2008-10-19   0.3.2:
+-------------------
+  * Added sequential search method.
+  * The special method __contains__ now also takes advantage of the
+    sequential search.
+
+
+2008-10-12   0.3.1:
+-------------------
+  * Simplified state information for pickling.  Argument for count is now
+    optional, defaults to True.  Fixed typos.
+
+
+2008-09-30   0.3.0:
+-------------------
+  * Fixed a severe bug for 64-bit machines.  Implemented all methods in C,
+    improved tests.
+  * Removed deprecated methods from01 and fromlist.
+
+
+2008-09-23   0.2.5:
+-------------------
+  * Added section in README about prefix codes.  Implemented _multiply method
+    for faster __mul__ and __imul__.  Fixed some typos.
+
+
+2008-09-22   0.2.4:
+-------------------
+  * Implemented encode and decode method (in C) for variable-length prefix
+    codes.
+  * Added more examples, wrote README for the examples.
+  * Added more tests, fixed some typos.
+
+
+2008-09-16   0.2.3:
+-------------------
+  * Fixed a memory leak, implemented a number of methods in C.
+    These include __getitem__, __setitem__, __delitem__, pop, remove,
+    insert.  The methods implemented on the Python level is very limit now.
+  * Implemented bitwise operations.
+
+
+2008-09-09   0.2.2:
+-------------------
+  * Rewrote parts of the README
+  * Implemented memory efficient algorithm for the reverse method
+  * Fixed typos, added a few tests, more C refactoring.
+
+
+2008-09-07   0.2.1:
+-------------------
+  * Improved tests, in particular added checking for memory leaks.
+  * Refactored many things on the C level.
+  * Implemented a few more methods.
+
+
+2008-09-02   0.2.0:
+-------------------
+  * Added bit endianness property to the bitarray object
+  * Added the examples to the release package.
+
+
+2008-08-17   0.1.0:
+-------------------
+  * First official release; put project to
+    http://pypi.python.org/pypi/bitarray/
+
+
+May 2008:
+---------
+Wrote the initial code, and put it on my personal web-site:
+http://ilan.schnell-web.net/prog/
diff --git a/shell/ext-py/bitarray-1.2.1/LICENSE b/shell/ext-py/bitarray-1.2.1/LICENSE
new file mode 100644
index 0000000..2004a1f
--- /dev/null
+++ b/shell/ext-py/bitarray-1.2.1/LICENSE
@@ -0,0 +1,48 @@
+PYTHON SOFTWARE FOUNDATION LICENSE
+----------------------------------
+
+1. This LICENSE AGREEMENT is between the Python Software Foundation
+("PSF"), and the Individual or Organization ("Licensee") accessing and
+otherwise using this software ("Python") in source or binary form and
+its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, PSF
+hereby grants Licensee a nonexclusive, royalty-free, world-wide
+license to reproduce, analyze, test, perform and/or display publicly,
+prepare derivative works, distribute, and otherwise use Python
+alone or in any derivative version, provided, however, that PSF's
+License Agreement and PSF's notice of copyright, i.e., "Copyright (c)
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Python Software Foundation; 
+All Rights Reserved" are retained in Python alone or in any derivative 
+version prepared by Licensee.
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python.
+
+4. PSF is making Python available to Licensee on an "AS IS"
+basis.  PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. Nothing in this License Agreement shall be deemed to create any
+relationship of agency, partnership, or joint venture between PSF and
+Licensee.  This License Agreement does not grant permission to use PSF
+trademarks or trade name in a trademark sense to endorse or promote
+products or services of Licensee, or any third party.
+
+8. By copying, installing or otherwise using Python, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
diff --git a/shell/ext-py/bitarray-1.2.1/README.md b/shell/ext-py/bitarray-1.2.1/README.md
new file mode 100644
index 0000000..b5ea6be
--- /dev/null
+++ b/shell/ext-py/bitarray-1.2.1/README.md
@@ -0,0 +1,695 @@
+bitarray: efficient arrays of booleans
+======================================
+
+This module provides an object type which efficiently represents an array
+of booleans.  Bitarrays are sequence types and behave very much like usual
+lists.  Eight bits are represented by one byte in a contiguous block of
+memory.  The user can select between two representations: little-endian
+and big-endian.  All of the functionality is implemented in C.
+Methods for accessing the machine representation are provided.
+This can be useful when bit level access to binary files is required,
+such as portable bitmap image files (.pbm).  Also, when dealing with
+compressed data which uses variable bit length encoding, you may find
+this module useful.
+
+
+Key features
+------------
+
+ * All functionality implemented in C.
+ * Bitarray objects behave very much like a list object, in particular
+   slicing (including slice assignment and deletion) is supported.
+ * The bit endianness can be specified for each bitarray object, see below.
+ * Packing and unpacking to other binary data formats, e.g. numpy.ndarray
+   is possible.
+ * Fast methods for encoding and decoding variable bit length prefix codes
+ * Bitwise operations: `&`, `|`, `^`, `&=`, `|=`, `^=`, `~`
+ * Sequential search
+ * Pickling and unpickling of bitarray objects.
+ * Bitarray objects support the buffer protocol (Python 2.7 and above)
+ * On 32-bit systems, a bitarray object can contain up to 2^34 elements,
+   that is 16 Gbits (on 64-bit machines up to 2^63 elements in theory).
+
+
+Installation
+------------
+
+Bitarray can be installed from source:
+
+    $ tar xzf bitarray-1.2.1.tar.gz
+    $ cd bitarray-1.2.1
+    $ python setup.py install
+
+On Unix systems, the latter command may have to be executed with root
+privileges.  You can also pip install bitarray.
+Once you have installed the package, you may want to test it:
+
+    $ python -c 'import bitarray; bitarray.test()'
+    bitarray is installed in: /usr/local/lib/python2.7/site-packages/bitarray
+    bitarray version: 1.2.1
+    3.7.4 (r271:86832, Dec 29 2018) [GCC 4.2.1 (SUSE Linux)]
+    .........................................................................
+    .........................................................................
+    ..............................
+    ----------------------------------------------------------------------
+    Ran 199 tests in 1.144s
+
+    OK
+
+You can always import the function test,
+and `test().wasSuccessful()` will return `True` when the test went well.
+
+
+Using the module
+----------------
+
+As mentioned above, bitarray objects behave very much like lists, so
+there is not too much to learn.  The biggest difference from list objects
+is the ability to access the machine representation of the object.
+When doing so, the bit endianness is of importance; this issue is
+explained in detail in the section below.  Here, we demonstrate the
+basic usage of bitarray objects:
+
+    >>> from bitarray import bitarray
+    >>> a = bitarray()            # create empty bitarray
+    >>> a.append(True)
+    >>> a.extend([False, True, True])
+    >>> a
+    bitarray('1011')
+
+Bitarray objects can be instantiated in different ways:
+
+    >>> a = bitarray(2**20)       # bitarray of length 1048576 (uninitialized)
+    >>> bitarray('1001011')       # from a string
+    bitarray('1001011')
+    >>> lst = [True, False, False, True, False, True, True]
+    >>> bitarray(lst)             # from list, tuple, iterable
+    bitarray('1001011')
+
+Bits can be assigned from any Python object, if the value can be interpreted
+as a truth value.  You can think of this as Python's built-in function bool()
+being applied, whenever casting an object:
+
+    >>> a = bitarray([42, '', True, {}, 'foo', None])
+    >>> a
+    bitarray('101010')
+    >>> a.append(a)      # note that bool(a) is True
+    >>> a.count(42)      # counts occurrences of True (not 42)
+    4
+    >>> a.remove('')     # removes first occurrence of False
+    >>> a
+    bitarray('110101')
+
+Like lists, bitarray objects support slice assignment and deletion:
+
+    >>> a = bitarray(50)
+    >>> a.setall(False)
+    >>> a[11:37:3] = 9 * bitarray([True])
+    >>> a
+    bitarray('00000000000100100100100100100100100100000000000000')
+    >>> del a[12::3]
+    >>> a
+    bitarray('0000000000010101010101010101000000000')
+    >>> a[-6:] = bitarray('10011')
+    >>> a
+    bitarray('000000000001010101010101010100010011')
+    >>> a += bitarray('000111')
+    >>> a[9:]
+    bitarray('001010101010101010100010011000111')
+
+In addition, slices can be assigned to booleans, which is easier (and
+faster) than assigning to a bitarray in which all values are the same:
+
+    >>> a = 20 * bitarray('0')
+    >>> a[1:15:3] = True
+    >>> a
+    bitarray('01001001001001000000')
+
+This is easier and faster than:
+
+    >>> a = 20 * bitarray('0')
+    >>> a[1:15:3] = 5 * bitarray('1')
+    >>> a
+    bitarray('01001001001001000000')
+
+Note that in the latter we have to create a temporary bitarray whose length
+must be known or calculated.
+
+
+Bit endianness
+--------------
+
+Since a bitarray allows addressing of individual bits, where the machine
+represents 8 bits in one byte, there are two obvious choices for this
+mapping: little- and big-endian.
+When creating a new bitarray object, the endianness can always be
+specified explicitly:
+
+    >>> a = bitarray(endian='little')
+    >>> a.frombytes(b'A')
+    >>> a
+    bitarray('10000010')
+    >>> b = bitarray('11000010', endian='little')
+    >>> b.tobytes()
+    b'C'
+
+Here, the low-bit comes first because little-endian means that increasing
+numeric significance corresponds to an increasing address (index).
+So a[0] is the lowest and least significant bit, and a[7] is the highest
+and most significant bit.
+
+    >>> a = bitarray(endian='big')
+    >>> a.frombytes(b'A')
+    >>> a
+    bitarray('01000001')
+    >>> a[6] = 1
+    >>> a.tobytes()
+    b'C'
+
+Here, the high-bit comes first because big-endian
+means "most-significant first".
+So a[0] is now the lowest and most significant bit, and a[7] is the highest
+and least significant bit.
+
+The bit endianness is a property attached to each bitarray object.
+When comparing bitarray objects, the endianness (and hence the machine
+representation) is irrelevant; what matters is the mapping from indices
+to bits:
+
+    >>> bitarray('11001', endian='big') == bitarray('11001', endian='little')
+    True
+
+Bitwise operations (`&`, `|`, `^`, `&=`, `|=`, `^=`, `~`) are implemented
+efficiently using the corresponding byte operations in C, i.e. the operators
+act on the machine representation of the bitarray objects.
+Therefore, one has to be cautious when applying the operation to bitarrays
+with different endianness.
+
+When converting to and from machine representation, using
+the `tobytes`, `frombytes`, `tofile` and `fromfile` methods,
+the endianness matters:
+
+    >>> a = bitarray(endian='little')
+    >>> a.frombytes(b'\x01')
+    >>> a
+    bitarray('10000000')
+    >>> b = bitarray(endian='big')
+    >>> b.frombytes(b'\x80')
+    >>> b
+    bitarray('10000000')
+    >>> a == b
+    True
+    >>> a.tobytes() == b.tobytes()
+    False
+
+The endianness can not be changed once an object is created.
+However, since creating a bitarray from another bitarray just copies the
+memory representing the data, you can create a new bitarray with different
+endianness:
+
+    >>> a = bitarray('11100000', endian='little')
+    >>> a
+    bitarray('11100000')
+    >>> b = bitarray(a, endian='big')
+    >>> b
+    bitarray('00000111')
+    >>> a == b
+    False
+    >>> a.tobytes() == b.tobytes()
+    True
+
+The default bit endianness is currently big-endian, however this may change
+in the future, and when dealing with the machine representation of bitarray
+objects, it is recommended to always explicitly specify the endianness.
+
+Unless explicitly converting to machine representation, using
+the `tobytes`, `frombytes`, `tofile` and `fromfile` methods,
+the bit endianness will have no effect on any computation, and one
+can safely ignore setting the endianness, and other details of this section.
+
+
+Buffer protocol
+---------------
+
+Python 2.7 provides memoryview objects, which allow Python code to access
+the internal data of an object that supports the buffer protocol without
+copying.  Bitarray objects support this protocol, with the memory being
+interpreted as simple bytes.
+
+    >>> a = bitarray('01000001' '01000010' '01000011', endian='big')
+    >>> v = memoryview(a)
+    >>> len(v)
+    3
+    >>> v[-1]
+    67
+    >>> v[:2].tobytes()
+    b'AB'
+    >>> v.readonly  # changing a bitarray's memory is also possible
+    False
+    >>> v[1] = 111
+    >>> a
+    bitarray('010000010110111101000011')
+
+
+Variable bit length prefix codes
+--------------------------------
+
+The method `encode` takes a dictionary mapping symbols to bitarrays
+and an iterable, and extends the bitarray object with the encoded symbols
+found while iterating.  For example:
+
+    >>> d = {'H':bitarray('111'), 'e':bitarray('0'),
+    ...      'l':bitarray('110'), 'o':bitarray('10')}
+    ...
+    >>> a = bitarray()
+    >>> a.encode(d, 'Hello')
+    >>> a
+    bitarray('111011011010')
+
+Note that the string `'Hello'` is an iterable, but the symbols are not
+limited to characters, in fact any immutable Python object can be a symbol.
+Taking the same dictionary, we can apply the `decode` method which will
+return a list of the symbols:
+
+    >>> a.decode(d)
+    ['H', 'e', 'l', 'l', 'o']
+    >>> ''.join(a.decode(d))
+    'Hello'
+
+Since symbols are not limited to being characters, it is necessary to return
+them as elements of a list, rather than simply returning the joined string.
+
+
+Reference
+=========
+
+The bitarray object:
+--------------------
+
+`bitarray(initial=0, /, endian='big')`
+
+Return a new bitarray object whose items are bits initialized from
+the optional initial object, and endianness.
+If no initial object is provided, an empty bitarray (length zero) is created.
+The initial object may be of the following types:
+
+`int`: Create a bitarray of given integer length.  The initial values are
+arbitrary.  If you want all values to be set, use the .setall() method.
+
+`str`: Create bitarray from a string of `0` and `1`.
+
+`list`, `tuple`, `iterable`: Create bitarray from a sequence, each
+element in the sequence is converted to a bit using its truth value.
+
+`bitarray`: Create bitarray from another bitarray.  This is done by
+copying the memory holding the bitarray data, and is hence very fast.
+
+The optional keyword arguments `endian` specifies the bit endianness of the
+created bitarray object.
+Allowed values are the strings `big` and `little` (default is `big`).
+
+Note that setting the bit endianness only has an effect when accessing the
+machine representation of the bitarray, i.e. when using the methods: tofile,
+fromfile, tobytes, frombytes.
+
+
+**A bitarray object supports the following methods:**
+
+`all()` -> bool
+
+Returns True when all bits in the array are True.
+
+
+`any()` -> bool
+
+Returns True when any bit in the array is True.
+
+
+`append(item, /)`
+
+Append the value `bool(item)` to the end of the bitarray.
+
+
+`buffer_info()` -> tuple
+
+Return a tuple (address, size, endianness, unused, allocated) giving the
+current memory address, the size (in bytes) used to hold the bitarray's
+contents, the bit endianness as a string, the number of unused bits
+(e.g. a bitarray of length 11 will have a buffer size of 2 bytes and
+5 unused bits), and the size (in bytes) of the allocated memory.
+
+
+`bytereverse()`
+
+For all bytes representing the bitarray, reverse the bit order (in-place).
+Note: This method changes the actual machine values representing the
+bitarray; it does not change the endianness of the bitarray object.
+
+
+`copy()` -> bitarray
+
+Return a copy of the bitarray.
+
+
+`count(value=True, start=0, stop=<end of array>, /)` -> int
+
+Count the number of occurrences of bool(value) in the bitarray.
+
+
+`decode(code, /)` -> list
+
+Given a prefix code (a dict mapping symbols to bitarrays),
+decode the content of the bitarray and return it as a list of symbols.
+
+
+`encode(code, iterable, /)`
+
+Given a prefix code (a dict mapping symbols to bitarrays),
+iterate over the iterable object with symbols, and extend the bitarray
+with the corresponding bitarray for each symbols.
+
+
+`endian()` -> str
+
+Return the bit endianness as a string (either `little` or `big`).
+
+
+`extend(iterable, /)`
+
+Append bits to the end of the bitarray.  The objects which can be passed
+to this method are the same iterable objects which can given to a bitarray
+object upon initialization.
+
+
+`fill()` -> int
+
+Adds zeros to the end of the bitarray, such that the length of the bitarray
+will be a multiple of 8.  Returns the number of bits added (0..7).
+
+
+`frombytes(bytes, /)`
+
+Append from a byte string, interpreted as machine values.
+
+
+`fromfile(f, n=<till EOF>, /)`
+
+Read n bytes from the file object f and append them to the bitarray
+interpreted as machine values.  When n is omitted, as many bytes are
+read until EOF is reached.
+
+
+`fromstring(str)`
+
+Append from a string, interpreting the string as machine values.
+Deprecated since version 0.4.0, use `.frombytes()` instead.
+
+
+`index(value, start=0, stop=<end of array>, /)` -> int
+
+Return index of the first occurrence of `bool(value)` in the bitarray.
+Raises `ValueError` if the value is not present.
+
+
+`insert(index, value, /)`
+
+Insert `bool(value)` into the bitarray before index.
+
+
+`invert()`
+
+Invert all bits in the array (in-place),
+i.e. convert each 1-bit into a 0-bit and vice versa.
+
+
+`iterdecode(code, /)` -> iterator
+
+Given a prefix code (a dict mapping symbols to bitarrays),
+decode the content of the bitarray and return an iterator over
+the symbols.
+
+
+`itersearch(bitarray, /)` -> iterator
+
+Searches for the given a bitarray in self, and return an iterator over
+the start positions where bitarray matches self.
+
+
+`length()` -> int
+
+Return the length, i.e. number of bits stored in the bitarray.
+This method is preferred over `__len__` (used when typing `len(a)`),
+since `__len__` will fail for a bitarray object with 2^31 or more elements
+on a 32bit machine, whereas this method will return the correct value,
+on 32bit and 64bit machines.
+
+
+`pack(bytes, /)`
+
+Extend the bitarray from bytes, where each byte corresponds to a single
+bit.  The byte `b'\x00'` maps to bit 0 and all other characters map to
+bit 1.
+This method, as well as the unpack method, are meant for efficient
+transfer of data between bitarray objects to other python objects
+(for example NumPy's ndarray object) which have a different memory view.
+
+
+`pop(index=-1, /)` -> item
+
+Return the i-th (default last) element and delete it from the bitarray.
+Raises `IndexError` if bitarray is empty or index is out of range.
+
+
+`remove(value, /)`
+
+Remove the first occurrence of `bool(value)` in the bitarray.
+Raises `ValueError` if item is not present.
+
+
+`reverse()`
+
+Reverse the order of bits in the array (in-place).
+
+
+`search(bitarray, limit=<none>, /)` -> list
+
+Searches for the given bitarray in self, and return the list of start
+positions.
+The optional argument limits the number of search results to the integer
+specified.  By default, all search results are returned.
+
+
+`setall(value, /)`
+
+Set all bits in the bitarray to `bool(value)`.
+
+
+`sort(reverse=False)`
+
+Sort the bits in the array (in-place).
+
+
+`to01()` -> str
+
+Return a string containing '0's and '1's, representing the bits in the
+bitarray object.
+Note: To extend a bitarray from a string containing '0's and '1's,
+use the extend method.
+
+
+`tobytes()` -> bytes
+
+Return the byte representation of the bitarray.
+When the length of the bitarray is not a multiple of 8, the few remaining
+bits (1..7) are considered to be 0.
+
+
+`tofile(f, /)`
+
+Write all bits (as machine values) to the file object f.
+When the length of the bitarray is not a multiple of 8,
+the remaining bits (1..7) are set to 0.
+
+
+`tolist()` -> list
+
+Return an ordinary list with the items in the bitarray.
+Note that the list object being created will require 32 or 64 times more
+memory than the bitarray object, which may cause a memory error if the
+bitarray is very large.
+Also note that to extend a bitarray with elements from a list,
+use the extend method.
+
+
+`tostring()` -> str
+
+Return the string representing (machine values) of the bitarray.
+When the length of the bitarray is not a multiple of 8, the few remaining
+bits (1..7) are set to 0.
+Deprecated since version 0.4.0, use `.tobytes()` instead.
+
+
+`unpack(zero=b'\x00', one=b'\xff')` -> bytes
+
+Return bytes containing one character for each bit in the bitarray,
+using the specified mapping.
+
+
+The frozenbitarray object:
+--------------------------
+
+`frozenbitarray(initial=0, /, endian='big')`
+
+Return a frozenbitarray object, which is initialized the same way a bitarray
+object is initialized.  A frozenbitarray is immutable and hashable.
+Its contents cannot be altered after is created; however, it can be used as
+a dictionary key.
+
+
+Functions defined in the module:
+--------------------------------
+
+`test(verbosity=1, repeat=1)` -> TextTestResult
+
+Run self-test, and return unittest.runner.TextTestResult object.
+
+
+`bitdiff(a, b, /)` -> int
+
+Return the difference between two bitarrays a and b.
+This is function does the same as (a ^ b).count(), but is more memory
+efficient, as no intermediate bitarray object gets created.
+Deprecated since version 1.2.0, use `bitarray.util.count_xor()` instead.
+
+
+`bits2bytes(n, /)` -> int
+
+Return the number of bytes necessary to store n bits.
+
+
+Functions defined in bitarray.util:
+-----------------------------------
+
+`zeros(length, /, endian='big')` -> bitarray
+
+Create a bitarray of length, with all values 0.
+
+
+`rindex(bitarray, value=True, /)` -> int
+
+Return the rightmost index of `bool(value)` in bitarray.
+Raises `ValueError` if the value is not present.
+
+
+`strip(bitarray, mode='right', /)` -> bitarray
+
+Strip zeros from left, right or both ends.
+Allowed values for mode are the strings: `left`, `right`, `both`
+
+
+`count_n(a, n, /)` -> int
+
+Find the smallest index `i` for which `a[:i].count() == n`.
+Raises `ValueError`, when n exceeds the `a.count()`.
+
+
+`count_and(a, b, /)` -> int
+
+Returns `(a & b).count()`, but is more memory efficient,
+as no intermediate bitarray object gets created.
+
+
+`count_or(a, b, /)` -> int
+
+Returns `(a | b).count()`, but is more memory efficient,
+as no intermediate bitarray object gets created.
+
+
+`count_xor(a, b, /)` -> int
+
+Returns `(a ^ b).count()`, but is more memory efficient,
+as no intermediate bitarray object gets created.
+
+
+`subset(a, b, /)` -> bool
+
+Return True if bitarray `a` is a subset of bitarray `b` (False otherwise).
+`subset(a, b)` is equivalent to `(a & b).count() == a.count()` but is more
+efficient since we can stop as soon as one mismatch is found, and no
+intermediate bitarray object gets created.
+
+
+`ba2hex(bitarray, /)` -> hexstr
+
+Return a bytes object containing with hexadecimal representation of
+the bitarray (which has to be multiple of 4 in length).
+
+
+`hex2ba(hexstr, /)` -> bitarray
+
+Bitarray of hexadecimal representation.
+hexstr may contain any number of hex digits (upper or lower case).
+
+
+`ba2int(bitarray, /)` -> int
+
+Convert the given bitarray into an integer.
+The bit-endianness of the bitarray is respected.
+
+
+`int2ba(int, /, length=None, endian='big')` -> bitarray
+
+Convert the given integer into a bitarray (with given endianness,
+and no leading (big-endian) / trailing (little-endian) zeros).
+If length is provided, the result will be of this length, and an
+`OverflowError` will be raised, if the integer cannot be represented
+within length bits.
+
+
+`huffman_code(dict, /, endian='big')` -> dict
+
+Given a frequency map, a dictionary mapping symbols to thier frequency,
+calculate the Huffman code, i.e. a dict mapping those symbols to
+bitarrays (with given endianness).  Note that the symbols may be any
+hashable object (including `None`).
+
+
+Change log
+----------
+
+*1.2.1* (2020-01-06):
+
+  * simplify markdown of readme so PyPI renders better
+  * make tests for bitarray.util required (instead of warning when
+    they cannot be imported)
+
+
+*1.2.0* (2019-12-06):
+
+  * add bitarray.util module which provides useful utility functions
+  * deprecate `bitarray.bitdiff` in favor of `bitarray.util.count_xor`
+  * use markdown for documentation
+  * fix bug in .count() on 32bit systems in special cases when array size
+    is 2^29 bits or larger
+  * simplified tests by using bytes syntax
+  * update smallints and sieve example to use new utility module
+  * simplified mandel example to use numba
+  * use file context managers in tests
+
+
+*1.1.0* (2019-11-07):
+
+  * add frozenbitarray object
+  * add optional start and stop parameters to .count() method
+  * add official Python 3.8 support
+  * optimize setrange() C-function by using memset
+  * fix issue #74, bitarray is hashable on Python 2
+  * fix issue #68, `unittest.TestCase.assert_` deprecated
+  * improved test suite - tests should run in about 1 second
+  * update documentation to use positional-only syntax in docstrings
+  * update readme to pass Python 3 doctest
+  * add utils module to examples
+
+
+Please find the complete change log
+<a href="https://github.com/ilanschnell/bitarray/blob/master/CHANGE_LOG">here</a>.
diff --git a/shell/ext-py/bitarray-1.2.1/TODO b/shell/ext-py/bitarray-1.2.1/TODO
new file mode 100644
index 0000000..7ea9550
--- /dev/null
+++ b/shell/ext-py/bitarray-1.2.1/TODO
@@ -0,0 +1,95 @@
+* compute the lexicographically next bit permutation, see
+  http://www-graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation
+
+* Write special tests for really large bitarrays, for which the length
+  exceeds 2**31 bits
+
+
+--------------------------- RANDOM NOTES ---------------------------------
+
+#!/bin/bash
+for PY in py26 py26d py27 py32 py33
+do
+    export PYTHON=$HOME/$PY/bin/python
+    make clean
+    make test || exit 1
+done
+
+#!/bin/bash
+for PY in 2.4 2.5 2.6 2.7 3.1 3.2 3.3
+do
+    PYBIN=$HOME/$PY/bin/python
+    rm -rf $HOME/$PY/lib/python$PY/site-packages
+    $PYBIN -V
+    rm -rf build dist
+    $PYBIN setup.py install >/dev/null 2>&1 || exit 1
+    pushd /tmp
+    $PYBIN -c "import bitarray; assert bitarray.test(repeat=1).wasSuccessful()" || \
+        exit 1
+    popd
+done
+
+
+
+# checking the growth pattern:
+a = bitarray()
+sizes = set()
+for i in xrange(1000000):
+    sizes.add(a.buffer_info()[4])
+    a.append(0)
+print sorted(sizes)
+
+
+/* walk the binary tree, and display information for each node */
+static void
+display_binode_tree(binode *tree)
+{
+    int k;
+
+    printf("id: %p child0: %14p child1: %14p symbol: %s\n",
+           tree,
+           tree->child[0],
+           tree->child[1],
+           tree->symbol ? PyString_AsString(tree->symbol) : "NULL");
+
+    for (k = 0; k < 2; k++)
+        if (tree->child[k])
+            display_binode_tree(tree->child[k]);
+}
+
+
+# If I should ever decide to use pre-calculated tables:
+static char bytereverse_trans[256] = {
+    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+    0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+    0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+    0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+    0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+    0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+    0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+    0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+    0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+    0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+    0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+    0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+    0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+    0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+    0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+    0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+    0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+    0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+    0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+    0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+    0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+    0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+    0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+    0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+    0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+    0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+    0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+    0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+    0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+    0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+    0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+};
diff --git a/shell/ext-py/bitarray-1.2.1/bitarray/__init__.py b/shell/ext-py/bitarray-1.2.1/bitarray/__init__.py
new file mode 100644
index 0000000..1b99326
--- /dev/null
+++ b/shell/ext-py/bitarray-1.2.1/bitarray/__init__.py
@@ -0,0 +1,91 @@
+"""
+This package defines an object type which can efficiently represent
+a bitarray.  Bitarrays are sequence types and behave very much like lists.
+
+Please find a description of this package at:
+
+    http://pypi.python.org/pypi/bitarray/
+
+Author: Ilan Schnell
+"""
+from bitarray._bitarray import _bitarray, bitdiff, bits2bytes, _sysinfo
+
+__version__ = '1.2.1'
+
+
+class bitarray(_bitarray):
+    """bitarray(initial=0, /, endian='big')
+
+Return a new bitarray object whose items are bits initialized from
+the optional initial object, and endianness.
+If no initial object is provided, an empty bitarray (length zero) is created.
+The initial object may be of the following types:
+
+`int`: Create a bitarray of given integer length.  The initial values are
+arbitrary.  If you want all values to be set, use the .setall() method.
+
+`str`: Create bitarray from a string of `0` and `1`.
+
+`list`, `tuple`, `iterable`: Create bitarray from a sequence, each
+element in the sequence is converted to a bit using its truth value.
+
+`bitarray`: Create bitarray from another bitarray.  This is done by
+copying the memory holding the bitarray data, and is hence very fast.
+
+The optional keyword arguments `endian` specifies the bit endianness of the
+created bitarray object.
+Allowed values are the strings `big` and `little` (default is `big`).
+
+Note that setting the bit endianness only has an effect when accessing the
+machine representation of the bitarray, i.e. when using the methods: tofile,
+fromfile, tobytes, frombytes."""
+
+    def fromstring(self, string):
+        """fromstring(str)
+
+Append from a string, interpreting the string as machine values.
+Deprecated since version 0.4.0, use `.frombytes()` instead."""
+        return self.frombytes(string.encode())
+
+    def tostring(self):
+        """tostring() -> str
+
+Return the string representing (machine values) of the bitarray.
+When the length of the bitarray is not a multiple of 8, the few remaining
+bits (1..7) are set to 0.
+Deprecated since version 0.4.0, use `.tobytes()` instead."""
+        return self.tobytes().decode()
+
+
+class frozenbitarray(_bitarray):
+    """frozenbitarray(initial=0, /, endian='big')
+
+Return a frozenbitarray object, which is initialized the same way a bitarray
+object is initialized.  A frozenbitarray is immutable and hashable.
+Its contents cannot be altered after is created; however, it can be used as
+a dictionary key.
+"""
+    def __repr__(self):
+        return 'frozen' + _bitarray.__repr__(self)
+
+    def __hash__(self):
+        if getattr(self, '_hash', None) is None:
+            self._hash = hash((self.length(), self.tobytes()))
+        return self._hash
+
+    def __delitem__(self, *args, **kwargs):
+        raise TypeError("'frozenbitarray' is immutable")
+
+    append = bytereverse = extend = encode = fill = __delitem__
+    frombytes = fromfile = insert = invert = pack = pop = __delitem__
+    remove = reverse = setall = sort = __setitem__ = __delitem__
+    __iand__ = __iadd__ = __imul__ = __ior__ = __ixor__ = __delitem__
+
+
+def test(verbosity=1, repeat=1):
+    """test(verbosity=1, repeat=1) -> TextTestResult
+
+Run self-test, and return unittest.runner.TextTestResult object.
+"""
+    from bitarray import test_bitarray
+    return test_bitarray.run(verbosity=verbosity, repeat=repeat)
diff --git a/shell/ext-py/bitarray-0.9.0/bitarray/_bitarray.c b/shell/ext-py/bitarray-1.2.1/bitarray/_bitarray.c
similarity index 83%
rename from shell/ext-py/bitarray-0.9.0/bitarray/_bitarray.c
rename to shell/ext-py/bitarray-1.2.1/bitarray/_bitarray.c
index d605f4c..c9ce6ba 100644
--- a/shell/ext-py/bitarray-0.9.0/bitarray/_bitarray.c
+++ b/shell/ext-py/bitarray-1.2.1/bitarray/_bitarray.c
@@ -1,6 +1,9 @@
 /*
-   This file is the C part of the bitarray package.  Almost all
-   functionality is implemented here.
+   Copyright (c) 2008 - 2019, Ilan Schnell
+   bitarray is published under the PSF license.
+
+   This file is the C part of the bitarray package.
+   All functionality is implemented here.
 
    Author: Ilan Schnell
 */
@@ -13,22 +16,9 @@
 #endif
 
 #ifdef IS_PY3K
-#include "bytesobject.h"
-#define PyString_FromStringAndSize  PyBytes_FromStringAndSize
-#define PyString_FromString  PyBytes_FromString
-#define PyString_Check  PyBytes_Check
-#define PyString_Size  PyBytes_Size
-#define PyString_AsString  PyBytes_AsString
-#define PyString_ConcatAndDel  PyBytes_ConcatAndDel
 #define Py_TPFLAGS_HAVE_WEAKREFS  0
 #endif
 
-#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
-/* backward compatibility with Python 2.5 */
-#define Py_TYPE(ob)   (((PyObject *) (ob))->ob_type)
-#define Py_SIZE(ob)   (((PyVarObject *) (ob))->ob_size)
-#endif
-
 #if PY_MAJOR_VERSION == 3 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION == 7)
 /* (new) buffer protocol */
 #define WITH_BUFFER
@@ -48,15 +38,17 @@ typedef long long int idx_t;
 /* throughout:  0 = little endian   1 = big endian */
 #define DEFAULT_ENDIAN  1
 
+/* Unlike the normal convention, ob_size is the byte count, not the number
+   of elements.  The reason for doing this is that we can use our own
+   special idx_t for the number of bits (which can exceed 2^32 on a 32 bit
+   machine.  */
 typedef struct {
     PyObject_VAR_HEAD
-#ifdef WITH_BUFFER
-    int ob_exports;             /* how many buffer exports */
-#endif
     char *ob_item;
     Py_ssize_t allocated;       /* how many bytes allocated */
-    idx_t nbits;                /* length og bitarray */
+    idx_t nbits;                /* length of bitarray, i.e. elements */
     int endian;                 /* bit endianness of bitarray */
+    int ob_exports;             /* how many buffer exports */
     PyObject *weakreflist;      /* list of weak references */
 } bitarrayobject;
 
@@ -64,22 +56,31 @@ static PyTypeObject Bitarraytype;
 
 #define bitarray_Check(obj)  PyObject_TypeCheck(obj, &Bitarraytype)
 
-#define BITS(bytes)  (((idx_t) 8) * ((idx_t) (bytes)))
+#define BITS(bytes)  ((idx_t) (bytes) << 3)
 
+/* number of bytes necessary to store given bits */
 #define BYTES(bits)  (((bits) == 0) ? 0 : (((bits) - 1) / 8 + 1))
 
 #define BITMASK(endian, i)  (((char) 1) << ((endian) ? (7 - (i)%8) : (i)%8))
 
 /* ------------ low level access to bits in bitarrayobject ------------- */
 
+#ifndef NDEBUG
+static int GETBIT(bitarrayobject *self, idx_t i) {
+    assert(0 <= i && i < self->nbits);
+    return ((self)->ob_item[(i) / 8] & BITMASK((self)->endian, i) ? 1 : 0);
+}
+#else
 #define GETBIT(self, i)  \
     ((self)->ob_item[(i) / 8] & BITMASK((self)->endian, i) ? 1 : 0)
+#endif
 
 static void
 setbit(bitarrayobject *self, idx_t i, int bit)
 {
     char *cp, mask;
 
+    assert(0 <= i && i < BITS(Py_SIZE(self)));
     mask = BITMASK(self->endian, i);
     cp = self->ob_item + i / 8;
     if (bit)
@@ -91,11 +92,9 @@ setbit(bitarrayobject *self, idx_t i, int bit)
 static int
 check_overflow(idx_t nbits)
 {
-    idx_t max_bits;
-
     assert(nbits >= 0);
-    if (sizeof(void *) == 4) {  /* 32bit machine */
-        max_bits = ((idx_t) 1) << 34;  /* 2^34 = 16 Gbits*/
+    if (sizeof(void *) == 4) {  /* 32bit system */
+        const idx_t max_bits = ((idx_t) 1) << 34;  /* 2^34 = 16 Gbits*/
         if (nbits > max_bits) {
             char buff[256];
             sprintf(buff, "cannot create bitarray of size %lld, "
@@ -111,50 +110,46 @@ static int
 resize(bitarrayobject *self, idx_t nbits)
 {
     Py_ssize_t newsize;
-    size_t _new_size;       /* for allocation */
+    size_t new_allocated;
+    Py_ssize_t allocated = self->allocated;
 
     if (check_overflow(nbits) < 0)
         return -1;
-
     newsize = (Py_ssize_t) BYTES(nbits);
 
     /* Bypass realloc() when a previous overallocation is large enough
-       to accommodate the newsize.  If the newsize is 16 smaller than the
-       current size, then proceed with the realloc() to shrink the list.
+       to accommodate the newsize.  If the newsize falls lower than half
+       the allocated size, then proceed with the realloc() to shrink.
     */
-    if (self->allocated >= newsize &&
-        Py_SIZE(self) < newsize + 16 &&
-        self->ob_item != NULL)
-    {
+    if (allocated >= newsize && newsize >= (allocated >> 1)) {
+        assert(self->ob_item != NULL || newsize == 0);
         Py_SIZE(self) = newsize;
         self->nbits = nbits;
         return 0;
     }
 
-    if (newsize >= Py_SIZE(self) + 65536)
-        /* Don't overallocate when the size increase is very large. */
-        _new_size = newsize;
-    else
-        /* This over-allocates proportional to the bitarray size, making
-           room for additional growth.  The over-allocation is mild, but is
-           enough to give linear-time amortized behavior over a long
-           sequence of appends() in the presence of a poorly-performing
-           system realloc().
+    new_allocated = (size_t) newsize;
+    if (newsize < Py_SIZE(self) + 65536)
+        /* Over-allocate unless the size increase is very large.
+           This over-allocates proportional to the bitarray size, making
+           room for additional growth.
            The growth pattern is:  0, 4, 8, 16, 25, 34, 44, 54, 65, 77, ...
            Note, the pattern starts out the same as for lists but then
            grows at a smaller rate so that larger bitarrays only overallocate
            by about 1/16th -- this is done because bitarrays are assumed
            to be memory critical.
         */
-        _new_size = (newsize >> 4) + (Py_SIZE(self) < 8 ? 3 : 7) + newsize;
+        new_allocated += (newsize >> 4) + (newsize < 8 ? 3 : 7);
 
-    self->ob_item = PyMem_Realloc(self->ob_item, _new_size);
+    if (newsize == 0)
+        new_allocated = 0;
+    self->ob_item = PyMem_Realloc(self->ob_item, new_allocated);
     if (self->ob_item == NULL) {
         PyErr_NoMemory();
         return -1;
     }
     Py_SIZE(self) = newsize;
-    self->allocated = _new_size;
+    self->allocated = new_allocated;
     self->nbits = nbits;
     return 0;
 }
@@ -181,7 +176,7 @@ newbitarrayobject(PyTypeObject *type, idx_t nbits, int endian)
         obj->ob_item = NULL;
     }
     else {
-        obj->ob_item = PyMem_Malloc((size_t) nbytes);
+        obj->ob_item = (char *) PyMem_Malloc((size_t) nbytes);
         if (obj->ob_item == NULL) {
             PyObject_Del(obj);
             PyErr_NoMemory();
@@ -215,30 +210,34 @@ copy_n(bitarrayobject *self, idx_t a,
     assert(0 <= n && n <= self->nbits && n <= other->nbits);
     assert(0 <= a && a <= self->nbits - n);
     assert(0 <= b && b <= other->nbits - n);
-    if (n == 0) {
+    if (n == 0)
         return;
-    }
 
+    /* When the start positions are at byte positions, we can copy whole
+       bytes using memmove, and copy the remaining few bits individually.
+       Note that the order of these two operations matters when copying
+       self to self. */
     if (self->endian == other->endian && a % 8 == 0 && b % 8 == 0 && n >= 8)
     {
         const Py_ssize_t bytes = (Py_ssize_t) n / 8;
-        const idx_t bits = bytes * 8;
+        const idx_t bits = BITS(bytes);
 
-        if (a <= b) {
+        assert(bits <= n && n < bits + 8);
+        if (a <= b)
             memmove(self->ob_item + a / 8, other->ob_item + b / 8, bytes);
-        }
-        if (n != bits) {
+
+        if (n != bits)
             copy_n(self, bits + a, other, bits + b, n - bits);
-        }
-        if (a > b) {
+
+        if (a > b)
             memmove(self->ob_item + a / 8, other->ob_item + b / 8, bytes);
-        }
+
         return;
     }
 
-    /* the different type of looping is only relevant when other and self
-       are the same object, i.e. when copying a piece of an bitarrayobject
-       onto itself */
+    /* The two different types of looping are only relevant when copying
+       self to self, i.e. when copying a piece of an bitarrayobject onto
+       itself. */
     if (a <= b) {
         for (i = 0; i < n; i++)             /* loop forward (delete) */
             setbit(self, i + a, GETBIT(other, i + b));
@@ -282,10 +281,10 @@ insert_n(bitarrayobject *self, idx_t start, idx_t n)
 static int
 setunused(bitarrayobject *self)
 {
-    idx_t i, n;
+    const idx_t n = BITS(Py_SIZE(self));
+    idx_t i;
     int res = 0;
 
-    n = BITS(Py_SIZE(self));
     for (i = self->nbits; i < n; i++) {
         setbit(self, i, 0);
         res++;
@@ -321,7 +320,7 @@ enum op_type {
     OP_xor,
 };
 
-/* perform bitwise operation */
+/* perform bitwise in-place operation */
 static int
 bitwise(bitarrayobject *self, PyObject *arg, enum op_type oper)
 {
@@ -354,6 +353,8 @@ bitwise(bitarrayobject *self, PyObject *arg, enum op_type oper)
         for (i = 0; i < Py_SIZE(self); i++)
             self->ob_item[i] ^= other->ob_item[i];
         break;
+    default:  /* should never happen */
+        return -1;
     }
     return 0;
 }
@@ -366,8 +367,24 @@ setrange(bitarrayobject *self, idx_t start, idx_t stop, int val)
 
     assert(0 <= start && start <= self->nbits);
     assert(0 <= stop && stop <= self->nbits);
-    for (i = start; i < stop; i++)
-        setbit(self, i, val);
+
+    if (self->nbits == 0 || start >= stop)
+        return;
+
+    if (stop >= start + 8) {
+        const Py_ssize_t byte_start = BYTES(start);
+        const Py_ssize_t byte_stop = (Py_ssize_t) stop / 8;
+        for (i = start; i < BITS(byte_start); i++)
+            setbit(self, i, val);
+        memset(self->ob_item + byte_start, val ? 0xff : 0x00,
+               byte_stop - byte_start);
+        for (i = BITS(byte_stop); i < stop; i++)
+            setbit(self, i, val);
+    }
+    else {
+        for (i = start; i < stop; i++)
+            setbit(self, i, val);
+    }
 }
 
 static void
@@ -430,18 +447,38 @@ static int bitcount_lookup[256] = {
 
 /* returns number of 1 bits */
 static idx_t
-count(bitarrayobject *self)
+count(bitarrayobject *self, int vi, idx_t start, idx_t stop)
 {
-    Py_ssize_t i;
-    idx_t res = 0;
+    idx_t i, res = 0;
     unsigned char c;
 
-    setunused(self);
-    for (i = 0; i < Py_SIZE(self); i++) {
-        c = self->ob_item[i];
-        res += bitcount_lookup[c];
+    assert(0 <= start && start <= self->nbits);
+    assert(0 <= stop && stop <= self->nbits);
+    assert(0 <= vi && vi <= 1);
+    assert(BYTES(stop) <= Py_SIZE(self));
+
+    if (self->nbits == 0 || start >= stop)
+        return 0;
+
+    if (stop >= start + 8) {
+        const Py_ssize_t byte_start = BYTES(start);
+        const Py_ssize_t byte_stop = (Py_ssize_t) (stop / 8);
+        Py_ssize_t j;
+
+        for (i = start; i < BITS(byte_start); i++)
+            res += GETBIT(self, i);
+        for (j = byte_start; j < byte_stop; j++) {
+            c = self->ob_item[j];
+            res += bitcount_lookup[c];
+        }
+        for (i = BITS(byte_stop); i < stop; i++)
+            res += GETBIT(self, i);
     }
-    return res;
+    else {
+        for (i = start; i < stop; i++)
+            res += GETBIT(self, i);
+    }
+    return vi ? res : stop - start - res;
 }
 
 /* return index of first occurrence of vi, -1 when x is not in found. */
@@ -450,31 +487,25 @@ findfirst(bitarrayobject *self, int vi, idx_t start, idx_t stop)
 {
     Py_ssize_t j;
     idx_t i;
-    char c;
 
-    if (Py_SIZE(self) == 0)
-        return -1;
-    if (start < 0 || start > self->nbits)
-        start = 0;
-    if (stop < 0 || stop > self->nbits)
-        stop = self->nbits;
-    if (start >= stop)
+    assert(0 <= start && start <= self->nbits);
+    assert(0 <= stop && stop <= self->nbits);
+    assert(0 <= vi && vi <= 1);
+    assert(BYTES(stop) <= Py_SIZE(self));
+
+    if (self->nbits == 0 || start >= stop)
         return -1;
 
-    if (stop > start + 8) {
+    if (stop >= start + 8) {
         /* seraching for 1 means: break when byte is not 0x00
            searching for 0 means: break when byte is not 0xff */
-        c = vi ? 0x00 : 0xff;
+        const char c = vi ? 0x00 : 0xff;
 
         /* skip ahead by checking whole bytes */
         for (j = (Py_ssize_t) (start / 8); j < BYTES(stop); j++)
             if (c ^ self->ob_item[j])
                 break;
 
-        if (j == Py_SIZE(self))
-            j--;
-        assert(0 <= j && j < Py_SIZE(self));
-
         if (start < BITS(j))
             start = BITS(j);
     }
@@ -487,8 +518,8 @@ findfirst(bitarrayobject *self, int vi, idx_t start, idx_t stop)
     return -1;
 }
 
-/* search for the first occurrence bitarray xa (in self), starting at p,
-   and return its position (-1 when not found)
+/* search for the first occurrence of bitarray xa (in self), starting at p,
+   and return its position (or -1 when not found)
 */
 static idx_t
 search(bitarrayobject *self, bitarrayobject *xa, idx_t p)
@@ -532,7 +563,7 @@ append_item(bitarrayobject *self, PyObject *item)
 static PyObject *
 unpack(bitarrayobject *self, char zero, char one)
 {
-    PyObject *res;
+    PyObject *result;
     Py_ssize_t i;
     char *str;
 
@@ -540,7 +571,7 @@ unpack(bitarrayobject *self, char zero, char one)
         PyErr_SetString(PyExc_OverflowError, "bitarray too large to unpack");
         return NULL;
     }
-    str = PyMem_Malloc((size_t) self->nbits);
+    str = (char *) PyMem_Malloc((size_t) self->nbits);
     if (str == NULL) {
         PyErr_NoMemory();
         return NULL;
@@ -548,9 +579,9 @@ unpack(bitarrayobject *self, char zero, char one)
     for (i = 0; i < self->nbits; i++) {
         *(str + i) = GETBIT(self, i) ? one : zero;
     }
-    res = PyString_FromStringAndSize(str, (Py_ssize_t) self->nbits);
+    result = PyBytes_FromStringAndSize(str, (Py_ssize_t) self->nbits);
     PyMem_Free((void *) str);
-    return res;
+    return result;
 }
 
 static int
@@ -562,10 +593,8 @@ extend_bitarray(bitarrayobject *self, bitarrayobject *other)
     if (other->nbits == 0)
         return 0;
 
-    /*
-        Note: other may be self. Thus we take the size before we resize,
-        ensuring we only copy the right parts of the array.
-    */
+    /* Note that other may be self.  Thus we take the size before we resize,
+       ensuring we only copy the right parts of the array. */
     n_other_bits = other->nbits;
     n_sum = self->nbits + other->nbits;
 
@@ -643,36 +672,35 @@ extend_tuple(bitarrayobject *self, PyObject *tuple)
     return 0;
 }
 
-/* extend_string(): extend the bitarray from a string, where each whole
-   characters is converted to a single bit
-*/
-enum conv_tp {
-    STR_01,    /*  '0' -> 0    '1'  -> 1   no other characters allowed */
-    STR_RAW,   /*  0x00 -> 0   other -> 1                              */
+/* extend_bytes(): extend the bitarray from a PyBytes object, where each
+   whole character is converted to a single bit */
+enum conv_t {
+    BYTES_01,    /*  '0' -> 0    '1'  -> 1   no other characters allowed */
+    BYTES_RAW,   /*  0x00 -> 0   other -> 1                              */
 };
 
 static int
-extend_string(bitarrayobject *self, PyObject *string, enum conv_tp conv)
+extend_bytes(bitarrayobject *self, PyObject *bytes, enum conv_t conv)
 {
     Py_ssize_t strlen, i;
     char c, *str;
     int vi = 0;
 
-    assert(PyString_Check(string));
-    strlen = PyString_Size(string);
+    assert(PyBytes_Check(bytes));
+    strlen = PyBytes_Size(bytes);
     if (strlen == 0)
         return 0;
 
     if (resize(self, self->nbits + strlen) < 0)
         return -1;
 
-    str = PyString_AsString(string);
+    str = PyBytes_AsString(bytes);
 
     for (i = 0; i < strlen; i++) {
         c = *(str + i);
         /* depending on conv, map c to bit */
         switch (conv) {
-        case STR_01:
+        case BYTES_01:
             switch (c) {
             case '0': vi = 0; break;
             case '1': vi = 1; break;
@@ -682,9 +710,11 @@ extend_string(bitarrayobject *self, PyObject *string, enum conv_tp conv)
                 return -1;
             }
             break;
-        case STR_RAW:
+        case BYTES_RAW:
             vi = c ? 1 : 0;
             break;
+        default:  /* should never happen */
+            return -1;
         }
         setbit(self, self->nbits - strlen + i, vi);
     }
@@ -692,20 +722,20 @@ extend_string(bitarrayobject *self, PyObject *string, enum conv_tp conv)
 }
 
 static int
-extend_rawstring(bitarrayobject *self, PyObject *string)
+extend_rawbytes(bitarrayobject *self, PyObject *bytes)
 {
     Py_ssize_t strlen;
     char *str;
 
-    assert(PyString_Check(string) && self->nbits % 8 == 0);
-    strlen = PyString_Size(string);
+    assert(PyBytes_Check(bytes) && self->nbits % 8 == 0);
+    strlen = PyBytes_Size(bytes);
     if (strlen == 0)
         return 0;
 
     if (resize(self, self->nbits + BITS(strlen)) < 0)
         return -1;
 
-    str = PyString_AsString(string);
+    str = PyBytes_AsString(bytes);
     memcpy(self->ob_item + (Py_SIZE(self) - strlen), str, strlen);
     return 0;
 }
@@ -726,18 +756,16 @@ extend_dispatch(bitarrayobject *self, PyObject *obj)
     if (PyTuple_Check(obj))                                  /* tuple */
         return extend_tuple(self, obj);
 
-    if (PyString_Check(obj))                                 /* str01 */
-        return extend_string(self, obj, STR_01);
+    if (PyBytes_Check(obj))                               /* bytes 01 */
+        return extend_bytes(self, obj, BYTES_01);
 
-#ifdef IS_PY3K
-    if (PyUnicode_Check(obj)) {                               /* str01 */
-        PyObject *string;
-        string = PyUnicode_AsEncodedString(obj, NULL, NULL);
-        ret = extend_string(self, string, STR_01);
-        Py_DECREF(string);
+    if (PyUnicode_Check(obj)) {                /* (unicode) string 01 */
+        PyObject *bytes;
+        bytes = PyUnicode_AsEncodedString(obj, NULL, NULL);
+        ret = extend_bytes(self, bytes, BYTES_01);
+        Py_DECREF(bytes);
         return ret;
     }
-#endif
 
     if (PyIter_Check(obj))                                    /* iter */
         return extend_iter(self, obj);
@@ -760,7 +788,7 @@ extend_dispatch(bitarrayobject *self, PyObject *obj)
 #ifdef IS_PY3K
 #define IS_INDEX(x)  (PyLong_Check(x) || PyIndex_Check(x))
 #define IS_INT_OR_BOOL(x)  (PyBool_Check(x) || PyLong_Check(x))
-#else
+#else  /* Py 2 */
 #define IS_INDEX(x)  (PyInt_Check(x) || PyLong_Check(x) || PyIndex_Check(x))
 #define IS_INT_OR_BOOL(x)  (PyBool_Check(x) || PyInt_Check(x) || \
                                                PyLong_Check(x))
@@ -798,6 +826,19 @@ IntBool_AsInt(PyObject *v)
     return (int) x;
 }
 
+/* Normalize index (which may be negative), such that 0 <= i <= n */
+static void
+normalize_index(idx_t n, idx_t *i)
+{
+    if (*i < 0) {
+        *i += n;
+        if (*i < 0)
+            *i = 0;
+    }
+    if (*i > n)
+        *i = n;
+}
+
 /* Extract a slice index from a PyInt or PyLong or an object with the
    nb_index slot defined, and store in *i.
    However, this function returns -1 on error and 0 on success.
@@ -902,8 +943,8 @@ PyDoc_STRVAR(length_doc,
 "length() -> int\n\
 \n\
 Return the length, i.e. number of bits stored in the bitarray.\n\
-This method is preferred over __len__ (used when typing ``len(a)``),\n\
-since __len__ will fail for a bitarray object with 2^31 or more elements\n\
+This method is preferred over `__len__` (used when typing `len(a)`),\n\
+since `__len__` will fail for a bitarray object with 2^31 or more elements\n\
 on a 32bit machine, whereas this method will return the correct value,\n\
 on 32bit and 64bit machines.");
 
@@ -937,27 +978,34 @@ Return a copy of the bitarray.");
 static PyObject *
 bitarray_count(bitarrayobject *self, PyObject *args)
 {
-    idx_t n1;
-    long x = 1;
+    PyObject *x = Py_True;
+    idx_t start = 0, stop = self->nbits;
+    long vi;
 
-    if (!PyArg_ParseTuple(args, "|i:count", &x))
+    if (!PyArg_ParseTuple(args, "|OLL:count", &x, &start, &stop))
         return NULL;
 
-    n1 = count(self);
-    return PyLong_FromLongLong(x ? n1 : (self->nbits - n1));
+    vi = PyObject_IsTrue(x);
+    if (vi < 0)
+        return NULL;
+
+    normalize_index(self->nbits, &start);
+    normalize_index(self->nbits, &stop);
+
+    return PyLong_FromLongLong(count(self, vi, start, stop));
 }
 
 PyDoc_STRVAR(count_doc,
-"count([value]) -> int\n\
+"count(value=True, start=0, stop=<end of array>, /) -> int\n\
 \n\
-Return number of occurrences of value (defaults to True) in the bitarray.");
+Count the number of occurrences of bool(value) in the bitarray.");
 
 
 static PyObject *
 bitarray_index(bitarrayobject *self, PyObject *args)
 {
     PyObject *x;
-    idx_t i, start = 0, stop = -1;
+    idx_t i, start = 0, stop = self->nbits;
     long vi;
 
     if (!PyArg_ParseTuple(args, "O|LL:index", &x, &start, &stop))
@@ -967,6 +1015,9 @@ bitarray_index(bitarrayobject *self, PyObject *args)
     if (vi < 0)
         return NULL;
 
+    normalize_index(self->nbits, &start);
+    normalize_index(self->nbits, &stop);
+
     i = findfirst(self, vi, start, stop);
     if (i < 0) {
         PyErr_SetString(PyExc_ValueError, "index(x): x not in bitarray");
@@ -976,10 +1027,10 @@ bitarray_index(bitarrayobject *self, PyObject *args)
 }
 
 PyDoc_STRVAR(index_doc,
-"index(value, [start, [stop]]) -> int\n\
+"index(value, start=0, stop=<end of array>, /) -> int\n\
 \n\
-Return index of the first occurrence of bool(value) in the bitarray.\n\
-Raises ValueError if the value is not present.");
+Return index of the first occurrence of `bool(value)` in the bitarray.\n\
+Raises `ValueError` if the value is not present.");
 
 
 static PyObject *
@@ -991,7 +1042,7 @@ bitarray_extend(bitarrayobject *self, PyObject *obj)
 }
 
 PyDoc_STRVAR(extend_doc,
-"extend(object)\n\
+"extend(iterable, /)\n\
 \n\
 Append bits to the end of the bitarray.  The objects which can be passed\n\
 to this method are the same iterable objects which can given to a bitarray\n\
@@ -1009,7 +1060,7 @@ bitarray_contains(bitarrayobject *self, PyObject *x)
         vi = IntBool_AsInt(x);
         if (vi < 0)
             return NULL;
-        res = findfirst(self, vi, 0, -1) >= 0;
+        res = findfirst(self, vi, 0, self->nbits) >= 0;
     }
     else if (bitarray_Check(x)) {
         res = search(self, (bitarrayobject *) x, 0) >= 0;
@@ -1022,10 +1073,10 @@ bitarray_contains(bitarrayobject *self, PyObject *x)
 }
 
 PyDoc_STRVAR(contains_doc,
-"__contains__(x) -> bool\n\
+"__contains__(value, /) -> bool\n\
 \n\
-Return True if bitarray contains x, False otherwise.\n\
-The value x may be a boolean (or integer between 0 and 1), or a bitarray.");
+Return True if bitarray contains value, False otherwise.\n\
+The value may be a boolean (or integer between 0 and 1), or a bitarray.");
 
 
 static PyObject *
@@ -1075,10 +1126,10 @@ bitarray_search(bitarrayobject *self, PyObject *args)
 }
 
 PyDoc_STRVAR(search_doc,
-"search(bitarray, [limit]) -> list\n\
+"search(bitarray, limit=<none>, /) -> list\n\
 \n\
-Searches for the given a bitarray in self, and returns the start positions\n\
-where bitarray matches self as a list.\n\
+Searches for the given bitarray in self, and return the list of start\n\
+positions.\n\
 The optional argument limits the number of search results to the integer\n\
 specified.  By default, all search results are returned.");
 
@@ -1120,9 +1171,9 @@ bitarray_endian(bitarrayobject *self)
 }
 
 PyDoc_STRVAR(endian_doc,
-"endian() -> string\n\
+"endian() -> str\n\
 \n\
-Return the bit endianness as a string (either 'little' or 'big').");
+Return the bit endianness as a string (either `little` or `big`).");
 
 
 static PyObject *
@@ -1135,15 +1186,15 @@ bitarray_append(bitarrayobject *self, PyObject *v)
 }
 
 PyDoc_STRVAR(append_doc,
-"append(item)\n\
+"append(item, /)\n\
 \n\
-Append the value bool(item) to the end of the bitarray.");
+Append the value `bool(item)` to the end of the bitarray.");
 
 
 static PyObject *
 bitarray_all(bitarrayobject *self)
 {
-    if (findfirst(self, 0, 0, -1) >= 0)
+    if (findfirst(self, 0, 0, self->nbits) >= 0)
         Py_RETURN_FALSE;
     else
         Py_RETURN_TRUE;
@@ -1158,7 +1209,7 @@ Returns True when all bits in the array are True.");
 static PyObject *
 bitarray_any(bitarrayobject *self)
 {
-    if (findfirst(self, 1, 0, -1) >= 0)
+    if (findfirst(self, 1, 0, self->nbits) >= 0)
         Py_RETURN_TRUE;
     else
         Py_RETURN_FALSE;
@@ -1184,14 +1235,14 @@ bitarray_reduce(bitarrayobject *self)
     }
     /* the first byte indicates the number of unused bits at the end, and
        the rest of the bytes consist of the raw binary data */
-    str = PyMem_Malloc(Py_SIZE(self) + 1);
+    str = (char *) PyMem_Malloc(Py_SIZE(self) + 1);
     if (str == NULL) {
         PyErr_NoMemory();
         goto error;
     }
     str[0] = (char) setunused(self);
     memcpy(str + 1, self->ob_item, Py_SIZE(self));
-    repr = PyString_FromStringAndSize(str, Py_SIZE(self) + 1);
+    repr = PyBytes_FromStringAndSize(str, Py_SIZE(self) + 1);
     if (repr == NULL)
         goto error;
     PyMem_Free((void *) str);
@@ -1307,9 +1358,9 @@ bitarray_setall(bitarrayobject *self, PyObject *v)
 }
 
 PyDoc_STRVAR(setall_doc,
-"setall(value)\n\
+"setall(value, /)\n\
 \n\
-Set all bits in the bitarray to bool(value).");
+Set all bits in the bitarray to `bool(value)`.");
 
 
 static PyObject *
@@ -1317,13 +1368,13 @@ bitarray_sort(bitarrayobject *self, PyObject *args, PyObject *kwds)
 {
     idx_t n, n0, n1;
     int reverse = 0;
-    static char* kwlist[] = {"reverse", NULL};
+    static char *kwlist[] = {"reverse", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:sort", kwlist, &reverse))
         return NULL;
 
     n = self->nbits;
-    n1 = count(self);
+    n1 = count(self, 1, 0, n);
 
     if (reverse) {
         setrange(self, 0, n1, 1);
@@ -1343,6 +1394,10 @@ PyDoc_STRVAR(sort_doc,
 Sort the bits in the array (in-place).");
 
 
+/* since too many details differ between the Python 2 and 3 implementation
+   of this function, we choose to have two separate function implementation,
+   even though this means some of the code is duplicated in the two versions
+*/
 #ifdef IS_PY3K
 static PyObject *
 bitarray_fromfile(bitarrayobject *self, PyObject *args)
@@ -1381,7 +1436,6 @@ bitarray_fromfile(bitarrayobject *self, PyObject *args)
             Py_DECREF(reader);
             return NULL;
         }
-
         nread = PyBytes_Size(result);
 
         t = self->nbits;
@@ -1396,7 +1450,6 @@ bitarray_fromfile(bitarrayobject *self, PyObject *args)
             Py_DECREF(reader);
             return NULL;
         }
-
         memcpy(self->ob_item + (Py_SIZE(self) - nread),
                PyBytes_AS_STRING(result), nread);
 
@@ -1411,10 +1464,9 @@ bitarray_fromfile(bitarrayobject *self, PyObject *args)
 
     Py_DECREF(rargs);
     Py_DECREF(reader);
-
     Py_RETURN_NONE;
 }
-#else
+#else  /* Python 2 */
 static PyObject *
 bitarray_fromfile(bitarrayobject *self, PyObject *args)
 {
@@ -1478,13 +1530,16 @@ bitarray_fromfile(bitarrayobject *self, PyObject *args)
 #endif
 
 PyDoc_STRVAR(fromfile_doc,
-"fromfile(f, [n])\n\
+"fromfile(f, n=<till EOF>, /)\n\
 \n\
 Read n bytes from the file object f and append them to the bitarray\n\
 interpreted as machine values.  When n is omitted, as many bytes are\n\
 read until EOF is reached.");
 
 
+/* since too many details differ between the Python 2 and 3 implementation
+   of this function, we choose to have two separate function implementation
+*/
 #ifdef IS_PY3K
 static PyObject *
 bitarray_tofile(bitarrayobject *self, PyObject *f)
@@ -1522,7 +1577,7 @@ bitarray_tofile(bitarrayobject *self, PyObject *f)
     Py_DECREF(result);
     Py_RETURN_NONE;
 }
-#else
+#else  /* Python 2 */
 static PyObject *
 bitarray_tofile(bitarrayobject *self, PyObject *f)
 {
@@ -1549,7 +1604,7 @@ bitarray_tofile(bitarrayobject *self, PyObject *f)
 #endif
 
 PyDoc_STRVAR(tofile_doc,
-"tofile(f)\n\
+"tofile(f, /)\n\
 \n\
 Write all bits (as machine values) to the file object f.\n\
 When the length of the bitarray is not a multiple of 8,\n\
@@ -1585,19 +1640,25 @@ use the extend method.");
 
 
 static PyObject *
-bitarray_frombytes(bitarrayobject *self, PyObject *string)
+bitarray_frombytes(bitarrayobject *self, PyObject *bytes)
 {
     idx_t t, p;
 
-    if (!PyString_Check(string)) {
-        PyErr_SetString(PyExc_TypeError, "byte string expected");
+    if (!PyBytes_Check(bytes)) {
+        PyErr_SetString(PyExc_TypeError, "bytes expected");
         return NULL;
     }
+
+    /* Before we extend the raw bytes with the new data, we need to store
+       the current size and pad the last byte, as our bitarray size might
+       not be a multiple of 8.  After extending, we remove the padding
+       bits again.  The same is done in bitarray_fromfile().
+    */
     t = self->nbits;
     p = setunused(self);
     self->nbits += p;
 
-    if (extend_rawstring(self, string) < 0)
+    if (extend_rawbytes(self, bytes) < 0)
         return NULL;
     if (delete_n(self, t, p) < 0)
         return NULL;
@@ -1605,7 +1666,7 @@ bitarray_frombytes(bitarrayobject *self, PyObject *string)
 }
 
 PyDoc_STRVAR(frombytes_doc,
-"frombytes(bytes)\n\
+"frombytes(bytes, /)\n\
 \n\
 Append from a byte string, interpreted as machine values.");
 
@@ -1614,7 +1675,7 @@ static PyObject *
 bitarray_tobytes(bitarrayobject *self)
 {
     setunused(self);
-    return PyString_FromStringAndSize(self->ob_item, Py_SIZE(self));
+    return PyBytes_FromStringAndSize(self->ob_item, Py_SIZE(self));
 }
 
 PyDoc_STRVAR(tobytes_doc,
@@ -1622,16 +1683,19 @@ PyDoc_STRVAR(tobytes_doc,
 \n\
 Return the byte representation of the bitarray.\n\
 When the length of the bitarray is not a multiple of 8, the few remaining\n\
-bits (1..7) are set to 0.");
+bits (1..7) are considered to be 0.");
 
 
 static PyObject *
 bitarray_to01(bitarrayobject *self)
 {
 #ifdef IS_PY3K
-    PyObject *string, *unpacked;
+    PyObject *string;
+    PyObject *unpacked;
 
     unpacked = unpack(self, '0', '1');
+    if (unpacked == NULL)
+        return NULL;
     string = PyUnicode_FromEncodedObject(unpacked, NULL, NULL);
     Py_DECREF(unpacked);
     return string;
@@ -1641,7 +1705,7 @@ bitarray_to01(bitarrayobject *self)
 }
 
 PyDoc_STRVAR(to01_doc,
-"to01() -> string\n\
+"to01() -> str\n\
 \n\
 Return a string containing '0's and '1's, representing the bits in the\n\
 bitarray object.\n\
@@ -1653,7 +1717,7 @@ static PyObject *
 bitarray_unpack(bitarrayobject *self, PyObject *args, PyObject *kwds)
 {
     char zero = 0x00, one = 0xff;
-    static char* kwlist[] = {"zero", "one", NULL};
+    static char *kwlist[] = {"zero", "one", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|cc:unpack", kwlist,
                                      &zero, &one))
@@ -1665,61 +1729,61 @@ bitarray_unpack(bitarrayobject *self, PyObject *args, PyObject *kwds)
 PyDoc_STRVAR(unpack_doc,
 "unpack(zero=b'\\x00', one=b'\\xff') -> bytes\n\
 \n\
-Return a byte string containing one character for each bit in the bitarray,\n\
-using the specified mapping.\n\
-See also the pack method.");
+Return bytes containing one character for each bit in the bitarray,\n\
+using the specified mapping.");
 
 
 static PyObject *
-bitarray_pack(bitarrayobject *self, PyObject *string)
+bitarray_pack(bitarrayobject *self, PyObject *bytes)
 {
-    if (!PyString_Check(string)) {
-        PyErr_SetString(PyExc_TypeError, "byte string expected");
+    if (!PyBytes_Check(bytes)) {
+        PyErr_SetString(PyExc_TypeError, "bytes expected");
         return NULL;
     }
-    if (extend_string(self, string, STR_RAW) < 0)
+    if (extend_bytes(self, bytes, BYTES_RAW) < 0)
         return NULL;
 
     Py_RETURN_NONE;
 }
 
 PyDoc_STRVAR(pack_doc,
-"pack(bytes)\n\
+"pack(bytes, /)\n\
 \n\
-Extend the bitarray from a byte string, where each characters corresponds to\n\
-a single bit.  The character b'\\x00' maps to bit 0 and all other characters\n\
-map to bit 1.\n\
+Extend the bitarray from bytes, where each byte corresponds to a single\n\
+bit.  The byte `b'\\x00'` maps to bit 0 and all other characters map to\n\
+bit 1.\n\
 This method, as well as the unpack method, are meant for efficient\n\
 transfer of data between bitarray objects to other python objects\n\
-(for example NumPy's ndarray object) which have a different view of memory.");
+(for example NumPy's ndarray object) which have a different memory view.");
 
 
 static PyObject *
 bitarray_repr(bitarrayobject *self)
 {
-    PyObject *string;
+    PyObject *bytes;
+    PyObject *unpacked;
 #ifdef IS_PY3K
     PyObject *decoded;
 #endif
 
     if (self->nbits == 0) {
-        string = PyString_FromString("bitarray()");
-        if (string == NULL)
-            return NULL;
+        bytes = PyBytes_FromString("bitarray()");
     }
     else {
-        string = PyString_FromString("bitarray(\'");
-        if (string == NULL)
+        bytes = PyBytes_FromString("bitarray(\'");
+        unpacked = unpack(self, '0', '1');
+        if (unpacked == NULL)
             return NULL;
-        PyString_ConcatAndDel(&string, unpack(self, '0', '1'));
-        PyString_ConcatAndDel(&string, PyString_FromString("\')"));
+        PyBytes_ConcatAndDel(&bytes, unpacked);
+        PyBytes_ConcatAndDel(&bytes, PyBytes_FromString("\')"));
     }
 #ifdef IS_PY3K
-    decoded = PyUnicode_FromEncodedObject(string, NULL, NULL);
-    Py_DECREF(string);
-    string = decoded;
+    decoded = PyUnicode_FromEncodedObject(bytes, NULL, NULL);
+    Py_DECREF(bytes);
+    return decoded;
+#else
+    return bytes;  /* really a string in Python 2 */
 #endif
-    return string;
 }
 
 
@@ -1732,13 +1796,7 @@ bitarray_insert(bitarrayobject *self, PyObject *args)
     if (!PyArg_ParseTuple(args, "LO:insert", &i, &v))
         return NULL;
 
-    if (i < 0) {
-        i += self->nbits;
-        if (i < 0)
-            i = 0;
-    }
-    if (i > self->nbits)
-        i = self->nbits;
+    normalize_index(self->nbits, &i);
 
     if (insert_n(self, i, 1) < 0)
         return NULL;
@@ -1748,9 +1806,9 @@ bitarray_insert(bitarrayobject *self, PyObject *args)
 }
 
 PyDoc_STRVAR(insert_doc,
-"insert(i, item)\n\
+"insert(index, value, /)\n\
 \n\
-Insert bool(item) into the bitarray before position i.");
+Insert `bool(value)` into the bitarray before index.");
 
 
 static PyObject *
@@ -1781,10 +1839,10 @@ bitarray_pop(bitarrayobject *self, PyObject *args)
 }
 
 PyDoc_STRVAR(pop_doc,
-"pop([i]) -> item\n\
+"pop(index=-1, /) -> item\n\
 \n\
 Return the i-th (default last) element and delete it from the bitarray.\n\
-Raises IndexError if bitarray is empty or index is out of range.");
+Raises `IndexError` if bitarray is empty or index is out of range.");
 
 
 static PyObject *
@@ -1797,7 +1855,7 @@ bitarray_remove(bitarrayobject *self, PyObject *v)
     if (vi < 0)
         return NULL;
 
-    i = findfirst(self, vi, 0, -1);
+    i = findfirst(self, vi, 0, self->nbits);
     if (i < 0) {
         PyErr_SetString(PyExc_ValueError, "remove(x): x not in bitarray");
         return NULL;
@@ -1808,10 +1866,10 @@ bitarray_remove(bitarrayobject *self, PyObject *v)
 }
 
 PyDoc_STRVAR(remove_doc,
-"remove(item)\n\
+"remove(value, /)\n\
 \n\
-Remove the first occurrence of bool(item) in the bitarray.\n\
-Raises ValueError if item is not present.");
+Remove the first occurrence of `bool(value)` in the bitarray.\n\
+Raises `ValueError` if item is not present.");
 
 
 /* --------- special methods ----------- */
@@ -2097,12 +2155,43 @@ BITWISE_IFUNC(xor)
 
 /******************* variable length encoding and decoding ***************/
 
+static int
+check_codedict(PyObject *codedict)
+{
+    PyObject *key, *value;
+    Py_ssize_t pos = 0;
+
+    if (!PyDict_Check(codedict)) {
+        PyErr_SetString(PyExc_TypeError, "dict expected");
+        return -1;
+    }
+    if (PyDict_Size(codedict) == 0) {
+        PyErr_SetString(PyExc_ValueError, "prefix code dict empty");
+        return -1;
+    }
+    while (PyDict_Next(codedict, &pos, &key, &value)) {
+        if (!bitarray_Check(value)) {
+            PyErr_SetString(PyExc_TypeError,
+                            "bitarray expected for dict value");
+            return -1;
+        }
+        if (((bitarrayobject *) value)->nbits == 0) {
+            PyErr_SetString(PyExc_ValueError, "non-empty bitarray expected");
+            return -1;
+        }
+    }
+    return 0;
+}
+
 static PyObject *
 bitarray_encode(bitarrayobject *self, PyObject *args)
 {
     PyObject *codedict, *iterable, *iter, *symbol, *bits;
 
-    if (!PyArg_ParseTuple(args, "OO:_encode", &codedict, &iterable))
+    if (!PyArg_ParseTuple(args, "OO:encode", &codedict, &iterable))
+        return NULL;
+
+    if (check_codedict(codedict) < 0)
         return NULL;
 
     iter = PyObject_GetIter(iterable);
@@ -2115,7 +2204,8 @@ bitarray_encode(bitarrayobject *self, PyObject *args)
         bits = PyDict_GetItem(codedict, symbol);
         Py_DECREF(symbol);
         if (bits == NULL) {
-            PyErr_SetString(PyExc_ValueError, "symbol not in prefix code");
+            PyErr_SetString(PyExc_ValueError,
+                            "symbol not defined in prefix code");
             goto error;
         }
         if (extend_bitarray(self, (bitarrayobject *) bits) < 0)
@@ -2131,16 +2221,18 @@ error:
 }
 
 PyDoc_STRVAR(encode_doc,
-"_encode(code, iterable)\n\
+"encode(code, iterable, /)\n\
 \n\
-like the encode method without code checking");
+Given a prefix code (a dict mapping symbols to bitarrays),\n\
+iterate over the iterable object with symbols, and extend the bitarray\n\
+with the corresponding bitarray for each symbols.");
 
 
-/* Binary Tree definition */
+/* Binary tree definition */
 typedef struct _bin_node
 {
-    PyObject *symbol;
     struct _bin_node *child[2];
+    PyObject *symbol;
 } binode;
 
 
@@ -2149,39 +2241,44 @@ new_binode(void)
 {
     binode *nd;
 
-    nd = PyMem_Malloc(sizeof *nd);
+    nd = (binode *) PyMem_Malloc(sizeof(binode));
     if (nd == NULL) {
         PyErr_NoMemory();
         return NULL;
     }
-    nd->symbol = NULL;
     nd->child[0] = NULL;
     nd->child[1] = NULL;
+    nd->symbol = NULL;
     return nd;
 }
 
 static void
-delete_binode_tree(binode *root)
+delete_binode_tree(binode *tree)
 {
-    if (root == NULL)
+    if (tree == NULL)
         return;
 
-    delete_binode_tree(root->child[0]);
-    delete_binode_tree(root->child[1]);
-    PyMem_Free(root);
+    delete_binode_tree(tree->child[0]);
+    delete_binode_tree(tree->child[1]);
+    PyMem_Free(tree);
 }
 
 static int
-insert_symbol(binode *root, bitarrayobject *self, PyObject *symbol)
+insert_symbol(binode *tree, bitarrayobject *ba, PyObject *symbol)
 {
-    binode *nd = root, *prev;
+    binode *nd = tree, *prev;
     Py_ssize_t i;
     int k;
 
-    for (i = 0; i < self->nbits; i++) {
-        k = GETBIT(self, i);
+    for (i = 0; i < ba->nbits; i++) {
+        k = GETBIT(ba, i);
         prev = nd;
         nd = nd->child[k];
+
+        /* we cannot have already a symbol when branching to the new leaf */
+        if (nd && nd->symbol)
+            goto ambiguity;
+
         if (!nd) {
             nd = new_binode();
             if (nd == NULL)
@@ -2189,43 +2286,52 @@ insert_symbol(binode *root, bitarrayobject *self, PyObject *symbol)
             prev->child[k] = nd;
         }
     }
+    /* the new leaf node cannot already have a symbol or children */
+    if (nd->symbol || nd->child[0] || nd->child[1])
+        goto ambiguity;
 
-    if (nd->symbol) {
-        PyErr_SetString(PyExc_ValueError, "prefix code ambiguous");
-        return -1;
-    }
     nd->symbol = symbol;
     return 0;
+
+ ambiguity:
+    PyErr_SetString(PyExc_ValueError, "prefix code ambiguous");
+    return -1;
 }
 
 static binode *
 make_tree(PyObject *codedict)
 {
-    binode *root;
+    binode *tree;
     PyObject *symbol, *array;
     Py_ssize_t pos = 0;
 
-    root = new_binode();
-    if (root == NULL)
+    tree = new_binode();
+    if (tree == NULL)
         return NULL;
 
     while (PyDict_Next(codedict, &pos, &symbol, &array)) {
-        if (insert_symbol(root, (bitarrayobject *) array, symbol) < 0) {
-            delete_binode_tree(root);
+        if (insert_symbol(tree, (bitarrayobject *) array, symbol) < 0) {
+            delete_binode_tree(tree);
             return NULL;
         }
     }
-    return root;
+    return tree;
 }
 
+/*
+  Traverse tree using the branches corresponding to the bitarray `ba`,
+  starting at *indexp.  Return the symbol at the leaf node, or NULL
+  when the end of the bitarray has been reached, or on error (in which
+  case the appropriate PyErr_SetString is set.
+*/
 static PyObject *
-tree_traverse(bitarrayobject *self, idx_t *indexp, binode *tree)
+traverse_tree(binode *tree, bitarrayobject *ba, idx_t *indexp)
 {
     binode *nd = tree;
     int k;
 
-    while (*indexp < self->nbits) {
-        k = GETBIT(self, *indexp);
+    while (*indexp < ba->nbits) {
+        k = GETBIT(ba, *indexp);
         (*indexp)++;
         nd = nd->child[k];
         if (nd == NULL) {
@@ -2250,6 +2356,9 @@ bitarray_decode(bitarrayobject *self, PyObject *codedict)
     Py_ssize_t i;
     int k;
 
+    if (check_codedict(codedict) < 0)
+        return NULL;
+
     tree = make_tree(codedict);
     if (tree == NULL || PyErr_Occurred())
         return NULL;
@@ -2260,6 +2369,7 @@ bitarray_decode(bitarrayobject *self, PyObject *codedict)
         delete_binode_tree(tree);
         return NULL;
     }
+    /* traverse tree (just like above) */
     for (i = 0; i < self->nbits; i++) {
         k = GETBIT(self, i);
         nd = nd->child[k];
@@ -2288,10 +2398,10 @@ error:
 }
 
 PyDoc_STRVAR(decode_doc,
-"_decode(codedict) -> list\n\
+"decode(code, /) -> list\n\
 \n\
-Given a code dictionary, decode the content of the bitarray and return\n\
-the list of symbols.");
+Given a prefix code (a dict mapping symbols to bitarrays),\n\
+decode the content of the bitarray and return it as a list of symbols.");
 
 /*********************** (Bitarray) Decode Iterator *********************/
 
@@ -2316,6 +2426,9 @@ bitarray_iterdecode(bitarrayobject *self, PyObject *codedict)
     decodeiterobject *it;  /* iterator to be returned */
     binode *tree;
 
+    if (check_codedict(codedict) < 0)
+        return NULL;
+
     tree = make_tree(codedict);
     if (tree == NULL || PyErr_Occurred())
         return NULL;
@@ -2334,10 +2447,11 @@ bitarray_iterdecode(bitarrayobject *self, PyObject *codedict)
 }
 
 PyDoc_STRVAR(iterdecode_doc,
-"_iterdecode(codedict) -> iterator\n\
+"iterdecode(code, /) -> iterator\n\
 \n\
-Given a code dictionary, decode the content of the bitarray and iterate\n\
-over the represented symbols.");
+Given a prefix code (a dict mapping symbols to bitarrays),\n\
+decode the content of the bitarray and return an iterator over\n\
+the symbols.");
 
 static PyObject *
 decodeiter_next(decodeiterobject *it)
@@ -2345,7 +2459,7 @@ decodeiter_next(decodeiterobject *it)
     PyObject *symbol;
 
     assert(DecodeIter_Check(it));
-    symbol = tree_traverse(it->bao, &(it->index), it->tree);
+    symbol = traverse_tree(it->tree, it->bao, &(it->index));
     if (symbol == NULL)  /* stop iteration OR error occured */
         return NULL;
     Py_INCREF(symbol);
@@ -2370,7 +2484,7 @@ decodeiter_traverse(decodeiterobject *it, visitproc visit, void *arg)
 
 static PyTypeObject DecodeIter_Type = {
 #ifdef IS_PY3K
-    PyVarObject_HEAD_INIT(&DecodeIter_Type, 0)
+    PyVarObject_HEAD_INIT(NULL, 0)
 #else
     PyObject_HEAD_INIT(NULL)
     0,                                        /* ob_size */
@@ -2449,7 +2563,7 @@ bitarray_itersearch(bitarrayobject *self, PyObject *x)
 }
 
 PyDoc_STRVAR(itersearch_doc,
-"itersearch(bitarray) -> iterator\n\
+"itersearch(bitarray, /) -> iterator\n\
 \n\
 Searches for the given a bitarray in self, and return an iterator over\n\
 the start positions where bitarray matches self.");
@@ -2485,7 +2599,7 @@ searchiter_traverse(searchiterobject *it, visitproc visit, void *arg)
 
 static PyTypeObject SearchIter_Type = {
 #ifdef IS_PY3K
-    PyVarObject_HEAD_INIT(&SearchIter_Type, 0)
+    PyVarObject_HEAD_INIT(NULL, 0)
 #else
     PyObject_HEAD_INIT(NULL)
     0,                                        /* ob_size */
@@ -2538,11 +2652,11 @@ bitarray_methods[] = {
      copy_doc},
     {"count",        (PyCFunction) bitarray_count,       METH_VARARGS,
      count_doc},
-    {"_decode",      (PyCFunction) bitarray_decode,      METH_O,
+    {"decode",       (PyCFunction) bitarray_decode,      METH_O,
      decode_doc},
-    {"_iterdecode",  (PyCFunction) bitarray_iterdecode,  METH_O,
+    {"iterdecode",   (PyCFunction) bitarray_iterdecode,  METH_O,
      iterdecode_doc},
-    {"_encode",      (PyCFunction) bitarray_encode,      METH_VARARGS,
+    {"encode",       (PyCFunction) bitarray_encode,      METH_VARARGS,
      encode_doc},
     {"endian",       (PyCFunction) bitarray_endian,      METH_NOARGS,
      endian_doc},
@@ -2633,7 +2747,7 @@ bitarray_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *initial = NULL;
     char *endian_str = NULL;
     int endian;
-    static char* kwlist[] = {"initial", "endian", NULL};
+    static char *kwlist[] = {"initial", "endian", NULL};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwds,
                         "|Os:bitarray", kwlist, &initial, &endian_str))
@@ -2684,16 +2798,16 @@ bitarray_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         return a;
     }
 
-    /* string */
-    if (PyString_Check(initial)) {
+    /* bytes */
+    if (PyBytes_Check(initial)) {
         Py_ssize_t strlen;
         char *str;
 
-        strlen = PyString_Size(initial);
+        strlen = PyBytes_Size(initial);
         if (strlen == 0)        /* empty string */
             return newbitarrayobject(type, 0, endian);
 
-        str = PyString_AsString(initial);
+        str = PyBytes_AsString(initial);
         if (0 <= str[0] && str[0] < 8) {
             /* when the first character is smaller than 8, it indicates the
                number of unused bits at the end, and rest of the bytes
@@ -2712,6 +2826,16 @@ bitarray_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         }
     }
 
+#define CHECK_TYPE(type)  \
+    if (Py ## type ## _Check(initial)) {                                  \
+        PyErr_SetString(PyExc_TypeError,                                  \
+                        "cannot create bitarray from " #type " object");  \
+        return NULL;                                                      \
+    }
+CHECK_TYPE(Float)
+CHECK_TYPE(Complex)
+#undef CHECK_TYPE
+
     /* leave remaining type dispatch to the extend method */
     a = newbitarrayobject(type, 0, endian);
     if (a == NULL)
@@ -2849,7 +2973,7 @@ bitarrayiter_traverse(bitarrayiterobject *it, visitproc visit, void *arg)
 
 static PyTypeObject BitarrayIter_Type = {
 #ifdef IS_PY3K
-    PyVarObject_HEAD_INIT(&BitarrayIter_Type, 0)
+    PyVarObject_HEAD_INIT(NULL, 0)
 #else
     PyObject_HEAD_INIT(NULL)
     0,                                        /* ob_size */
@@ -2887,7 +3011,7 @@ static PyTypeObject BitarrayIter_Type = {
 /********************* Bitarray Buffer Interface ************************/
 #ifdef WITH_BUFFER
 
-#if PY_MAJOR_VERSION == 2
+#if PY_MAJOR_VERSION == 2       /* old buffer protocol */
 static Py_ssize_t
 bitarray_buffer_getreadbuf(bitarrayobject *self,
                            Py_ssize_t index, const void **ptr)
@@ -2976,7 +3100,7 @@ static PyBufferProcs bitarray_as_buffer = {
 
 static PyTypeObject Bitarraytype = {
 #ifdef IS_PY3K
-    PyVarObject_HEAD_INIT(&Bitarraytype, 0)
+    PyVarObject_HEAD_INIT(NULL, 0)
 #else
     PyObject_HEAD_INIT(NULL)
     0,                                        /* ob_size */
@@ -2994,7 +3118,7 @@ static PyTypeObject Bitarraytype = {
     0,                                        /* tp_as_number*/
     0,                                        /* tp_as_sequence */
     0,                                        /* tp_as_mapping */
-    0,                                        /* tp_hash */
+    PyObject_HashNotImplemented,              /* tp_hash */
     0,                                        /* tp_call */
     0,                                        /* tp_str */
     PyObject_GenericGetAttr,                  /* tp_getattro */
@@ -3066,11 +3190,12 @@ bitdiff(PyObject *self, PyObject *args)
 }
 
 PyDoc_STRVAR(bitdiff_doc,
-"bitdiff(a, b) -> int\n\
+"bitdiff(a, b, /) -> int\n\
 \n\
 Return the difference between two bitarrays a and b.\n\
 This is function does the same as (a ^ b).count(), but is more memory\n\
-efficient, as no intermediate bitarray object gets created");
+efficient, as no intermediate bitarray object gets created.\n\
+Deprecated since version 1.2.0, use `bitarray.util.count_xor()` instead.");
 
 
 static PyObject *
@@ -3085,14 +3210,14 @@ bits2bytes(PyObject *self, PyObject *v)
     if (getIndex(v, &n) < 0)
         return NULL;
     if (n < 0) {
-        PyErr_SetString(PyExc_ValueError, "positive value expected");
+        PyErr_SetString(PyExc_ValueError, "non-negative integer expected");
         return NULL;
     }
     return PyLong_FromLongLong(BYTES(n));
 }
 
 PyDoc_STRVAR(bits2bytes_doc,
-"bits2bytes(n) -> int\n\
+"bits2bytes(n, /) -> int\n\
 \n\
 Return the number of bytes necessary to store n bits.");
 
@@ -3117,7 +3242,12 @@ tuple(sizeof(void *),\n\
       sizeof(idx_t),\n\
       PY_SSIZE_T_MAX)");
 
-
+/*
+   In retrospect, I wish I had never added any modules functions here.
+   These, and possibly many others should be part of a separate utility
+   module.  Anyway, at this point (2019) it is too late to remove them,
+   so I will just leave them here, but not any new ones.
+*/
 static PyMethodDef module_functions[] = {
     {"bitdiff",    (PyCFunction) bitdiff,    METH_VARARGS, bitdiff_doc   },
     {"bits2bytes", (PyCFunction) bits2bytes, METH_O,       bits2bytes_doc},
diff --git a/shell/ext-py/bitarray-1.2.1/bitarray/_util.c b/shell/ext-py/bitarray-1.2.1/bitarray/_util.c
new file mode 100644
index 0000000..5ed5920
--- /dev/null
+++ b/shell/ext-py/bitarray-1.2.1/bitarray/_util.c
@@ -0,0 +1,422 @@
+/*
+   Copyright (c) 2019, Ilan Schnell
+   bitarray is published under the PSF license.
+
+   This file contains the C implementation of some useful utility functions.
+
+   Author: Ilan Schnell
+*/
+
+#define PY_SSIZE_T_CLEAN
+#include "Python.h"
+
+#if PY_MAJOR_VERSION >= 3
+#define IS_PY3K
+#endif
+
+#ifdef STDC_HEADERS
+#include <stddef.h>
+#else  /* !STDC_HEADERS */
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>      /* For size_t */
+#endif /* HAVE_SYS_TYPES_H */
+#endif /* !STDC_HEADERS */
+
+
+typedef long long int idx_t;
+
+typedef struct {
+    PyObject_VAR_HEAD
+    char *ob_item;
+    Py_ssize_t allocated;       /* how many bytes allocated */
+    idx_t nbits;                /* length of bitarray, i.e. elements */
+    int endian;                 /* bit endianness of bitarray */
+    int ob_exports;             /* how many buffer exports */
+    PyObject *weakreflist;      /* list of weak references */
+} bitarrayobject;
+
+#define BITS(bytes)  ((idx_t) (bytes) << 3)
+
+#define BYTES(bits)  (((bits) == 0) ? 0 : (((bits) - 1) / 8 + 1))
+
+#define BITMASK(endian, i)  (((char) 1) << ((endian) ? (7 - (i)%8) : (i)%8))
+
+/* ------------ low level access to bits in bitarrayobject ------------- */
+
+#ifndef NDEBUG
+static int GETBIT(bitarrayobject *self, idx_t i) {
+    assert(0 <= i && i < self->nbits);
+    return ((self)->ob_item[(i) / 8] & BITMASK((self)->endian, i) ? 1 : 0);
+}
+#else
+#define GETBIT(self, i)  \
+    ((self)->ob_item[(i) / 8] & BITMASK((self)->endian, i) ? 1 : 0)
+#endif
+
+static void
+setbit(bitarrayobject *self, idx_t i, int bit)
+{
+    char *cp, mask;
+
+    assert(0 <= i && i < BITS(Py_SIZE(self)));
+    mask = BITMASK(self->endian, i);
+    cp = self->ob_item + i / 8;
+    if (bit)
+        *cp |= mask;
+    else
+        *cp &= ~mask;
+}
+
+/* set using the Python module function _set_babt() */
+static PyObject *bitarray_basetype = NULL;
+
+/* return 1 if obj is a bitarray, 0 otherwise */
+static int
+bitarray_Check(PyObject *obj)
+{
+    if (bitarray_basetype == NULL) /* fallback */
+        return PyObject_HasAttrString(obj, "endian");
+    return PyObject_IsInstance(obj, bitarray_basetype);
+}
+
+static void
+setunused(bitarrayobject *self)
+{
+    const idx_t n = BITS(Py_SIZE(self));
+    idx_t i;
+
+    for (i = self->nbits; i < n; i++)
+        setbit(self, i, 0);
+}
+
+static int bitcount_lookup[256] = {
+    0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+    4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
+};
+
+/* return the smallest index i for which a.count(1, 0, i) == n, or when
+   n exceeds the total count return -1  */
+static idx_t
+count_to_n(bitarrayobject *a, idx_t n)
+{
+    idx_t i = 0, j = 0, m;  /* i is the index, j the total count up to i */
+    Py_ssize_t block_start, block_stop, k;
+    unsigned char c;
+
+    if (n == 0)
+        return 0;
+
+#define BLOCK_BITS  8192
+    /* by counting big blocks we save comparisons */
+    while (i + BLOCK_BITS < a->nbits) {
+        m = 0;
+        assert(i % 8 == 0);
+        block_start = (Py_ssize_t) (i / 8);
+        block_stop = block_start + (BLOCK_BITS / 8);
+        for (k = block_start; k < block_stop; k++) {
+            assert(k < Py_SIZE(a));
+            c = a->ob_item[k];
+            m += bitcount_lookup[c];
+        }
+        if (j + m >= n)
+            break;
+        j += m;
+        i += BLOCK_BITS;
+    }
+#undef BLOCK_SIZE
+
+    while (i + 8 < a->nbits) {
+        k = (Py_ssize_t) (i / 8);
+        assert(k < Py_SIZE(a));
+        c = a->ob_item[k];
+        m = bitcount_lookup[c];
+        if (j + m >= n)
+            break;
+        j += m;
+        i += 8;
+    }
+
+    while (j < n && i < a->nbits ) {
+        j += GETBIT(a, i);
+        i++;
+    }
+    if (j < n)
+        return -1;
+
+    return i;
+}
+
+/* return index of last occurrence of vi, -1 when x is not in found. */
+static idx_t
+find_last(bitarrayobject *self, int vi)
+{
+    Py_ssize_t j;
+    idx_t i;
+    char c;
+
+    if (self->nbits == 0)
+        return -1;
+
+    /* search within top byte */
+    for (i = self->nbits - 1; i >= BITS(self->nbits / 8); i--)
+        if (GETBIT(self, i) == vi)
+            return i;
+
+    if (i < 0)  /* not found within top byte */
+        return -1;
+    assert((i + 1) % 8 == 0);
+
+    /* seraching for 1 means: break when byte is not 0x00
+       searching for 0 means: break when byte is not 0xff */
+    c = vi ? 0x00 : 0xff;
+
+    /* skip ahead by checking whole bytes */
+    for (j = BYTES(i) - 1; j >= 0; j--)
+        if (c ^ self->ob_item[j])
+            break;
+
+    if (j < 0)  /* not found within bytes */
+        return -1;
+
+    /* search within byte found */
+    for (i = BITS(j + 1) - 1; i >= BITS(j); i--)
+        if (GETBIT(self, i) == vi)
+            return i;
+
+    return -1;
+}
+
+/*************************** Module functions **********************/
+
+static PyObject *
+count_n(PyObject *self, PyObject *args)
+{
+    PyObject *a;
+    idx_t n, i;
+
+    if (!PyArg_ParseTuple(args, "OL:count_n", &a, &n))
+        return NULL;
+
+    if (!bitarray_Check(a)) {
+        PyErr_SetString(PyExc_TypeError, "bitarray object expected");
+        return NULL;
+    }
+    if (n < 0) {
+        PyErr_SetString(PyExc_ValueError, "non-negative integer expected");
+        return NULL;
+    }
+#define aa  ((bitarrayobject *) a)
+    if (n > aa->nbits)  {
+        PyErr_SetString(PyExc_ValueError, "n larger than bitarray size");
+        return NULL;
+    }
+    i = count_to_n(aa, n);        /* do actual work here */
+#undef aa
+    if (i < 0) {
+        PyErr_SetString(PyExc_ValueError, "n exceeds total count");
+        return NULL;
+    }
+    return PyLong_FromLongLong(i);
+}
+
+PyDoc_STRVAR(count_n_doc,
+"count_n(a, n, /) -> int\n\
+\n\
+Find the smallest index `i` for which `a[:i].count() == n`.\n\
+Raises `ValueError`, when n exceeds the `a.count()`.");
+
+
+static PyObject *
+r_index(PyObject *self, PyObject *args)
+{
+    PyObject *a, *x = Py_True;
+    idx_t i;
+    long vi;
+
+    if (!PyArg_ParseTuple(args, "O|O:rindex", &a, &x))
+        return NULL;
+
+    if (!bitarray_Check(a)) {
+        PyErr_SetString(PyExc_TypeError, "bitarray object expected");
+        return NULL;
+    }
+    vi = PyObject_IsTrue(x);
+    if (vi < 0)
+        return NULL;
+
+    i = find_last((bitarrayobject *) a, vi);
+    if (i < 0) {
+        PyErr_SetString(PyExc_ValueError, "index(x): x not in bitarray");
+        return NULL;
+    }
+    return PyLong_FromLongLong(i);
+}
+
+PyDoc_STRVAR(rindex_doc,
+"rindex(bitarray, value=True, /) -> int\n\
+\n\
+Return the rightmost index of `bool(value)` in bitarray.\n\
+Raises `ValueError` if the value is not present.");
+
+
+enum kernel_type {
+    KERN_cand,     /* count bitwise and -> int */
+    KERN_cor,      /* count bitwise or -> int */
+    KERN_cxor,     /* count bitwise xor -> int */
+    KERN_subset,   /* is subset -> bool */
+};
+
+static PyObject *
+two_bitarray_func(PyObject *args, enum kernel_type kern, char *format)
+{
+    PyObject *a, *b;
+    Py_ssize_t i;
+    idx_t res = 0;
+    unsigned char c;
+
+    if (!PyArg_ParseTuple(args, format, &a, &b))
+        return NULL;
+    if (!(bitarray_Check(a) && bitarray_Check(b))) {
+        PyErr_SetString(PyExc_TypeError, "bitarray object expected");
+        return NULL;
+    }
+#define aa  ((bitarrayobject *) a)
+#define bb  ((bitarrayobject *) b)
+    if (aa->nbits != bb->nbits) {
+        PyErr_SetString(PyExc_ValueError,
+                        "bitarrays of equal length expected");
+        return NULL;
+    }
+    if (aa->endian != bb->endian) {
+        PyErr_SetString(PyExc_ValueError,
+                        "bitarrays of equal endianness expected");
+        return NULL;
+    }
+    setunused(aa);
+    setunused(bb);
+    switch (kern) {
+    case KERN_cand:
+        for (i = 0; i < Py_SIZE(aa); i++) {
+            c = aa->ob_item[i] & bb->ob_item[i];
+            res += bitcount_lookup[c];
+        }
+        break;
+    case KERN_cor:
+        for (i = 0; i < Py_SIZE(aa); i++) {
+            c = aa->ob_item[i] | bb->ob_item[i];
+            res += bitcount_lookup[c];
+        }
+        break;
+    case KERN_cxor:
+        for (i = 0; i < Py_SIZE(aa); i++) {
+            c = aa->ob_item[i] ^ bb->ob_item[i];
+            res += bitcount_lookup[c];
+        }
+        break;
+    case KERN_subset:
+        for (i = 0; i < Py_SIZE(aa); i++)
+            if ((aa->ob_item[i] & bb->ob_item[i]) != aa->ob_item[i])
+                Py_RETURN_FALSE;
+        Py_RETURN_TRUE;
+    default:  /* should never happen */
+        return NULL;
+    }
+#undef aa
+#undef bb
+    return PyLong_FromLongLong(res);
+}
+
+#define COUNT_FUNC(oper, ochar)                                         \
+static PyObject *                                                       \
+count_ ## oper (bitarrayobject *self, PyObject *args)                   \
+{                                                                       \
+    return two_bitarray_func(args, KERN_c ## oper, "OO:count_" #oper);  \
+}                                                                       \
+PyDoc_STRVAR(count_ ## oper ## _doc,                                    \
+"count_" #oper "(a, b, /) -> int\n\
+\n\
+Returns `(a " ochar " b).count()`, but is more memory efficient,\n\
+as no intermediate bitarray object gets created.")
+
+COUNT_FUNC(and, "&");
+COUNT_FUNC(or,  "|");
+COUNT_FUNC(xor, "^");
+
+
+static PyObject *
+subset(PyObject *self, PyObject *args)
+{
+    return two_bitarray_func(args, KERN_subset, "OO:subset");
+}
+
+PyDoc_STRVAR(subset_doc,
+"subset(a, b, /) -> bool\n\
+\n\
+Return True if bitarray `a` is a subset of bitarray `b` (False otherwise).\n\
+`subset(a, b)` is equivalent to `(a & b).count() == a.count()` but is more\n\
+efficient since we can stop as soon as one mismatch is found, and no\n\
+intermediate bitarray object gets created.");
+
+
+/* set bitarray_basetype (babt) */
+static PyObject *
+set_babt(PyObject *self, PyObject *obj)
+{
+    bitarray_basetype = obj;
+    Py_RETURN_NONE;
+}
+
+static PyMethodDef module_functions[] = {
+    {"count_n",   (PyCFunction) count_n,   METH_VARARGS, count_n_doc},
+    {"rindex",    (PyCFunction) r_index,   METH_VARARGS, rindex_doc},
+    {"count_and", (PyCFunction) count_and, METH_VARARGS, count_and_doc},
+    {"count_or",  (PyCFunction) count_or,  METH_VARARGS, count_or_doc},
+    {"count_xor", (PyCFunction) count_xor, METH_VARARGS, count_xor_doc},
+    {"subset",    (PyCFunction) subset,    METH_VARARGS, subset_doc},
+    {"_set_babt", (PyCFunction) set_babt,  METH_O,       ""},
+    {NULL,        NULL}  /* sentinel */
+};
+
+/*********************** Install Module **************************/
+
+#ifdef IS_PY3K
+static PyModuleDef moduledef = {
+    PyModuleDef_HEAD_INIT, "_util", 0, -1, module_functions,
+};
+PyMODINIT_FUNC
+PyInit__util(void)
+#else
+PyMODINIT_FUNC
+init_util(void)
+#endif
+{
+    PyObject *m;
+
+#ifdef IS_PY3K
+    m = PyModule_Create(&moduledef);
+    if (m == NULL)
+        return NULL;
+#else
+    m = Py_InitModule3("_util", module_functions, 0);
+    if (m == NULL)
+        return;
+#endif
+
+#ifdef IS_PY3K
+    return m;
+#endif
+}
diff --git a/shell/ext-py/bitarray-0.9.0/bitarray/test_bitarray.py b/shell/ext-py/bitarray-1.2.1/bitarray/test_bitarray.py
similarity index 68%
rename from shell/ext-py/bitarray-0.9.0/bitarray/test_bitarray.py
rename to shell/ext-py/bitarray-1.2.1/bitarray/test_bitarray.py
index 3e66bff..93eb5ab 100644
--- a/shell/ext-py/bitarray-0.9.0/bitarray/test_bitarray.py
+++ b/shell/ext-py/bitarray-1.2.1/bitarray/test_bitarray.py
@@ -12,57 +12,65 @@ from random import randint
 
 is_py3k = bool(sys.version_info[0] == 3)
 
+# imports needed inside tests
+import copy
+import pickle
+import itertools
+
+try:
+    import shelve, hashlib
+except ImportError:
+    shelve = hashlib = None
+
 if is_py3k:
     from io import StringIO
+    unicode = str
 else:
     from cStringIO import StringIO
 
 
-from bitarray import bitarray, bitdiff, bits2bytes, __version__
+from bitarray import (bitarray, frozenbitarray,
+                      bitdiff, bits2bytes, __version__)
 
 
 tests = []
 
-if sys.version_info[:2] < (2, 6):
-    def next(x):
-        return x.next()
-
-
-def to_bytes(s):
-    if is_py3k:
-        return bytes(s.encode('latin1'))
-    elif sys.version_info[:2] >= (2, 6):
-        return bytes(s)
-    else:
-        return s
-
 
 class Util(object):
 
-    def randombitarrays(self):
-        for n in list(range(25)) + [randint(1000, 2000)]:
+    @staticmethod
+    def randombitarrays(start=1):
+        for n in list(range(start, 25)) + [randint(1000, 2000)]:
             a = bitarray(endian=['little', 'big'][randint(0, 1)])
             a.frombytes(os.urandom(bits2bytes(n)))
             del a[n:]
             yield a
 
-    def randomlists(self):
+    @staticmethod
+    def randomlists():
         for n in list(range(25)) + [randint(1000, 2000)]:
             yield [bool(randint(0, 1)) for d in range(n)]
 
-    def rndsliceidx(self, length):
+    @staticmethod
+    def rndsliceidx(length):
         if randint(0, 1):
             return None
         else:
-            return randint(-2 * length, 2 * length - 1)
+            return randint(-length-5, length+5)
 
-    def slicelen(self, r, length):
-        return getIndicesEx(r, length)[-1]
+    @staticmethod
+    def slicelen(s, length):
+        assert isinstance(s, slice)
+        start, stop, step = s.indices(length)
+        slicelength = (stop - start + (1 if step < 0 else -1)) // step + 1
+        if slicelength < 0:
+            slicelength = 0
+        return slicelength
 
     def check_obj(self, a):
         self.assertEqual(repr(type(a)), "<class 'bitarray.bitarray'>")
         unused = 8 * a.buffer_info()[1] - len(a)
-        self.assert_(0 <= unused < 8)
+        self.assertTrue(0 <= unused < 8)
         self.assertEqual(unused, a.buffer_info()[3])
 
     def assertEQUAL(self, a, b):
@@ -76,51 +84,9 @@ class Util(object):
             return
         self.assertRaises(StopIteration, it.next)
 
-
-def getIndicesEx(r, length):
-    if not isinstance(r, slice):
-        raise TypeError("slice object expected")
-    start = r.start
-    stop  = r.stop
-    step  = r.step
-    if r.step is None:
-        step = 1
-    else:
-        if step == 0:
-            raise ValueError("slice step cannot be zero")
-
-    if step < 0:
-        defstart = length - 1
-        defstop = -1
-    else:
-        defstart = 0
-        defstop = length
-
-    if r.start is None:
-        start = defstart
-    else:
-        if start < 0: start += length
-        if start < 0: start = [0, -1][step < 0]
-        if start >= length: start = [length, length - 1][step < 0]
-
-    if r.stop is None:
-        stop = defstop
-    else:
-        if stop < 0: stop += length
-        if stop < 0: stop = -1
-        if stop > length: stop = length
-
-    if (step < 0 and stop >= length) or (step > 0 and start >= stop):
-        slicelength = 0
-    elif step < 0:
-        slicelength = (stop - start + 1) / step + 1
-    else:
-        slicelength = (stop - start - 1) / step + 1
-
-    if slicelength < 0:
-        slicelength = 0
-
-    return start, stop, step, slicelength
+    if sys.version_info[:2] == (2, 6):
+        def assertIsInstance(self, o, t):
+            self.assertTrue(isinstance(o, t))
 
 # ---------------------------------------------------------------------------
 
@@ -150,6 +116,8 @@ class TestsModuleFunctions(unittest.TestCase, Util):
         for arg in ['foo', [], None, {}]:
             self.assertRaises(TypeError, bits2bytes, arg)
 
+        self.assertRaises(TypeError, bits2bytes, 187.0)
+        self.assertRaises(TypeError, bits2bytes, -4.0)
         self.assertRaises(TypeError, bits2bytes)
         self.assertRaises(TypeError, bits2bytes, 1, 2)
 
@@ -157,12 +125,11 @@ class TestsModuleFunctions(unittest.TestCase, Util):
         self.assertRaises(ValueError, bits2bytes, -924)
 
         self.assertEqual(bits2bytes(0), 0)
-        for n in range(1, 1000):
+        for n in range(1, 100):
             self.assertEqual(bits2bytes(n), (n - 1) // 8 + 1)
 
         for n, m in [(0, 0), (1, 1), (2, 1), (7, 1), (8, 1), (9, 2),
                      (10, 2), (15, 2), (16, 2), (64, 8), (65, 9),
-                     (0, 0), (1, 1), (65, 9), (2**29, 2**26),
                      (2**31, 2**28), (2**32, 2**29), (2**34, 2**31),
                      (2**34+793, 2**31+100), (2**35-8, 2**32-1),
                      (2**62, 2**59), (2**63-8, 2**60-1)]:
@@ -185,11 +152,13 @@ class CreateObjectTests(unittest.TestCase, Util):
         a = bitarray(endian='little')
         a.fromstring('A')
         self.assertEqual(a.endian(), 'little')
+        self.assertIsInstance(a.endian(), str)
         self.check_obj(a)
 
         b = bitarray(endian='big')
         b.fromstring('A')
         self.assertEqual(b.endian(), 'big')
+        self.assertIsInstance(a.endian(), str)
         self.check_obj(b)
 
         self.assertEqual(a.tostring(), b.tostring())
@@ -265,6 +234,13 @@ class CreateObjectTests(unittest.TestCase, Util):
             self.assertEqual(a, bitarray(lst))
             self.check_obj(a)
 
+    def test_iter3(self):
+        a = bitarray(itertools.repeat(False, 10))
+        self.assertEqual(a, bitarray(10 * '0'))
+        # Note that the through value of '0' is True: bool('0') -> True
+        a = bitarray(itertools.repeat('0', 10))
+        self.assertEqual(a, bitarray(10 * '1'))
+
     def test_01(self):
         a = bitarray('0010111')
         self.assertEqual(a.tolist(), [0, 0, 1, 0, 1, 1, 1])
@@ -280,20 +256,20 @@ class CreateObjectTests(unittest.TestCase, Util):
         self.assertRaises(ValueError, bitarray.__new__, bitarray, '01012100')
 
     def test_rawbytes(self): # this representation is used for pickling
-        for s, r in [('\x00', ''), ('\x07\xff', '1'), ('\x03\xff', '11111'),
-                     ('\x01\x87\xda', '10000111' '1101101')]:
-            self.assertEqual(bitarray(to_bytes(s), endian='big'),
+        for s, r in [(b'\x00', ''), (b'\x07\xff', '1'), (b'\x03\xff', '11111'),
+                     (b'\x01\x87\xda', '10000111' '1101101')]:
+            self.assertEqual(bitarray(s, endian='big'),
                              bitarray(r))
 
         for i in range(1, 8):
             self.assertRaises(ValueError, bitarray.__new__,
-                              bitarray, to_bytes(chr(i)))
+                              bitarray, bytes(bytearray([i])))
 
     def test_bitarray(self):
-        for n in range(50):
+        for n in range(10):
             a = bitarray(n)
             b = bitarray(a)
-            self.assert_(a is not b)
+            self.assertFalse(a is b)
             self.assertEQUAL(a, b)
 
         for end in ('little', 'big'):
@@ -330,19 +306,11 @@ tests.append(CreateObjectTests)
 
 class ToObjectsTests(unittest.TestCase, Util):
 
-    def test_int(self):
-        a = bitarray()
-        self.assertRaises(TypeError, int, a)
-        if not is_py3k:
-            self.assertRaises(TypeError, long, a)
-
-    def test_float(self):
+    def test_numeric(self):
         a = bitarray()
-        self.assertRaises(TypeError, float, a)
-
-    def test_complext(self):
-        a = bitarray()
-        self.assertRaises(TypeError, complex, a)
+        self.assertRaises(Exception, int, a)
+        self.assertRaises(Exception, float, a)
+        self.assertRaises(Exception, complex, a)
 
     def test_list(self):
         for a in self.randombitarrays():
@@ -357,7 +325,7 @@ tests.append(ToObjectsTests)
 
 # ---------------------------------------------------------------------------
 
-class MetaDataTests(unittest.TestCase):
+class MetaDataTests(unittest.TestCase, Util):
 
     def test_buffer_info1(self):
         a = bitarray('0000111100001', endian='little')
@@ -367,23 +335,23 @@ class MetaDataTests(unittest.TestCase):
         self.assertRaises(TypeError, a.buffer_info, 42)
 
         bi = a.buffer_info()
-        self.assert_(isinstance(bi, tuple))
+        self.assertIsInstance(bi, tuple)
         self.assertEqual(len(bi), 5)
 
-        self.assert_(isinstance(bi[0], int))
+        self.assertIsInstance(bi[0], int)
         if is_py3k:
-            self.assert_(isinstance(bi[1], int))
-        self.assert_(isinstance(bi[2], str))
-        self.assert_(isinstance(bi[3], int))
+            self.assertIsInstance(bi[1], int)
+        self.assertIsInstance(bi[2], str)
+        self.assertIsInstance(bi[3], int)
         if is_py3k:
-            self.assert_(isinstance(bi[4], int))
+            self.assertIsInstance(bi[4], int)
 
     def test_buffer_info2(self):
         for n in range(50):
             bi = bitarray(n).buffer_info()
             self.assertEqual(bi[1], bits2bytes(n))
             self.assertEqual(bi[3] + n, 8 * bi[1])
-            self.assert_(bi[4] >= bi[1])
+            self.assertTrue(bi[4] >= bi[1])
 
     def test_buffer_info3(self):
         a = bitarray(endian='little')
@@ -402,7 +370,7 @@ class MetaDataTests(unittest.TestCase):
 
 
     def test_length(self):
-        for n in range(1000):
+        for n in range(100):
             a = bitarray(n)
             self.assertEqual(len(a), n)
             self.assertEqual(a.length(), n)
@@ -421,7 +389,6 @@ class SliceTests(unittest.TestCase, Util):
         self.assertEqual(a[0], True)
         self.assertRaises(IndexError, a.__getitem__,  1)
         self.assertRaises(IndexError, a.__getitem__, -2)
-
         a.append(False)
         self.assertEqual(a[1], False)
         self.assertRaises(IndexError, a.__getitem__,  2)
@@ -438,7 +405,7 @@ class SliceTests(unittest.TestCase, Util):
     def test_getitem3(self):
         a = bitarray('0100000100001')
         self.assertEQUAL(a[:], a)
-        self.assert_(a[:] is not a)
+        self.assertFalse(a[:] is a)
         aa = a.tolist()
         self.assertEQUAL(a[11:2:-3], bitarray(aa[11:2:-3]))
         self.check_obj(a[:])
@@ -447,38 +414,33 @@ class SliceTests(unittest.TestCase, Util):
         self.assertRaises(TypeError, a.__getitem__, (1, 2))
 
     def test_getitem4(self):
-        for a in self.randombitarrays():
+        for a in self.randombitarrays(start=1):
             aa = a.tolist()
             la = len(a)
-            if la == 0: continue
             for dum in range(10):
-                step = self.rndsliceidx(la)
-                if step == 0: step = None
-                s = slice(self.rndsliceidx(la),
-                          self.rndsliceidx(la), step)
+                step = self.rndsliceidx(la) or None
+                s = slice(self.rndsliceidx(la), self.rndsliceidx(la), step)
                 self.assertEQUAL(a[s], bitarray(aa[s], endian=a.endian()))
 
     def test_setitem1(self):
         a = bitarray([False])
         a[0] = 1
-        self.assertEqual(a.tolist(), [True])
+        self.assertEqual(a, bitarray('1'))
 
         a = bitarray(2)
         a[0] = 0
         a[1] = 1
-        self.assertEqual(a.tolist(), [False, True])
+        self.assertEqual(a, bitarray('01'))
         a[-1] = 0
         a[-2] = 1
-        self.assertEqual(a.tolist(), [True, False])
+        self.assertEqual(a, bitarray('10'))
 
         self.assertRaises(IndexError, a.__setitem__,  2, True)
         self.assertRaises(IndexError, a.__setitem__, -3, False)
 
     def test_setitem2(self):
-        for a in self.randombitarrays():
+        for a in self.randombitarrays(start=1):
             la = len(a)
-            if la == 0:
-                continue
             i = randint(0, la - 1)
             aa = a.tolist()
             ida = id(a)
@@ -504,61 +466,96 @@ class SliceTests(unittest.TestCase, Util):
             self.assertEqual(a.tolist()[::-1], b.tolist())
 
     def test_setitem3(self):
-        a = bitarray(5 * [False])
+        a = bitarray('00000')
         a[0] = 1
         a[-2] = 1
         self.assertEqual(a, bitarray('10010'))
-        self.assertRaises(IndexError, a.__setitem__,  5, 'foo')
+        self.assertRaises(IndexError, a.__setitem__, 5, 'foo')
         self.assertRaises(IndexError, a.__setitem__, -6, 'bar')
 
     def test_setitem4(self):
-        for a in self.randombitarrays():
+        for a in self.randombitarrays(start=1):
             la = len(a)
-            if la == 0: continue
-            for dum in range(50):
-                step = self.rndsliceidx(la)
-                if step == 0: step = None
-                s = slice(self.rndsliceidx(la),
-                          self.rndsliceidx(la), step)
-                for b in self.randombitarrays():
-                    if len(b) == self.slicelen(s, len(a)) or step is None:
-                        c = bitarray(a)
-                        d = c
-                        c[s] = b
-                        self.assert_(c is d)
-                        self.check_obj(c)
-                        cc = a.tolist()
-                        cc[s] = b.tolist()
-                        self.assertEqual(c, bitarray(cc))
+            for dum in range(10):
+                step = self.rndsliceidx(la) or None
+                s = slice(self.rndsliceidx(la), self.rndsliceidx(la), step)
+                lb = randint(0, 10) if step is None else self.slicelen(s, la)
+                b = bitarray(lb)
+                c = bitarray(a)
+                c[s] = b
+                self.check_obj(c)
+                cc = a.tolist()
+                cc[s] = b.tolist()
+                self.assertEqual(c, bitarray(cc))
 
+    def test_setslice_to_bitarray(self):
+        a = bitarray('11111111' '1111')
+        a[2:6] = bitarray('0010')
+        self.assertEqual(a, bitarray('11001011' '1111'))
+        a.setall(0)
+        a[::2] = bitarray('111001')
+        self.assertEqual(a, bitarray('10101000' '0010'))
+        a.setall(0)
+        a[3:] = bitarray('111')
+        self.assertEqual(a, bitarray('000111'))
+        a = bitarray(12)
+        a.setall(0)
+        a[1:11:2] = bitarray('11101')
+        self.assertEqual(a, bitarray('01010100' '0100'))
+        a = bitarray(12)
+        a.setall(0)
+        a[:-6:-1] = bitarray('10111')
+        self.assertEqual(a, bitarray('00000001' '1101'))
+        a = bitarray('1111')
+        a[3:3] = bitarray('000')  # insert
+        self.assertEqual(a, bitarray('1110001'))
+        a[2:5] = bitarray()  # remove
+        self.assertEqual(a, bitarray('1101'))
+        a = bitarray('1111')
+        a[1:3] = bitarray('0000')
+        self.assertEqual(a, bitarray('100001'))
+        a[:] = bitarray('010') # replace all values
+        self.assertEqual(a, bitarray('010'))
 
     def test_setslice_to_bool(self):
         a = bitarray('11111111')
         a[::2] = False
         self.assertEqual(a, bitarray('01010101'))
-        a[4::] = True
+        a[4::] = True #                   ^^^^
         self.assertEqual(a, bitarray('01011111'))
-        a[-2:] = False
+        a[-2:] = False #                    ^^
         self.assertEqual(a, bitarray('01011100'))
-        a[:2:] = True
+        a[:2:] = True #               ^^
         self.assertEqual(a, bitarray('11011100'))
-        a[:] = True
+        a[:] = True #                 ^^^^^^^^
         self.assertEqual(a, bitarray('11111111'))
+        a[2:5] = False #                ^^^
+        self.assertEqual(a, bitarray('11000111'))
+        a[1::3] = False #              ^  ^  ^
+        self.assertEqual(a, bitarray('10000110'))
+        a[1:6:2] = True #              ^ ^ ^
+        self.assertEqual(a, bitarray('11010110'))
 
     def test_setslice_to_int(self):
         a = bitarray('11111111')
-        a[::2] = 0
+        a[::2] = 0 #  ^ ^ ^ ^
         self.assertEqual(a, bitarray('01010101'))
-        a[4::] = 1
+        a[4::] = 1 #                      ^^^^
         self.assertEqual(a, bitarray('01011111'))
         a.__setitem__(slice(-2, None, None), 0)
         self.assertEqual(a, bitarray('01011100'))
+        self.assertRaises(ValueError, a.__setitem__, slice(None, None, 2), 3)
+        self.assertRaises(ValueError, a.__setitem__, slice(None, 2, None), -1)
 
-        self.assertRaises(ValueError, a.__setitem__,
-                          slice(None, None, 2), 3)
-        self.assertRaises(ValueError, a.__setitem__,
-                          slice(None, 2, None), -1)
-
+    def test_sieve(self): # Sieve of Eratosthenes
+        a = bitarray(50)
+        a.setall(1)
+        for i in range(2, 8):
+            if a[i]:
+                a[i*i::i] = 0
+        primes = [i for i in range(2, 50) if a[i]]
+        self.assertEqual(primes, [2, 3, 5, 7, 11, 13, 17, 19,
+                                  23, 29, 31, 37, 41, 43, 47])
 
     def test_delitem1(self):
         a = bitarray('100110')
@@ -569,20 +566,25 @@ class SliceTests(unittest.TestCase, Util):
         self.assertEqual(a, bitarray('100'))
         self.assertRaises(IndexError, a.__delitem__,  3)
         self.assertRaises(IndexError, a.__delitem__, -4)
+        a = bitarray('10101100' '10110')
+        del a[3:9] #     ^^^^^   ^
+        self.assertEqual(a, bitarray('1010110'))
+        del a[::3] #                  ^  ^  ^
+        self.assertEqual(a, bitarray('0111'))
+        a = bitarray('10101100' '1011011')
+        del a[:-9:-2] #          ^ ^ ^ ^
+        self.assertEqual(a, bitarray('10101100' '011'))
 
     def test_delitem2(self):
-        for a in self.randombitarrays():
+        for a in self.randombitarrays(start=1):
             la = len(a)
-            if la == 0: continue
-            for dum in range(50):
-                step = self.rndsliceidx(la)
-                if step == 0: step = None
-                s = slice(self.rndsliceidx(la),
-                          self.rndsliceidx(la), step)
+            for dum in range(10):
+                step = self.rndsliceidx(la) or None
+                s = slice(self.rndsliceidx(la), self.rndsliceidx(la), step)
                 c = bitarray(a)
                 d = c
                 del c[s]
-                self.assert_(c is d)
+                self.assertTrue(c is d)
                 self.check_obj(c)
                 cc = a.tolist()
                 del cc[s]
@@ -597,7 +599,7 @@ class MiscTests(unittest.TestCase, Util):
 
     def test_instancecheck(self):
         a = bitarray('011')
-        self.assertTrue(isinstance(a, bitarray))
+        self.assertIsInstance(a, bitarray)
         self.assertFalse(isinstance(a, str))
 
     def test_booleanness(self):
@@ -605,6 +607,15 @@ class MiscTests(unittest.TestCase, Util):
         self.assertEqual(bool(bitarray('0')), True)
         self.assertEqual(bool(bitarray('1')), True)
 
+    def test_to01(self):
+        a = bitarray()
+        self.assertEqual(a.to01(), '')
+        self.assertIsInstance(a.to01(), str)
+
+        a = bitarray('101')
+        self.assertEqual(a.to01(), '101')
+        self.assertIsInstance(a.to01(), str)
+
     def test_iterate(self):
         for lst in self.randomlists():
             acc = []
@@ -635,7 +646,6 @@ class MiscTests(unittest.TestCase, Util):
     def test_compare(self):
         for a in self.randombitarrays():
             aa = a.tolist()
-
             for b in self.randombitarrays():
                 bb = b.tolist()
                 self.assertEqual(a == b, aa == bb)
@@ -657,28 +667,26 @@ class MiscTests(unittest.TestCase, Util):
             def __getitem__(self, i):
                 return bitarray.__getitem__(self, i - self.offset)
 
-        for a in self.randombitarrays():
-            if len(a) == 0:
-                continue
+        for a in self.randombitarrays(start=1):
             b = ExaggeratingBitarray(a, 1234)
             for i in range(len(a)):
                 self.assertEqual(a[i], b[i+1234])
 
     def test_endianness1(self):
         a = bitarray(endian='little')
-        a.frombytes(to_bytes('\x01'))
+        a.frombytes(b'\x01')
         self.assertEqual(a.to01(), '10000000')
 
         b = bitarray(endian='little')
-        b.frombytes(to_bytes('\x80'))
+        b.frombytes(b'\x80')
         self.assertEqual(b.to01(), '00000001')
 
         c = bitarray(endian='big')
-        c.frombytes(to_bytes('\x80'))
+        c.frombytes(b'\x80')
         self.assertEqual(c.to01(), '10000000')
 
         d = bitarray(endian='big')
-        d.frombytes(to_bytes('\x01'))
+        d.frombytes(b'\x01')
         self.assertEqual(d.to01(), '00000001')
 
         self.assertEqual(a, c)
@@ -688,29 +696,29 @@ class MiscTests(unittest.TestCase, Util):
         a = bitarray(8, endian='little')
         a.setall(False)
         a[0] = True
-        self.assertEqual(a.tobytes(), to_bytes('\x01'))
+        self.assertEqual(a.tobytes(), b'\x01')
         a[1] = True
-        self.assertEqual(a.tobytes(), to_bytes('\x03'))
-        a.frombytes(to_bytes(' '))
-        self.assertEqual(a.tobytes(), to_bytes('\x03 '))
+        self.assertEqual(a.tobytes(), b'\x03')
+        a.frombytes(b' ')
+        self.assertEqual(a.tobytes(), b'\x03 ')
         self.assertEqual(a.to01(), '1100000000000100')
 
     def test_endianness3(self):
         a = bitarray(8, endian='big')
         a.setall(False)
         a[7] = True
-        self.assertEqual(a.tobytes(), to_bytes('\x01'))
+        self.assertEqual(a.tobytes(), b'\x01')
         a[6] = True
-        self.assertEqual(a.tobytes(), to_bytes('\x03'))
-        a.frombytes(to_bytes(' '))
-        self.assertEqual(a.tobytes(), to_bytes('\x03 '))
+        self.assertEqual(a.tobytes(), b'\x03')
+        a.frombytes(b' ')
+        self.assertEqual(a.tobytes(), b'\x03 ')
         self.assertEqual(a.to01(), '0000001100100000')
 
     def test_endianness4(self):
         a = bitarray('00100000', endian='big')
-        self.assertEqual(a.tobytes(), to_bytes(' '))
+        self.assertEqual(a.tobytes(), b' ')
         b = bitarray('00000100', endian='little')
-        self.assertEqual(b.tobytes(), to_bytes(' '))
+        self.assertEqual(b.tobytes(), b' ')
         self.assertNotEqual(a, b)
 
     def test_endianness5(self):
@@ -720,27 +728,14 @@ class MiscTests(unittest.TestCase, Util):
         self.assertEqual(a.tobytes(), b.tobytes())
 
     def test_pickle(self):
-        from pickle import loads, dumps
-        for v in range(3):
-            for a in self.randombitarrays():
-                b = loads(dumps(a, v))
-                self.assert_(b is not a)
-                self.assertEQUAL(a, b)
-
-    def test_cPickle(self):
-        if is_py3k:
-            return
         for v in range(3):
-            from cPickle import loads, dumps
             for a in self.randombitarrays():
-                b = loads(dumps(a, v))
-                self.assert_(b is not a)
+                b = pickle.loads(pickle.dumps(a, v))
+                self.assertFalse(b is a)
                 self.assertEQUAL(a, b)
 
     def test_overflow(self):
-        from platform import architecture
-
-        if architecture()[0] == '64bit':
+        if tuple.__itemsize__ == 8:
             return
 
         self.assertRaises(OverflowError, bitarray.__new__,
@@ -749,6 +744,35 @@ class MiscTests(unittest.TestCase, Util):
         a = bitarray(10 ** 6)
         self.assertRaises(OverflowError, a.__imul__, 17180)
 
+    def test_unicode1(self):
+        a = bitarray(unicode())
+        self.assertEqual(a, bitarray())
+
+        a = bitarray(unicode('111001'))
+        self.assertEqual(a, bitarray('111001'))
+
+        for a in self.randombitarrays():
+            b = bitarray(unicode(a.to01()))
+            self.assertEqual(a, b)
+
+    def test_unicode2(self):
+        a = bitarray()
+        a.extend(unicode())
+        self.assertEqual(a, bitarray())
+
+        a = bitarray()
+        a.extend(unicode('001011'))
+        self.assertEqual(a, bitarray('001011'))
+
+        for a in self.randombitarrays():
+            b = bitarray()
+            b.extend(unicode(a.to01()))
+            self.assertEqual(a, b)
+
+    def test_unhashable(self):
+        a = bitarray()
+        self.assertRaises(TypeError, hash, a)
+        self.assertRaises(TypeError, dict, [(a, 'foo')])
 
 tests.append(MiscTests)
 
@@ -759,54 +783,52 @@ class SpecialMethodTests(unittest.TestCase, Util):
     def test_all(self):
         a = bitarray()
         self.assertTrue(a.all())
-
-        if sys.version_info[:2] < (2, 5):
-            return
+        for s, r in ('0', False), ('1', True), ('01', False):
+            self.assertEqual(bitarray(s).all(), r)
 
         for a in self.randombitarrays():
-            self.assertEqual(all(a),          a.all())
+            self.assertEqual(all(a), a.all())
             self.assertEqual(all(a.tolist()), a.all())
 
-
     def test_any(self):
         a = bitarray()
         self.assertFalse(a.any())
-
-        if sys.version_info[:2] < (2, 5):
-            return
+        for s, r in ('0', False), ('1', True), ('01', True):
+            self.assertEqual(bitarray(s).any(), r)
 
         for a in self.randombitarrays():
-            self.assertEqual(any(a),          a.any())
+            self.assertEqual(any(a), a.any())
             self.assertEqual(any(a.tolist()), a.any())
 
 
     def test_repr(self):
-        a = bitarray()
-        self.assertEqual(repr(a), "bitarray()")
+        r = repr(bitarray())
+        self.assertEqual(r, "bitarray()")
+        self.assertIsInstance(r, str)
 
-        a = bitarray('10111')
-        self.assertEqual(repr(a), "bitarray('10111')")
+        r = repr(bitarray('10111'))
+        self.assertEqual(r, "bitarray('10111')")
+        self.assertIsInstance(r, str)
 
         for a in self.randombitarrays():
             b = eval(repr(a))
-            self.assert_(b is not a)
+            self.assertFalse(b is a)
             self.assertEqual(a, b)
             self.check_obj(b)
 
 
     def test_copy(self):
-        import copy
         for a in self.randombitarrays():
             b = a.copy()
-            self.assert_(b is not a)
+            self.assertFalse(b is a)
             self.assertEQUAL(a, b)
 
             b = copy.copy(a)
-            self.assert_(b is not a)
+            self.assertFalse(b is a)
             self.assertEQUAL(a, b)
 
             b = copy.deepcopy(a)
-            self.assert_(b is not a)
+            self.assertFalse(b is a)
             self.assertEQUAL(a, b)
 
 
@@ -883,7 +905,7 @@ class NumberTests(unittest.TestCase, Util):
                 d = c
                 d += b
                 self.assertEqual(d, a + b)
-                self.assert_(c is d)
+                self.assertTrue(c is d)
                 self.assertEQUAL(c, d)
                 self.assertEqual(d.endian(), a.endian())
                 self.check_obj(d)
@@ -978,12 +1000,19 @@ class BitwiseTests(unittest.TestCase, Util):
     def test_or(self):
         a = bitarray('11001')
         b = bitarray('10011')
+        aa = a.copy()
+        bb = b.copy()
         self.assertEQUAL(a | b, bitarray('11011'))
+        self.assertEQUAL(a, aa)
+        self.assertEQUAL(b, bb)
 
     def test_ior(self):
-        a =  bitarray('110010110')
-        a |= bitarray('100110011')
+        a = bitarray('110010110')
+        b = bitarray('100110011')
+        bb = b.copy()
+        a |= b
         self.assertEQUAL(a, bitarray('110110111'))
+        self.assertEQUAL(b, bb)
 
     def test_xor(self):
         a = bitarray('11001')
@@ -1008,24 +1037,17 @@ class BitwiseTests(unittest.TestCase, Util):
         b = ~a
         self.assertEQUAL(b, bitarray('00100'))
         self.assertEQUAL(a, bitarray('11011'))
-        self.assert_(a is not b)
+        self.assertFalse(a is b)
 
         for a in self.randombitarrays():
-            aa = a.tolist()
             b = bitarray(a)
             b.invert()
             for i in range(len(a)):
-                self.assertEqual(b[i], not aa[i])
+                self.assertEqual(b[i], not a[i])
             self.check_obj(b)
-
             c = ~a
-            self.assert_(c is not a)
-            self.assertEQUAL(a, bitarray(aa, endian=a.endian()))
-
-            for i in range(len(a)):
-                self.assertEqual(c[i], not aa[i])
-
-            self.check_obj(b)
+            self.assertEQUAL(c, b)
+            self.check_obj(c)
 
 
 tests.append(BitwiseTests)
@@ -1036,21 +1058,21 @@ class SequenceTests(unittest.TestCase, Util):
 
     def test_contains1(self):
         a = bitarray()
-        self.assert_(False not in a)
-        self.assert_(True not in a)
-        self.assert_(bitarray() in a)
+        self.assertFalse(False in a)
+        self.assertFalse(True in a)
+        self.assertTrue(bitarray() in a)
         a.append(True)
-        self.assert_(True in a)
-        self.assert_(False not in a)
+        self.assertTrue(True in a)
+        self.assertFalse(False in a)
         a = bitarray([False])
-        self.assert_(False in a)
-        self.assert_(True not in a)
+        self.assertTrue(False in a)
+        self.assertFalse(True in a)
         a.append(True)
-        self.assert_(0 in a)
-        self.assert_(1 in a)
+        self.assertTrue(0 in a)
+        self.assertTrue(1 in a)
         if not is_py3k:
-            self.assert_(long(0) in a)
-            self.assert_(long(1) in a)
+            self.assertTrue(long(0) in a)
+            self.assertTrue(long(1) in a)
 
     def test_contains2(self):
         a = bitarray()
@@ -1067,20 +1089,20 @@ class SequenceTests(unittest.TestCase, Util):
             self.assertRaises(ValueError, a.__contains__, long(2))
 
     def test_contains3(self):
-        for n in range(2, 100):
+        for n in range(2, 50):
             a = bitarray(n)
             a.setall(0)
-            self.assert_(False in a)
-            self.assert_(True not in a)
+            self.assertTrue(False in a)
+            self.assertFalse(True in a)
             a[randint(0, n - 1)] = 1
-            self.assert_(True in a)
-            self.assert_(False in a)
+            self.assertTrue(True in a)
+            self.assertTrue(False in a)
             a.setall(1)
-            self.assert_(True in a)
-            self.assert_(False not in a)
+            self.assertTrue(True in a)
+            self.assertFalse(False in a)
             a[randint(0, n - 1)] = 0
-            self.assert_(True in a)
-            self.assert_(False in a)
+            self.assertTrue(True in a)
+            self.assertTrue(False in a)
 
     def test_contains4(self):
         a = bitarray('011010000001')
@@ -1189,10 +1211,6 @@ class ExtendTests(unittest.TestCase, Util):
                 self.check_obj(c)
 
     def test_iterator2(self):
-        try:
-            import itertools
-        except ImportError:
-            return
         a = bitarray()
         a.extend(itertools.repeat(True, 23))
         self.assertEqual(a, bitarray(23 * '1'))
@@ -1242,12 +1260,19 @@ class MethodTests(unittest.TestCase, Util):
         a.append(False)
         a.append(False)
         self.assertEQUAL(a, bitarray('100'))
+        a.append(0)
+        a.append(1)
+        a.append(2)
+        a.append(None)
+        a.append('')
+        a.append('a')
+        self.assertEQUAL(a, bitarray('100011001'))
 
         for a in self.randombitarrays():
             aa = a.tolist()
             b = a
             b.append(1)
-            self.assert_(a is b)
+            self.assertTrue(a is b)
             self.check_obj(b)
             self.assertEQUAL(b, bitarray(aa+[1], endian=a.endian()))
             b.append('')
@@ -1258,7 +1283,7 @@ class MethodTests(unittest.TestCase, Util):
         a = bitarray()
         b = a
         a.insert(0, True)
-        self.assert_(a is b)
+        self.assertTrue(a is b)
         self.assertEqual(a, bitarray('1'))
         self.assertRaises(TypeError, a.insert)
         self.assertRaises(TypeError, a.insert, None)
@@ -1274,15 +1299,26 @@ class MethodTests(unittest.TestCase, Util):
                 self.check_obj(a)
 
 
-    def test_index(self):
+    def test_index1(self):
         a = bitarray()
         for i in (True, False, 1, 0):
             self.assertRaises(ValueError, a.index, i)
 
         a = bitarray(100 * [False])
         self.assertRaises(ValueError, a.index, True)
+        self.assertRaises(TypeError, a.index)
+        self.assertRaises(TypeError, a.index, 1, 'a')
+        self.assertRaises(TypeError, a.index, 1, 0, 'a')
+        self.assertRaises(TypeError, a.index, 1, 0, 100, 1)
         a[20] = a[27] = 1
         self.assertEqual(a.index(42), 20)
+        self.assertEqual(a.index(1, 21), 27)
+        self.assertEqual(a.index(1, 27), 27)
+        self.assertEqual(a.index(1, -73), 27)
+        self.assertRaises(ValueError, a.index, 1, 5, 17)
+        self.assertRaises(ValueError, a.index, 1, 5, -83)
+        self.assertRaises(ValueError, a.index, 1, 21, 27)
+        self.assertRaises(ValueError, a.index, 1, 28)
         self.assertEqual(a.index(0), 0)
 
         a = bitarray(200 * [True])
@@ -1291,6 +1327,7 @@ class MethodTests(unittest.TestCase, Util):
         self.assertEqual(a.index(False), 173)
         self.assertEqual(a.index(True), 0)
 
+    def test_index2(self):
         for n in range(50):
             for m in range(n):
                 a = bitarray(n)
@@ -1304,7 +1341,7 @@ class MethodTests(unittest.TestCase, Util):
                 a[m] = 0
                 self.assertEqual(a.index(0), m)
 
-    def test_index2(self):
+    def test_index3(self):
         a = bitarray('00001000' '00000000' '0010000')
         self.assertEqual(a.index(1), 4)
         self.assertEqual(a.index(1, 1), 4)
@@ -1313,7 +1350,16 @@ class MethodTests(unittest.TestCase, Util):
         self.assertRaises(ValueError, a.index, 1, 5, 18)
         self.assertRaises(ValueError, a.index, 1, 19)
 
-    def test_index3(self):
+    def test_index4(self):
+        a = bitarray('11110111' '11111111' '1101111')
+        self.assertEqual(a.index(0), 4)
+        self.assertEqual(a.index(0, 1), 4)
+        self.assertEqual(a.index(1, 4), 5)
+        self.assertEqual(a.index(0, 5), 18)
+        self.assertRaises(ValueError, a.index, 0, 5, 18)
+        self.assertRaises(ValueError, a.index, 0, 19)
+
+    def test_index5(self):
         a = bitarray(2000)
         a.setall(0)
         for _ in range(3):
@@ -1332,25 +1378,80 @@ class MethodTests(unittest.TestCase, Util):
                 res2 = None
             self.assertEqual(res1, res2)
 
-
-    def test_count(self):
+    def test_index6(self):
+        for n in range(1, 50):
+            a = bitarray(n)
+            i = randint(0, 1)
+            a.setall(i)
+            for unused in range(randint(1, 4)):
+                a[randint(0, n-1)] = 1-i
+            aa = a.tolist()
+            for unused in range(100):
+                start = randint(-50, n+50)
+                stop = randint(-50, n+50)
+                try:
+                    res1 = a.index(1-i, start, stop)
+                except ValueError:
+                    res1 = None
+                try:
+                    res2 = aa.index(1-i, start, stop)
+                except ValueError:
+                    res2 = None
+                self.assertEqual(res1, res2)
+
+
+    def test_count1(self):
         a = bitarray('10011')
         self.assertEqual(a.count(), 3)
         self.assertEqual(a.count(True), 3)
         self.assertEqual(a.count(False), 2)
         self.assertEqual(a.count(1), 3)
         self.assertEqual(a.count(0), 2)
-        self.assertRaises(TypeError, a.count, 'A')
+        self.assertEqual(a.count(None), 2)
+        self.assertEqual(a.count(''), 2)
+        self.assertEqual(a.count('A'), 3)
+        self.assertRaises(TypeError, a.count, 0, 'A')
+        self.assertRaises(TypeError, a.count, 0, 0, 'A')
 
+    def test_count2(self):
         for i in range(0, 256):
             a = bitarray()
-            a.frombytes(to_bytes(chr(i)))
+            a.frombytes(bytes(bytearray([i])))
             self.assertEqual(a.count(), a.to01().count('1'))
 
+    def test_count3(self):
+        for a in self.randombitarrays():
+            s = a.to01()
+            self.assertEqual(a.count(1), s.count('1'))
+            self.assertEqual(a.count(0), s.count('0'))
+
+    def test_count4(self):
+        N = 37
+        a = bitarray(N)
+        a.setall(1)
+        for i in range(N):
+            for j in range(i, N):
+                self.assertEqual(a.count(1, i, j), j - i)
+
+    def test_count5(self):
+        for endian in 'big', 'little':
+            a = bitarray('01001100' '01110011' '01', endian)
+            self.assertEqual(a.count(), 9)
+            self.assertEqual(a.count(0, 12), 3)
+            self.assertEqual(a.count(1, -5), 3)
+            self.assertEqual(a.count(1, 2, 17), 7)
+            self.assertEqual(a.count(1, 6, 11), 2)
+            self.assertEqual(a.count(0, 7, -3), 4)
+            self.assertEqual(a.count(1, 1, -1), 8)
+            self.assertEqual(a.count(1, 17, 14), 0)
+
+    def test_count6(self):
         for a in self.randombitarrays():
-            self.assertEqual(a.count(), a.count(1))
-            self.assertEqual(a.count(1), a.to01().count('1'))
-            self.assertEqual(a.count(0), a.to01().count('0'))
+            s = a.to01()
+            i = randint(-3, len(a)+1)
+            j = randint(-3, len(a)+1)
+            self.assertEqual(a.count(1, i, j), s[i:j].count('1'))
+            self.assertEqual(a.count(0, i, j), s[i:j].count('0'))
 
 
     def test_search(self):
@@ -1406,6 +1507,21 @@ class MethodTests(unittest.TestCase, Util):
             self.assertEqual(list(a.itersearch(b)), res)
             self.assertEqual([p for p in a.itersearch(b)], res)
 
+    def test_search4(self):
+        for a in self.randombitarrays():
+            aa = a.to01()
+            for sub in '0', '1', '01', '01', '11', '101', '1111111':
+                sr = a.search(bitarray(sub), 1)
+                try:
+                    p = sr[0]
+                except IndexError:
+                    p = -1
+                self.assertEqual(p, aa.find(sub))
+
+    def test_search_type(self):
+        a = bitarray('10011')
+        it = a.itersearch(bitarray('1'))
+        self.assertIsInstance(type(it), type)
 
     def test_fill(self):
         a = bitarray('')
@@ -1422,21 +1538,21 @@ class MethodTests(unittest.TestCase, Util):
             aa = a.tolist()
             la = len(a)
             b = a
-            self.assert_(0 <= b.fill() < 8)
+            self.assertTrue(0 <= b.fill() < 8)
             self.assertEqual(b.endian(), a.endian())
             bb = b.tolist()
             lb = len(b)
-            self.assert_(a is b)
+            self.assertTrue(a is b)
             self.check_obj(b)
             if la % 8 == 0:
                 self.assertEqual(bb, aa)
                 self.assertEqual(lb, la)
             else:
-                self.assert_(lb % 8 == 0)
+                self.assertTrue(lb % 8 == 0)
                 self.assertNotEqual(bb, aa)
                 self.assertEqual(bb[:la], aa)
                 self.assertEqual(b[la:], (lb-la)*bitarray('0'))
-                self.assert_(0 < lb-la < 8)
+                self.assertTrue(0 < lb-la < 8)
 
 
     def test_sort(self):
@@ -1456,11 +1572,20 @@ class MethodTests(unittest.TestCase, Util):
 
         self.assertRaises(TypeError, a.sort, 'A')
 
+        N = 100000
+        a = bitarray(randint(N, N + 100))
+        for dum in range(100):
+            a[randint(0, N - 1)] = randint(0, 1)
+        b = a.tolist()
+        a.sort()
+        self.assertEqual(a, bitarray(sorted(b)))
+
         for a in self.randombitarrays():
+            b = a.tolist()
             ida = id(a)
             rev = randint(0, 1)
             a.sort(rev)
-            self.assertEqual(a, bitarray(sorted(a.tolist(), reverse=rev)))
+            self.assertEqual(a, bitarray(sorted(b, reverse=rev)))
             self.assertEqual(id(a), ida)
 
 
@@ -1480,10 +1605,12 @@ class MethodTests(unittest.TestCase, Util):
 
         for a in self.randombitarrays():
             aa = a.tolist()
+            b = bitarray(a)
             ida = id(a)
             a.reverse()
             self.assertEqual(ida, id(a))
             self.assertEQUAL(a, bitarray(aa[::-1], endian=a.endian()))
+            self.assertEqual(a, b[::-1])
 
 
     def test_tolist(self):
@@ -1519,7 +1646,7 @@ class MethodTests(unittest.TestCase, Util):
         a = bitarray('0010011')
         b = a
         b.remove('1')
-        self.assert_(b is a)
+        self.assertTrue(b is a)
         self.assertEQUAL(b, bitarray('000011'))
 
 
@@ -1547,9 +1674,7 @@ class MethodTests(unittest.TestCase, Util):
             self.check_obj(a)
             self.assertEqual(a.endian(), enda)
 
-        for a in self.randombitarrays():
-            if len(a) == 0:
-                continue
+        for a in self.randombitarrays(start=1):
             n = randint(-len(a), len(a)-1)
             aa = a.tolist()
             self.assertEqual(a.pop(n), aa[n])
@@ -1568,7 +1693,7 @@ class MethodTests(unittest.TestCase, Util):
             b = a
             b.setall(val)
             self.assertEqual(b, bitarray(len(b) * [val]))
-            self.assert_(a is b)
+            self.assertTrue(a is b)
             self.check_obj(b)
 
 
@@ -1587,12 +1712,12 @@ class MethodTests(unittest.TestCase, Util):
 
         for i in range(256):
             a = bitarray()
-            a.frombytes(to_bytes(chr(i)))
+            a.frombytes(bytes(bytearray([i])))
             aa = a.tolist()
             b = a
             b.bytereverse()
             self.assertEqual(b, bitarray(aa[::-1]))
-            self.assert_(a is b)
+            self.assertTrue(a is b)
             self.check_obj(b)
 
 
@@ -1604,102 +1729,99 @@ class StringTests(unittest.TestCase, Util):
 
     def randombytes(self):
         for n in range(1, 20):
-            yield to_bytes(''.join(chr(randint(0, 255))
-                                   for x in range(n)))
+            yield os.urandom(n)
 
     def test_frombytes(self):
         a = bitarray(endian='big')
-        a.frombytes(to_bytes('A'))
+        a.frombytes(b'A')
         self.assertEqual(a, bitarray('01000001'))
 
         b = a
-        b.frombytes(to_bytes('BC'))
+        b.frombytes(b'BC')
         self.assertEQUAL(b, bitarray('01000001' '01000010' '01000011',
                                      endian='big'))
-        self.assert_(b is a)
+        self.assertTrue(b is a)
 
         for b in self.randombitarrays():
-            c = b.__copy__()
-            b.frombytes(to_bytes(''))
+            c = b.copy()
+            b.frombytes(b'')
             self.assertEQUAL(b, c)
 
         for b in self.randombitarrays():
             for s in self.randombytes():
                 a = bitarray(endian=b.endian())
                 a.frombytes(s)
-                c = b.__copy__()
+                c = b.copy()
                 b.frombytes(s)
                 self.assertEQUAL(b[-len(a):], a)
                 self.assertEQUAL(b[:-len(a)], c)
-                self.assertEQUAL(c + a, b)
+                self.assertEQUAL(b, c + a)
 
 
     def test_tobytes(self):
         a = bitarray()
-        self.assertEqual(a.tobytes(), to_bytes(''))
+        self.assertEqual(a.tobytes(), b'')
 
         for end in ('big', 'little'):
             a = bitarray(endian=end)
-            a.frombytes(to_bytes('foo'))
-            self.assertEqual(a.tobytes(), to_bytes('foo'))
+            a.frombytes(b'foo')
+            self.assertEqual(a.tobytes(), b'foo')
 
             for s in self.randombytes():
                 a = bitarray(endian=end)
                 a.frombytes(s)
                 self.assertEqual(a.tobytes(), s)
 
-        for n, s in [(1, '\x01'), (2, '\x03'), (3, '\x07'), (4, '\x0f'),
-                     (5, '\x1f'), (6, '\x3f'), (7, '\x7f'), (8, '\xff'),
-                     (12, '\xff\x0f'), (15, '\xff\x7f'), (16, '\xff\xff'),
-                     (17, '\xff\xff\x01'), (24, '\xff\xff\xff')]:
+        for n, s in [(1, b'\x01'), (2, b'\x03'), (3, b'\x07'), (4, b'\x0f'),
+                     (5, b'\x1f'), (6, b'\x3f'), (7, b'\x7f'), (8, b'\xff'),
+                     (12, b'\xff\x0f'), (15, b'\xff\x7f'), (16, b'\xff\xff'),
+                     (17, b'\xff\xff\x01'), (24, b'\xff\xff\xff')]:
             a = bitarray(n, endian='little')
             a.setall(1)
-            self.assertEqual(a.tobytes(), to_bytes(s))
+            self.assertEqual(a.tobytes(), s)
 
 
     def test_unpack(self):
         a = bitarray('01')
-        self.assertEqual(a.unpack(), to_bytes('\x00\xff'))
-        self.assertEqual(a.unpack(to_bytes('A')), to_bytes('A\xff'))
-        self.assertEqual(a.unpack(to_bytes('0'), to_bytes('1')),
-                         to_bytes('01'))
-        self.assertEqual(a.unpack(one=to_bytes('\x01')),
-                         to_bytes('\x00\x01'))
-        self.assertEqual(a.unpack(zero=to_bytes('A')),
-                         to_bytes('A\xff'))
-        self.assertEqual(a.unpack(one=to_bytes('t'), zero=to_bytes('f')),
-                         to_bytes('ft'))
-
-        self.assertRaises(TypeError, a.unpack,
-                          to_bytes('a'), zero=to_bytes('b'))
-        self.assertRaises(TypeError, a.unpack, foo=to_bytes('b'))
+        if is_py3k:
+            self.assertIsInstance(a.unpack(), bytes)
+        else:
+            self.assertIsInstance(a.unpack(), str)
+        self.assertEqual(a.unpack(), b'\x00\xff')
+        self.assertEqual(a.unpack(b'A'), b'A\xff')
+        self.assertEqual(a.unpack(b'0', b'1'), b'01')
+        self.assertEqual(a.unpack(one=b'\x01'), b'\x00\x01')
+        self.assertEqual(a.unpack(zero=b'A'), b'A\xff')
+        self.assertEqual(a.unpack(one=b't', zero=b'f'), b'ft')
+
+        self.assertRaises(TypeError, a.unpack, b'a', zero=b'b')
+        self.assertRaises(TypeError, a.unpack, foo=b'b')
 
         for a in self.randombitarrays():
-            self.assertEqual(a.unpack(to_bytes('0'), to_bytes('1')),
-                             to_bytes(a.to01()))
+            self.assertEqual(a.unpack(b'0', b'1'), a.to01().encode())
 
             b = bitarray()
             b.pack(a.unpack())
             self.assertEqual(b, a)
 
             b = bitarray()
-            b.pack(a.unpack(to_bytes('\x01'), to_bytes('\x00')))
+            b.pack(a.unpack(b'\x01', b'\x00'))
             b.invert()
             self.assertEqual(b, a)
 
 
     def test_pack(self):
         a = bitarray()
-        a.pack(to_bytes('\x00'))
+        a.pack(b'\x00')
         self.assertEqual(a, bitarray('0'))
-        a.pack(to_bytes('\xff'))
+        a.pack(b'\xff')
         self.assertEqual(a, bitarray('01'))
-        a.pack(to_bytes('\x01\x00\x7a'))
+        a.pack(b'\x01\x00\x7a')
         self.assertEqual(a, bitarray('01101'))
 
         a = bitarray()
         for n in range(256):
-            a.pack(to_bytes(chr(n)))
+            a.pack(bytes(bytearray([n])))
         self.assertEqual(a, bitarray('0' + 255 * '1'))
 
         self.assertRaises(TypeError, a.pack, 0)
@@ -1724,35 +1846,17 @@ class FileTests(unittest.TestCase, Util):
 
 
     def test_pickle(self):
-        from pickle import load, dump
-
-        for v in range(3):
-            for a in self.randombitarrays():
-                fo = open(self.tmpfname, 'wb')
-                dump(a, fo, v)
-                fo.close()
-                b = load(open(self.tmpfname, 'rb'))
-                self.assert_(b is not a)
-                self.assertEQUAL(a, b)
-
-    def test_cPickle(self):
-        if is_py3k:
-            return
-        from cPickle import load, dump
-
         for v in range(3):
             for a in self.randombitarrays():
-                fo = open(self.tmpfname, 'wb')
-                dump(a, fo, v)
-                fo.close()
-                b = load(open(self.tmpfname, 'rb'))
-                self.assert_(b is not a)
+                with open(self.tmpfname, 'wb') as fo:
+                    pickle.dump(a, fo, v)
+                b = pickle.load(open(self.tmpfname, 'rb'))
+                self.assertFalse(b is a)
                 self.assertEQUAL(a, b)
 
     def test_shelve(self):
-        if sys.version_info[:2] < (2, 5):
+        if not shelve or hasattr(sys, 'gettotalrefcount'):
             return
-        import shelve, hashlib
 
         d = shelve.open(self.tmpfname)
         stored = []
@@ -1779,8 +1883,8 @@ class FileTests(unittest.TestCase, Util):
 
 
     def test_from_empty_file(self):
-        fo = open(self.tmpfname, 'wb')
-        fo.close()
+        with open(self.tmpfname, 'wb') as fo:
+            pass
 
         a = bitarray()
         a.fromfile(open(self.tmpfname, 'rb'))
@@ -1790,9 +1894,8 @@ class FileTests(unittest.TestCase, Util):
     def test_from_large_file(self):
         N = 100000
 
-        fo = open(self.tmpfname, 'wb')
-        fo.write(N * to_bytes('X'))
-        fo.close()
+        with open(self.tmpfname, 'wb') as fo:
+            fo.write(N * b'X')
 
         a = bitarray()
         a.fromfile(open(self.tmpfname, 'rb'))
@@ -1803,9 +1906,8 @@ class FileTests(unittest.TestCase, Util):
 
 
     def test_fromfile_Foo(self):
-        fo = open(self.tmpfname, 'wb')
-        fo.write(to_bytes('Foo\n'))
-        fo.close()
+        with open(self.tmpfname, 'wb') as fo:
+            fo.write(b'Foo\n')
 
         a = bitarray(endian='big')
         a.fromfile(open(self.tmpfname, 'rb'))
@@ -1831,61 +1933,54 @@ class FileTests(unittest.TestCase, Util):
     def test_fromfile_n(self):
         a = bitarray()
         a.fromstring('ABCDEFGHIJ')
-        fo = open(self.tmpfname, 'wb')
-        a.tofile(fo)
-        fo.close()
+        with open(self.tmpfname, 'wb') as fo:
+            a.tofile(fo)
 
         b = bitarray()
-        f = open(self.tmpfname, 'rb')
-        b.fromfile(f, 1);     self.assertEqual(b.tostring(), 'A')
-        f.read(1)
-        b = bitarray()
-        b.fromfile(f, 2);     self.assertEqual(b.tostring(), 'CD')
-        b.fromfile(f, 1);     self.assertEqual(b.tostring(), 'CDE')
-        b.fromfile(f, 0);     self.assertEqual(b.tostring(), 'CDE')
-        b.fromfile(f);        self.assertEqual(b.tostring(), 'CDEFGHIJ')
-        b.fromfile(f);        self.assertEqual(b.tostring(), 'CDEFGHIJ')
-        f.close()
+        with open(self.tmpfname, 'rb') as f:
+            b.fromfile(f, 0);     self.assertEqual(b.tostring(), '')
+            b.fromfile(f, 1);     self.assertEqual(b.tostring(), 'A')
+            f.read(1)
+            b = bitarray()
+            b.fromfile(f, 2);     self.assertEqual(b.tostring(), 'CD')
+            b.fromfile(f, 1);     self.assertEqual(b.tostring(), 'CDE')
+            b.fromfile(f, 0);     self.assertEqual(b.tostring(), 'CDE')
+            b.fromfile(f);        self.assertEqual(b.tostring(), 'CDEFGHIJ')
+            b.fromfile(f);        self.assertEqual(b.tostring(), 'CDEFGHIJ')
 
         b = bitarray()
-        f = open(self.tmpfname, 'rb')
-        f.read(1);
-        self.assertRaises(EOFError, b.fromfile, f, 10)
-        f.close()
+        with open(self.tmpfname, 'rb') as f:
+            f.read(1);
+            self.assertRaises(EOFError, b.fromfile, f, 10)
+
         self.assertEqual(b.tostring(), 'BCDEFGHIJ')
 
         b = bitarray()
-        f = open(self.tmpfname, 'rb')
-        b.fromfile(f);
-        self.assertEqual(b.tostring(), 'ABCDEFGHIJ')
-        self.assertRaises(EOFError, b.fromfile, f, 1)
-        f.close()
+        with open(self.tmpfname, 'rb') as f:
+            b.fromfile(f);
+            self.assertEqual(b.tostring(), 'ABCDEFGHIJ')
+            self.assertRaises(EOFError, b.fromfile, f, 1)
 
 
     def test_tofile(self):
         a = bitarray()
-        f = open(self.tmpfname, 'wb')
-        a.tofile(f)
-        f.close()
+        with open(self.tmpfname, 'wb') as f:
+            a.tofile(f)
 
-        fi = open(self.tmpfname, 'rb')
-        self.assertEqual(fi.read(), to_bytes(''))
-        fi.close()
+        with open(self.tmpfname, 'rb') as fi:
+            self.assertEqual(fi.read(), b'')
 
         a = bitarray('01000110011011110110111100001010', endian='big')
-        f = open(self.tmpfname, 'wb')
-        a.tofile(f)
-        f.close()
+        with open(self.tmpfname, 'wb') as f:
+            a.tofile(f)
 
-        fi = open(self.tmpfname, 'rb')
-        self.assertEqual(fi.read(), to_bytes('Foo\n'))
-        fi.close()
+        with open(self.tmpfname, 'rb') as fi:
+            self.assertEqual(fi.read(), b'Foo\n')
 
         for a in self.randombitarrays():
             b = bitarray(a, endian='big')
-            fo = open(self.tmpfname, 'wb')
-            b.tofile(fo)
-            fo.close()
+            with open(self.tmpfname, 'wb') as fo:
+                b.tofile(fo)
 
             s = open(self.tmpfname, 'rb').read()
             self.assertEqual(len(s), a.buffer_info()[1])
@@ -1895,21 +1990,19 @@ class FileTests(unittest.TestCase, Util):
             self.assertRaises(TypeError, a.tofile)
             self.assertRaises(TypeError, a.tofile, StringIO())
 
-            f = open(self.tmpfname, 'wb')
-            a.tofile(f)
-            f.close()
+            with open(self.tmpfname, 'wb') as f:
+                a.tofile(f)
             self.assertRaises(TypeError, a.tofile, f)
 
         for n in range(20):
             a = n * bitarray('1', endian='little')
-            fo = open(self.tmpfname, 'wb')
-            a.tofile(fo)
-            fo.close()
+            with open(self.tmpfname, 'wb') as fo:
+                a.tofile(fo)
 
             s = open(self.tmpfname, 'rb').read()
             self.assertEqual(len(s), a.buffer_info()[1])
 
-            b = a.__copy__()
+            b = a.copy()
             b.fill()
 
             c = bitarray(endian='little')
@@ -1923,16 +2016,6 @@ tests.append(FileTests)
 
 class PrefixCodeTests(unittest.TestCase, Util):
 
-    def test_encode_errors(self):
-        a = bitarray()
-        self.assertRaises(TypeError, a.encode, 0, '')
-        self.assertRaises(ValueError, a.encode, {}, '')
-        self.assertRaises(TypeError, a.encode, {'a':42}, '')
-        self.assertRaises(ValueError, a.encode, {'a': bitarray()}, '')
-        # 42 not iterable
-        self.assertRaises(TypeError, a.encode, {'a': bitarray('0')}, 42)
-        self.assertEqual(len(a), 0)
-
     def test_encode_string(self):
         a = bitarray()
         d = {'a': bitarray('0')}
@@ -1944,7 +2027,7 @@ class PrefixCodeTests(unittest.TestCase, Util):
 
     def test_encode_list(self):
         a = bitarray()
-        d = {'a':bitarray('0')}
+        d = {'a': bitarray('0')}
         a.encode(d, [])
         self.assertEqual(a, bitarray())
         a.encode(d, ['a'])
@@ -1979,14 +2062,48 @@ class PrefixCodeTests(unittest.TestCase, Util):
                              'a': bitarray('001'), 'n': bitarray('000')})
         self.assertRaises(ValueError, a.encode, d, 'arvin')
 
+    def test_encode_symbol_not_in_code(self):
+        d = {None : bitarray('0'),
+             0    : bitarray('10'),
+             'A'  : bitarray('11')}
+        a = bitarray()
+        a.encode(d, ['A', None, 0])
+        self.assertEqual(a, bitarray('11010'))
+        self.assertRaises(ValueError, a.encode, d, [1, 2])
+        self.assertRaises(ValueError, a.encode, d, 'ABCD')
+
+    def test_encode_not_iterable(self):
+        d = {'a': bitarray('0'), 'b': bitarray('1')}
+        a = bitarray()
+        a.encode(d, 'abba')
+        self.assertRaises(TypeError, a.encode, d, 42)
+        self.assertRaises(TypeError, a.encode, d, 1.3)
+        self.assertRaises(TypeError, a.encode, d, None)
+        self.assertEqual(a, bitarray('0110'))
 
-    def test_decode_check_codedict(self):
+    def test_check_codedict_encode(self):
         a = bitarray()
+        self.assertRaises(TypeError, a.encode, None, '')
+        self.assertRaises(ValueError, a.encode, {}, '')
+        self.assertRaises(TypeError, a.encode, {'a': 'b'}, '')
+        self.assertRaises(ValueError, a.encode, {'a': bitarray()}, '')
+        self.assertEqual(len(a), 0)
+
+    def test_check_codedict_decode(self):
+        a = bitarray('101')
         self.assertRaises(TypeError, a.decode, 0)
         self.assertRaises(ValueError, a.decode, {})
-        # 42 not iterable
-        self.assertRaises(TypeError, a.decode, {'a':42})
-        self.assertRaises(ValueError, a.decode, {'a':bitarray()})
+        self.assertRaises(TypeError, a.decode, {'a': 42})
+        self.assertRaises(ValueError, a.decode, {'a': bitarray()})
+        self.assertEqual(a, bitarray('101'))
+
+    def test_check_codedict_iterdecode(self):
+        a = bitarray('1100101')
+        self.assertRaises(TypeError, a.iterdecode, 0)
+        self.assertRaises(ValueError, a.iterdecode, {})
+        self.assertRaises(TypeError, a.iterdecode, {'a': []})
+        self.assertRaises(ValueError, a.iterdecode, {'a': bitarray()})
+        self.assertEqual(a, bitarray('1100101'))
 
     def test_decode_simple(self):
         d = {'I': bitarray('1'),
@@ -2068,16 +2185,15 @@ class PrefixCodeTests(unittest.TestCase, Util):
         self.assertEqual(a, bitarray('1'))
 
     def test_decode_ambiguous_code(self):
-        d = {'a': bitarray('0'), 'b': bitarray('0'), 'c': bitarray('1')}
-        a = bitarray()
-        self.assertRaises(ValueError, a.decode, d)
-        self.assertRaises(ValueError, a.iterdecode, d)
-
-    def test_decode_ambiguous2(self):
-        d = {'a': bitarray('01'), 'b': bitarray('01'), 'c': bitarray('1')}
-        a = bitarray()
-        self.assertRaises(ValueError, a.decode, d)
-        self.assertRaises(ValueError, a.iterdecode, d)
+        for d in [
+            {'a': bitarray('0'), 'b': bitarray('0'), 'c': bitarray('1')},
+            {'a': bitarray('01'), 'b': bitarray('01'), 'c': bitarray('1')},
+            {'a': bitarray('0'), 'b': bitarray('01')},
+            {'a': bitarray('0'), 'b': bitarray('11'), 'c': bitarray('111')},
+        ]:
+            a = bitarray()
+            self.assertRaises(ValueError, a.decode, d)
+            self.assertRaises(ValueError, a.iterdecode, d)
 
     def test_miscitems(self):
         d = {None : bitarray('00'),
@@ -2099,34 +2215,34 @@ class PrefixCodeTests(unittest.TestCase, Util):
         self.assertStopIteration(it)
 
     def test_real_example(self):
-        code = {' '  : bitarray('001'),
-                '.'  : bitarray('0101010'),
-                'a'  : bitarray('0110'),
-                'b'  : bitarray('0001100'),
-                'c'  : bitarray('000011'),
-                'd'  : bitarray('01011'),
-                'e'  : bitarray('111'),
-                'f'  : bitarray('010100'),
-                'g'  : bitarray('101000'),
-                'h'  : bitarray('00000'),
-                'i'  : bitarray('1011'),
-                'j'  : bitarray('0111101111'),
-                'k'  : bitarray('00011010'),
-                'l'  : bitarray('01110'),
-                'm'  : bitarray('000111'),
-                'n'  : bitarray('1001'),
-                'o'  : bitarray('1000'),
-                'p'  : bitarray('101001'),
-                'q'  : bitarray('00001001101'),
-                'r'  : bitarray('1101'),
-                's'  : bitarray('1100'),
-                't'  : bitarray('0100'),
-                'u'  : bitarray('000100'),
-                'v'  : bitarray('0111100'),
-                'w'  : bitarray('011111'),
-                'x'  : bitarray('0000100011'),
-                'y'  : bitarray('101010'),
-                'z'  : bitarray('00011011110')}
+        code = {' ': bitarray('001'),
+                '.': bitarray('0101010'),
+                'a': bitarray('0110'),
+                'b': bitarray('0001100'),
+                'c': bitarray('000011'),
+                'd': bitarray('01011'),
+                'e': bitarray('111'),
+                'f': bitarray('010100'),
+                'g': bitarray('101000'),
+                'h': bitarray('00000'),
+                'i': bitarray('1011'),
+                'j': bitarray('0111101111'),
+                'k': bitarray('00011010'),
+                'l': bitarray('01110'),
+                'm': bitarray('000111'),
+                'n': bitarray('1001'),
+                'o': bitarray('1000'),
+                'p': bitarray('101001'),
+                'q': bitarray('00001001101'),
+                'r': bitarray('1101'),
+                's': bitarray('1100'),
+                't': bitarray('0100'),
+                'u': bitarray('000100'),
+                'v': bitarray('0111100'),
+                'w': bitarray('011111'),
+                'x': bitarray('0000100011'),
+                'y': bitarray('101010'),
+                'z': bitarray('00011011110')}
         a = bitarray()
         message = 'the quick brown fox jumps over the lazy dog.'
         a.encode(code, message)
@@ -2140,7 +2256,7 @@ class PrefixCodeTests(unittest.TestCase, Util):
 
 tests.append(PrefixCodeTests)
 
-# -------------- Buffer Interface (Python 2.7 only for now) ----------------
+# -------------- Buffer Interface (Python 2.7 and above) --------------------
 
 class BufferInterfaceTests(unittest.TestCase):
 
@@ -2149,36 +2265,117 @@ class BufferInterfaceTests(unittest.TestCase):
         v = memoryview(a)
         self.assertEqual(len(v), 3)
         self.assertEqual(v[0], 65 if is_py3k else 'A')
-        self.assertEqual(v[:].tobytes(), b'ABC')
+        self.assertEqual(v.tobytes(), b'ABC')
         a[13] = 1
-        self.assertEqual(v[:].tobytes(), b'AFC')
+        self.assertEqual(v.tobytes(), b'AFC')
 
     def test_read2(self):
-        a = bitarray([randint(0, 1) for d in range(8000)])
+        a = bitarray()
+        a.frombytes(os.urandom(100))
         v = memoryview(a)
-        self.assertEqual(len(v), 1000)
-        b = a[345 * 8 : 657 * 8]
-        self.assertEqual(v[345:657].tobytes(), b.tobytes())
-        self.assertEqual(v[:].tobytes(), a.tobytes())
+        self.assertEqual(len(v), 100)
+        b = a[34 * 8 : 67 * 8]
+        self.assertEqual(v[34:67].tobytes(), b.tobytes())
+        self.assertEqual(v.tobytes(), a.tobytes())
 
     def test_write(self):
-        a = bitarray(800000)
+        a = bitarray(8000)
         a.setall(0)
         v = memoryview(a)
         self.assertFalse(v.readonly)
-        v[50000] = 255 if is_py3k else '\xff'
-        self.assertEqual(a[399999:400009], bitarray('0111111110'))
-        a[400003] = 0
-        self.assertEqual(a[399999:400009], bitarray('0111011110'))
-        v[30001:30004] = b'ABC'
-        self.assertEqual(a[240000:240040].tobytes(), b'\x00ABC\x00')
+        v[500] = 255 if is_py3k else '\xff'
+        self.assertEqual(a[3999:4009], bitarray('0111111110'))
+        a[4003] = 0
+        self.assertEqual(a[3999:4009], bitarray('0111011110'))
+        v[301:304] = b'ABC'
+        self.assertEqual(a[300 *8 : 305 * 8].tobytes(), b'\x00ABC\x00')
 
 if sys.version_info[:2] >= (2, 7):
     tests.append(BufferInterfaceTests)
 
 # ---------------------------------------------------------------------------
 
+class TestsFrozenbitarray(unittest.TestCase, Util):
+
+    def test_init(self):
+        a = frozenbitarray('110')
+        self.assertEqual(a, bitarray('110'))
+        self.assertEqual(a.to01(), '110')
+        for endian in 'big', 'little':
+            a = frozenbitarray(0, endian)
+            self.assertEqual(a.endian(), endian)
+
+    def test_methods(self):
+        # test a few methods which do not raise the TypeError
+        a = frozenbitarray('1101100')
+        self.assertEqual(a[2], 0)
+        self.assertEqual(a[:4].to01(), '1101')
+        self.assertEqual(a.count(), 4)
+        self.assertEqual(a.index(0), 2)
+        b = a.copy()
+        self.assertEqual(b, a)
+        self.assertEqual(repr(type(b)), "<class 'bitarray.frozenbitarray'>")
+        self.assertEqual(len(b), 7)
+        self.assertEqual(b.length(), 7)
+        self.assertEqual(b.all(), False)
+        self.assertEqual(b.any(), True)
+
+    def test_init_bitarray(self):
+        for a in self.randombitarrays():
+            b = frozenbitarray(a)
+            self.assertFalse(b is a)
+            self.assertEqual(b, a)
+            self.assertEqual(b.endian(), a.endian())
+            c = frozenbitarray(b)
+            self.assertEqual(c, b)
+            self.assertFalse(c is b)
+            self.assertEqual(c.endian(), a.endian())
+            self.assertEqual(hash(c), hash(b))
+
+    def test_repr(self):
+        a = frozenbitarray()
+        self.assertEqual(repr(a), "frozenbitarray()")
+        self.assertEqual(str(a), "frozenbitarray()")
+        a = frozenbitarray('10111')
+        self.assertEqual(repr(a), "frozenbitarray('10111')")
+        self.assertEqual(str(a), "frozenbitarray('10111')")
+
+    def test_immutable(self):
+        a = frozenbitarray('111')
+        self.assertRaises(TypeError, a.append, True)
+        self.assertRaises(TypeError, a.__setitem__, 0, 0)
+        self.assertRaises(TypeError, a.__delitem__, 0)
+
+    def test_dictkey(self):
+        a = frozenbitarray('01')
+        b = frozenbitarray('1001')
+        d = {a: 123, b: 345}
+        self.assertEqual(d[frozenbitarray('01')], 123)
+        self.assertEqual(d[frozenbitarray(b)], 345)
+
+    def test_dictkey2(self): # taken sllightly modified from issue #74
+        a1 = frozenbitarray([True, False])
+        a2 = frozenbitarray([False, False])
+        dct = {a1: "one", a2: "two"}
+        a3 = frozenbitarray([True, False])
+        self.assertEqual(a3, a1)
+        self.assertEqual(dct[a3], 'one')
+
+    def test_mix(self):
+        a = bitarray('110')
+        b = frozenbitarray('0011')
+        self.assertEqual(a + b, bitarray('1100011'))
+        a.extend(b)
+        self.assertEqual(a, bitarray('1100011'))
+
+tests.append(TestsFrozenbitarray)
+
+# ---------------------------------------------------------------------------
+
 def run(verbosity=1, repeat=1):
+    import bitarray.test_util as btu
+    tests.extend(btu.tests)
+
     print('bitarray is installed in: %s' % os.path.dirname(__file__))
     print('bitarray version: %s' % __version__)
     print('Python version: %s' % sys.version)
diff --git a/shell/ext-py/bitarray-1.2.1/bitarray/test_util.py b/shell/ext-py/bitarray-1.2.1/bitarray/test_util.py
new file mode 100644
index 0000000..2446290
--- /dev/null
+++ b/shell/ext-py/bitarray-1.2.1/bitarray/test_util.py
@@ -0,0 +1,590 @@
+"""
+Tests for bitarray.util module
+"""
+import os
+import sys
+import unittest
+from string import hexdigits
+from random import choice, randint
+try:
+    from collections import Counter
+except ImportError:
+    pass
+
+from bitarray import bitarray, frozenbitarray, bits2bytes
+from bitarray.test_bitarray import Util
+
+from bitarray.util import (zeros, rindex, strip, count_n,
+                           count_and, count_or, count_xor, subset,
+                           ba2hex, hex2ba, ba2int, int2ba, huffman_code)
+
+
+tests = []
+
+# ---------------------------------------------------------------------------
+
+class TestsZeros(unittest.TestCase):
+
+    def test_init(self):
+        a = zeros(0)
+        self.assertEqual(a, bitarray(''))
+        self.assertEqual(a.endian(), 'big')
+        self.assertRaises(TypeError, zeros, 1.0)
+        for n in range(100):
+            a = zeros(n)
+            self.assertEqual(a, bitarray(n * '0'))
+        self.assertRaises(TypeError, zeros) # no argument
+
+        # wrong arguments
+        self.assertRaises(TypeError, zeros, '')
+        self.assertRaises(TypeError, zeros, bitarray())
+        self.assertRaises(TypeError, zeros, [])
+        self.assertRaises(ValueError, zeros, -1)
+
+        self.assertRaises(TypeError, zeros, 0, 1) # endian not string
+        self.assertRaises(ValueError, zeros, 0, 'foo') # endian wrong string
+
+    def test_endian(self):
+        for endian in 'big', 'little':
+            a = zeros(1, endian)
+            self.assertEqual(a, bitarray('0'))
+            self.assertEqual(a.endian(), endian)
+            a = zeros(1, endian=endian)
+            self.assertEqual(a, bitarray('0'))
+            self.assertEqual(a.endian(), endian)
+
+tests.append(TestsZeros)
+
+# ---------------------------------------------------------------------------
+
+class TestsHelpers(unittest.TestCase, Util):
+
+    def test_rindex(self):
+        self.assertRaises(TypeError, rindex)
+        self.assertRaises(TypeError, rindex, None)
+        self.assertRaises(TypeError, rindex, bitarray(), 1, 2)
+        for endian in 'big', 'little':
+            a = bitarray('00010110000', endian)
+            self.assertEqual(rindex(a), 6)
+            self.assertEqual(rindex(a, 1), 6)
+            self.assertEqual(rindex(a, 'A'), 6)
+            self.assertEqual(rindex(a, True), 6)
+
+            a = bitarray('00010110111', endian)
+            self.assertEqual(rindex(a, 0), 7)
+            self.assertEqual(rindex(a, None), 7)
+            self.assertEqual(rindex(a, False), 7)
+
+            a = frozenbitarray('00010110111', endian)
+            self.assertEqual(rindex(a, 0), 7)
+            self.assertEqual(rindex(a, None), 7)
+            self.assertEqual(rindex(a, False), 7)
+
+            for v in 0, 1:
+                self.assertRaises(ValueError, rindex,
+                                  bitarray(0, endian), v)
+            self.assertRaises(ValueError, rindex,
+                              bitarray('000', endian), 1)
+            self.assertRaises(ValueError, rindex,
+                              bitarray('11111', endian), 0)
+
+    def test_rindex2(self):
+        for a in self.randombitarrays():
+            v = randint(0, 1)
+            try:
+                i = rindex(a, v)
+            except ValueError:
+                i = None
+            s = a.to01()
+            try:
+                j = s.rindex(str(v))
+            except ValueError:
+                j = None
+            self.assertEqual(i, j)
+
+    def test_rindex3(self):
+        for _ in range(100):
+            n = randint(1, 100000)
+            v = randint(0, 1)
+            a = bitarray(n)
+            a.setall(1 - v)
+            lst = [randint(0, n - 1) for _ in range(100)]
+            for i in lst:
+                a[i] = v
+            self.assertEqual(rindex(a, v), max(lst))
+
+    def test_rindex4(self):
+        for _ in range(100):
+            N = randint(1, 10000)
+            a = bitarray(N)
+            a.setall(0)
+            a[randint(0, N - 1)] = 1
+            self.assertEqual(rindex(a), a.index(1))
+
+    def test_strip1(self):
+        self.assertRaises(TypeError, strip, bitarray(), 123)
+        self.assertRaises(ValueError, strip, bitarray(), 'up')
+        for endian in 'big', 'little':
+            a = bitarray('00010110000', endian)
+            self.assertEQUAL(strip(a), bitarray('0001011', endian))
+            self.assertEQUAL(strip(a, 'left'), bitarray('10110000', endian))
+            self.assertEQUAL(strip(a, 'both'), bitarray('1011', endian))
+
+        for mode in 'left', 'right', 'both':
+            self.assertEqual(strip(bitarray('000'), mode), bitarray())
+            self.assertEqual(strip(bitarray(), mode), bitarray())
+
+    def test_strip2(self):
+        for a in self.randombitarrays():
+            b = a.copy()
+            s = a.to01()
+            self.assertEqual(strip(a, 'left'), bitarray(s.lstrip('0')))
+            self.assertEqual(strip(a, 'right'), bitarray(s.rstrip('0')))
+            self.assertEqual(strip(a, 'both'), bitarray(s.strip('0')))
+            self.assertEQUAL(a, b)
+
+    def test_strip_both(self):
+        for _ in range(100):
+            N = randint(1, 10000)
+            a = bitarray(N)
+            a.setall(0)
+            a[randint(0, N - 1)] = 1
+            self.assertEqual(strip(a, 'both'), bitarray('1'))
+
+    def check_result(self, a, n, i):
+        self.assertEqual(a.count(1, 0, i), n)
+        if i:
+            self.assertTrue(a[i - 1])
+
+    def test_count_n1(self):
+        a = bitarray('111110111110111110111110011110111110111110111000')
+        b = a.copy()
+        self.assertEqual(len(a), 48)
+        self.assertEqual(a.count(), 37)
+        self.assertRaises(TypeError, count_n, '', 0)
+        self.assertEqual(count_n(a, 0), 0)
+        self.assertEqual(count_n(a, 20), 23)
+        self.assertEqual(count_n(a, 37), 45)
+        self.assertRaises(ValueError, count_n, a, -1) # n < 0
+        self.assertRaises(ValueError, count_n, a, 38) # n > a.count()
+        self.assertRaises(ValueError, count_n, a, 49) # n > len(a)
+        self.assertRaises(TypeError, count_n, a, "7")
+        for n in range(0, 37):
+            i = count_n(a, n)
+            self.check_result(a, n, i)
+            self.assertEqual(a[:i].count(), n)
+        self.assertEQUAL(a, b)
+
+    def test_count_n1_frozen(self):
+        a = frozenbitarray('001111101111101111101111100111100')
+        self.assertEqual(len(a), 33)
+        self.assertEqual(a.count(), 24)
+        self.assertRaises(TypeError, count_n, '', 0)
+        self.assertEqual(count_n(a, 0), 0)
+        self.assertEqual(count_n(a, 10), 13)
+        self.assertEqual(count_n(a, 24), 31)
+        self.assertRaises(ValueError, count_n, a, -1) # n < 0
+        self.assertRaises(ValueError, count_n, a, 25) # n > a.count()
+        self.assertRaises(ValueError, count_n, a, 34) # n > len(a)
+        self.assertRaises(TypeError, count_n, a, "7")
+
+    def test_count_n2(self):
+        for N in list(range(100)) + [1000, 10000, 100000]:
+            a = bitarray(N)
+            v = randint(0, 1)
+            a.setall(v - 1)
+            for _ in range(randint(0, min(N, 100))):
+                a[randint(0, N - 1)] = v
+            n = randint(0, a.count())
+            self.check_result(a, n, count_n(a, n))
+            # check for total count
+            tc = a.count()
+            self.assertTrue(count_n(a, tc) <= N)
+            self.assertRaises(ValueError, count_n, a, tc + 1)
+
+    def test_count_n3(self):
+        N = 100000
+        for _ in range(10):
+            a = bitarray(N)
+            a.setall(0)
+            self.assertEqual(count_n(a, 0), 0)
+            self.assertRaises(ValueError, count_n, a, 1)
+            i = randint(0, N - 1)
+            a[i] = 1
+            self.assertEqual(count_n(a, 1), i + 1)
+            self.assertRaises(ValueError, count_n, a, 2)
+
+    def test_count_n4(self):
+        for a in self.randombitarrays():
+            n = a.count() // 2
+            i = count_n(a, n)
+            self.check_result(a, n, i)
+
+tests.append(TestsHelpers)
+
+# ---------------------------------------------------------------------------
+
+class TestsBitwiseCount(unittest.TestCase, Util):
+
+    def test_bit_count1(self):
+        a = bitarray('001111')
+        aa = a.copy()
+        b = bitarray('010011')
+        bb = b.copy()
+        self.assertEqual(count_and(a, b), 2)
+        self.assertEqual(count_or(a, b), 5)
+        self.assertEqual(count_xor(a, b), 3)
+        for f in count_and, count_or, count_xor:
+            # not two arguments
+            self.assertRaises(TypeError, f)
+            self.assertRaises(TypeError, f, a)
+            self.assertRaises(TypeError, f, a, b, 3)
+            # wrong argument types
+            self.assertRaises(TypeError, f, a, '')
+            self.assertRaises(TypeError, f, '1', b)
+            self.assertRaises(TypeError, f, a, 4)
+        self.assertEQUAL(a, aa)
+        self.assertEQUAL(b, bb)
+
+        b.append(1)
+        for f in count_and, count_or, count_xor:
+            self.assertRaises(ValueError, f, a, b)
+            self.assertRaises(ValueError, f,
+                              bitarray('110', 'big'),
+                              bitarray('101', 'little'))
+
+    def test_bit_count_frozen(self):
+        a = frozenbitarray('001111')
+        b = frozenbitarray('010011')
+        self.assertEqual(count_and(a, b), 2)
+        self.assertEqual(count_or(a, b), 5)
+        self.assertEqual(count_xor(a, b), 3)
+
+    def test_bit_count2(self):
+        for n in list(range(50)) + [randint(1000, 2000)]:
+            a = bitarray()
+            a.frombytes(os.urandom(bits2bytes(n)))
+            del a[n:]
+            b = bitarray()
+            b.frombytes(os.urandom(bits2bytes(n)))
+            del b[n:]
+            self.assertEqual(count_and(a, b), (a & b).count())
+            self.assertEqual(count_or(a, b),  (a | b).count())
+            self.assertEqual(count_xor(a, b), (a ^ b).count())
+
+tests.append(TestsBitwiseCount)
+
+# ---------------------------------------------------------------------------
+
+class TestsSubset(unittest.TestCase, Util):
+
+    def test_subset(self):
+        a = frozenbitarray('0101')
+        b = bitarray('0111')
+        self.assertTrue(subset(a, b))
+        self.assertFalse(subset(b, a))
+        self.assertRaises(TypeError, subset)
+        self.assertRaises(TypeError, subset, a, '')
+        self.assertRaises(TypeError, subset, '1', b)
+        self.assertRaises(TypeError, subset, a, 4)
+        b.append(1)
+        self.assertRaises(ValueError, subset, a, b)
+
+    def subset_simple(self, a, b):
+        return (a & b).count() == a.count()
+
+    def test_subset_True(self):
+        for a, b in [('', ''), ('0', '1'), ('0', '0'), ('1', '1'),
+                     ('000', '111'), ('0101', '0111'),
+                     ('000010111', '010011111')]:
+            a, b = bitarray(a), bitarray(b)
+            self.assertTrue(subset(a, b) is True)
+            self.assertTrue(self.subset_simple(a, b) is True)
+
+    def test_subset_False(self):
+        for a, b in [('1', '0'), ('1101', '0111'),
+                     ('0000101111', '0100111011')]:
+            a, b = bitarray(a), bitarray(b)
+            self.assertTrue(subset(a, b) is False)
+            self.assertTrue(self.subset_simple(a, b) is False)
+
+    def test_many(self):
+        for a in self.randombitarrays(start=1):
+            b = a.copy()
+            # we set one random bit in b to 1, so a is always a subset of b
+            b[randint(0, len(a)-1)] = 1
+            self.assertTrue(subset(a, b))
+            # but b in not always a subset of a
+            self.assertEqual(subset(b, a), self.subset_simple(b, a))
+            # we set all bits in a, which ensures that b is a subset of a
+            a.setall(1)
+            self.assertTrue(subset(b, a))
+
+tests.append(TestsSubset)
+
+# ---------------------------------------------------------------------------
+
+class TestsHexlify(unittest.TestCase, Util):
+
+    def test_ba2hex(self):
+        self.assertEqual(ba2hex(bitarray(0, 'big')), b'')
+        self.assertEqual(ba2hex(bitarray('1110', 'big')), b'e')
+        self.assertEqual(ba2hex(bitarray('00000001', 'big')), b'01')
+        self.assertEqual(ba2hex(bitarray('10000000', 'big')), b'80')
+        self.assertEqual(ba2hex(frozenbitarray('11000111', 'big')), b'c7')
+        # length not multiple of 4
+        self.assertRaises(ValueError, ba2hex, bitarray('10'))
+        self.assertRaises(ValueError, ba2hex, bitarray(endian='little'))
+        self.assertRaises(TypeError, ba2hex, '101')
+
+        for n in range(7):
+            a = bitarray(n * '1111', 'big')
+            b = a.copy()
+            self.assertEqual(ba2hex(a), n * b'f')
+            # ensure original object wasn't altered
+            self.assertEQUAL(a, b)
+
+    def test_hex2ba(self):
+        self.assertEqual(hex2ba(''), bitarray())
+        for c in 'e', 'E', b'e', b'E':
+            a = hex2ba(c)
+            self.assertEqual(a.to01(), '1110')
+            self.assertEqual(a.endian(), 'big')
+        self.assertEQUAL(hex2ba('01'), bitarray('00000001', 'big'))
+        self.assertRaises(Exception, hex2ba, '01a7x89')
+        self.assertRaises(TypeError, hex2ba, 0)
+
+    def test_explicit(self):
+        for h, bs in [(b'',    ''),
+                      (b'0',   '0000'),
+                      (b'a',   '1010'),
+                      (b'f',   '1111'),
+                      (b'1a',  '00011010'),
+                      (b'2b',  '00101011'),
+                      (b'4c1', '010011000001'),
+                      (b'a7d', '101001111101')]:
+            a = bitarray(bs, 'big')
+            self.assertEQUAL(hex2ba(h), a)
+            self.assertEqual(ba2hex(a), h)
+
+    def test_round_trip(self):
+        for i in range(100):
+            s = ''.join(choice(hexdigits) for _ in range(randint(0, 1000)))
+            t = ba2hex(hex2ba(s))
+            self.assertEqual(t.decode(), s.lower())
+
+    def test_round_trip2(self):
+        for a in self.randombitarrays():
+            if len(a) % 4 or a.endian() != 'big':
+                self.assertRaises(ValueError, ba2hex, a)
+                continue
+            b = hex2ba(ba2hex(a))
+            self.assertEQUAL(b, a)
+
+tests.append(TestsHexlify)
+
+# ---------------------------------------------------------------------------
+
+class TestsIntegerization(unittest.TestCase, Util):
+
+    def test_ba2int(self):
+        self.assertEqual(ba2int(bitarray('0')), 0)
+        self.assertEqual(ba2int(bitarray('1')), 1)
+        self.assertEqual(ba2int(bitarray('00101', 'big')), 5)
+        self.assertEqual(ba2int(bitarray('00101', 'little')), 20)
+        self.assertEqual(ba2int(frozenbitarray('11')), 3)
+        self.assertRaises(ValueError, ba2int, bitarray())
+        self.assertRaises(ValueError, ba2int, frozenbitarray())
+        self.assertRaises(TypeError, ba2hex, '101')
+        a = bitarray('111')
+        b = a.copy()
+        self.assertEqual(ba2int(a), 7)
+        # ensure original object wasn't altered
+        self.assertEQUAL(a, b)
+
+    def test_int2ba(self):
+        self.assertEqual(int2ba(0), bitarray('0'))
+        self.assertEqual(int2ba(1), bitarray('1'))
+        self.assertEqual(int2ba(5), bitarray('101'))
+        self.assertEQUAL(int2ba(6), bitarray('110', 'big'))
+        self.assertEQUAL(int2ba(6, endian='little'),
+                         bitarray('011', 'little'))
+        self.assertRaises(ValueError, int2ba, -1)
+        self.assertRaises(TypeError, int2ba, 1.0)
+        self.assertRaises(TypeError, int2ba, 1, 3.0)
+        self.assertRaises(ValueError, int2ba, 1, 0)
+        self.assertRaises(TypeError, int2ba, 1, 10, 123)
+        self.assertRaises(ValueError, int2ba, 1, 10, 'asd')
+
+    def test_int2ba_length(self):
+        self.assertRaises(TypeError, int2ba, 0, 1.0)
+        self.assertRaises(ValueError, int2ba, 0, 0)
+        self.assertEqual(int2ba(5, length=6), bitarray('000101'))
+        self.assertRaises(OverflowError, int2ba, 3, 1)
+        for n in range(1, 100):
+            ab = int2ba(1, n, 'big')
+            al = int2ba(1, n, 'little')
+            self.assertEqual(ab.endian(), 'big')
+            self.assertEqual(al.endian(), 'little')
+            self.assertEqual(len(ab), n),
+            self.assertEqual(len(al), n)
+            self.assertEqual(ab, bitarray((n - 1) * '0') + bitarray('1'))
+            self.assertEqual(al, bitarray('1') + bitarray((n - 1) * '0'))
+
+            ab = int2ba(0, n, 'big')
+            al = int2ba(0, n, 'little')
+            self.assertEqual(len(ab), n)
+            self.assertEqual(len(al), n)
+            self.assertEqual(ab, bitarray(n * '0', 'big'))
+            self.assertEqual(al, bitarray(n * '0', 'little'))
+
+            self.assertRaises(OverflowError, int2ba, 2 ** n, n, 'big')
+            self.assertRaises(OverflowError, int2ba, 2 ** n, n, 'little')
+            self.assertEqual(int2ba(2 ** n - 1), bitarray(n * '1'))
+            self.assertEqual(int2ba(2 ** n - 1, endian='little'),
+                             bitarray(n * '1'))
+
+    def test_explicit(self):
+        for i, sa in [( 0,     '0'),    (1,         '1'),
+                      ( 2,    '10'),    (3,        '11'),
+                      (25, '11001'),  (265, '100001001'),
+                      (3691038, '1110000101001000011110')]:
+            ab = bitarray(sa, 'big')
+            al = bitarray(sa[::-1], 'little')
+            self.assertEQUAL(int2ba(i), ab)
+            self.assertEQUAL(int2ba(i, endian='little'), al)
+            self.assertEqual(ba2int(ab), ba2int(al), i)
+            if i == 0 or i >= 512:
+                continue
+            for n in range(9, 32):
+                for endian in 'big', 'little':
+                    a = int2ba(i, length=n, endian=endian)
+                    self.assertEqual(a.endian(), endian)
+                    self.assertEqual(len(a), n)
+                    if endian == 'big':
+                        f = a.index(1)
+                        self.assertEqual(a[:f], bitarray(f * '0'))
+                        self.assertEqual(a[f:], ab)
+
+    def check_round_trip(self, i):
+        for endian in 'big', 'little':
+            a = int2ba(i, endian=endian)
+            self.assertEqual(a.endian(), endian)
+            self.assertTrue(len(a) > 0)
+            # ensure we have no leading zeros
+            if a.endian == 'big':
+                self.assertTrue(len(a) == 1 or a.index(1) == 0)
+            self.assertEqual(ba2int(a), i)
+            if i > 0 and sys.version_info[:2] >= (2, 7):
+                self.assertEqual(i.bit_length(), len(a))
+            # add a few / trailing leading zeros to bitarray
+            if endian == 'big':
+                a = zeros(randint(0, 3), endian) + a
+            else:
+                a = a + zeros(randint(0, 3), endian)
+            self.assertEqual(a.endian(), endian)
+            self.assertEqual(ba2int(a), i)
+
+    def test_many(self):
+        for i in range(1000):
+            self.check_round_trip(i)
+            self.check_round_trip(randint(0, 10 ** randint(3, 300)))
+
+
+tests.append(TestsIntegerization)
+
+# ---------------------------------------------------------------------------
+
+class TestsHuffman(unittest.TestCase):
+
+    def test_simple(self):
+        freq = {0: 10, 'as': 2, None: 1.6}
+        code = huffman_code(freq)
+        self.assertEqual(len(code), 3)
+        self.assertEqual(len(code[0]), 1)
+        self.assertEqual(len(code['as']), 2)
+        self.assertEqual(len(code[None]), 2)
+
+    def test_tiny(self):
+        code = huffman_code({0: 0})
+        self.assertEqual(len(code), 1)
+        self.assertEqual(code, {0: bitarray()})
+
+        code = huffman_code({0: 0, 1: 0})
+        self.assertEqual(len(code), 2)
+        for i in range(2):
+            self.assertEqual(len(code[i]), 1)
+
+    def test_endianness(self):
+        freq = {'A': 10, 'B': 2, 'C': 5}
+        for endian in 'big', 'little':
+            code = huffman_code(freq, endian)
+            self.assertEqual(len(code), 3)
+            for v in code.values():
+                self.assertEqual(v.endian(), endian)
+
+    def test_wrong_arg(self):
+        self.assertRaises(TypeError, huffman_code, [('a', 1)])
+        self.assertRaises(TypeError, huffman_code, 123)
+        self.assertRaises(TypeError, huffman_code, None)
+        # cannot compare 'a' with 1
+        self.assertRaises(TypeError, huffman_code, {'A': 'a', 'B': 1})
+        self.assertRaises(ValueError, huffman_code, {})
+
+    def test_balanced(self):
+        n = 6
+        freq = {}
+        for i in range(2 ** n):
+            freq[i] = 1
+        code = huffman_code(freq)
+        self.assertEqual(len(code), 2 ** n)
+        self.assertTrue(all(len(v) == n for v in code.values()))
+
+    def test_unbalanced(self):
+        N = 27
+        freq = {}
+        for i in range(N):
+            freq[i] = 2 ** i
+        code = huffman_code(freq)
+        self.assertEqual(len(code), N)
+        for i in range(N):
+            self.assertEqual(len(code[i]), N - (1 if i <= 1 else i))
+
+    if sys.version_info[:2] >= (2, 7):
+        def test_counter(self):
+            message = 'the quick brown fox jumps over the lazy dog.'
+            code = huffman_code(Counter(message))
+            a = bitarray()
+            a.encode(code, message)
+            self.assertEqual(''.join(a.decode(code)), message)
+
+        def test_rand_list(self):
+            plain = [randint(0, 100) for _ in range(500)]
+            code = huffman_code(Counter(plain))
+            a = bitarray()
+            a.encode(code, plain)
+            self.assertEqual(a.decode(code), plain)
+
+
+tests.append(TestsHuffman)
+
+# ---------------------------------------------------------------------------
+
+def run(verbosity=1):
+    import os
+    import bitarray
+
+    print('bitarray is installed in: %s' % os.path.dirname(bitarray.__file__))
+    print('bitarray version: %s' % bitarray.__version__)
+    print('Python version: %s' % sys.version)
+
+    suite = unittest.TestSuite()
+    for cls in tests:
+        suite.addTest(unittest.makeSuite(cls))
+
+    runner = unittest.TextTestRunner(verbosity=verbosity)
+    return runner.run(suite)
+
+
+if __name__ == '__main__':
+    run()
diff --git a/shell/ext-py/bitarray-1.2.1/bitarray/util.py b/shell/ext-py/bitarray-1.2.1/bitarray/util.py
new file mode 100644
index 0000000..f2ddb40
--- /dev/null
+++ b/shell/ext-py/bitarray-1.2.1/bitarray/util.py
@@ -0,0 +1,274 @@
+# Copyright (c) 2019, Ilan Schnell
+# bitarray is published under the PSF license.
+#
+# Author: Ilan Schnell
+"""
+Useful utilities for working with bitarrays.
+"""
+import sys
+import heapq
+import binascii
+
+from bitarray import bitarray, frozenbitarray, bits2bytes, _bitarray
+
+from bitarray._util import (count_n, rindex,
+                            count_and, count_or, count_xor, subset,
+                            _set_babt)
+
+
+__all__ = ['zeros', 'rindex', 'strip', 'count_n',
+           'count_and', 'count_or', 'count_xor', 'subset',
+           'ba2hex', 'hex2ba', 'ba2int', 'int2ba', 'huffman_code']
+
+
+# tell the _util extension what the bitarray base type is, such that it can
+# check for instances thereof when checking for bitarray type
+_set_babt(_bitarray)
+
+_is_py2 = bool(sys.version_info[0] == 2)
+
+
+def zeros(length, endian='big'):
+    """zeros(length, /, endian='big') -> bitarray
+
+Create a bitarray of length, with all values 0.
+"""
+    if not isinstance(length, (int, long) if _is_py2 else int):
+        raise TypeError("integer expected")
+
+    a = bitarray(length, endian)
+    a.setall(0)
+    return a
+
+
+def strip(a, mode='right'):
+    """strip(bitarray, mode='right', /) -> bitarray
+
+Strip zeros from left, right or both ends.
+Allowed values for mode are the strings: `left`, `right`, `both`
+"""
+    if not isinstance(a, (bitarray, frozenbitarray)):
+        raise TypeError("bitarray expected")
+    if not isinstance(mode, str):
+        raise TypeError("string expected for mode")
+    if mode not in ('left', 'right', 'both'):
+        raise ValueError("allowed values 'left', 'right', 'both', got: %r" %
+                         mode)
+    first = 0
+    if mode in ('left', 'both'):
+        try:
+            first = a.index(1)
+        except ValueError:
+            return bitarray(endian=a.endian())
+
+    last = a.length() - 1
+    if mode in ('right', 'both'):
+        try:
+            last = rindex(a)
+        except ValueError:
+            return bitarray(endian=a.endian())
+
+    return a[first:last + 1]
+
+
+def ba2hex(a):
+    """ba2hex(bitarray, /) -> hexstr
+
+Return a bytes object containing with hexadecimal representation of
+the bitarray (which has to be multiple of 4 in length).
+"""
+    if not isinstance(a, (bitarray, frozenbitarray)):
+        raise TypeError("bitarray expected")
+    if a.endian() != 'big':
+        raise ValueError("big-endian bitarray expected")
+    la = a.length()
+    if la % 4:
+        raise ValueError("bitarray length not multiple of 4")
+    if la % 8:
+        # make sure we don't mutate the original argument
+        a = a + bitarray(4, 'big')
+    assert a.length() % 8 == 0
+
+    s = binascii.hexlify(a.tobytes())
+    if la % 8:
+        s = s[:-1]
+    return s
+
+
+def hex2ba(s):
+    """hex2ba(hexstr, /) -> bitarray
+
+Bitarray of hexadecimal representation.
+hexstr may contain any number of hex digits (upper or lower case).
+"""
+    if not isinstance(s, (str, bytes)):
+        raise TypeError("string expected")
+
+    ls = len(s)
+    if ls % 2:
+        s = s + ('0' if isinstance(s, str) else b'0')
+    assert len(s) % 2 == 0
+
+    a = bitarray(endian='big')
+    a.frombytes(binascii.unhexlify(s))
+    if ls % 2:
+        del a[-4:]
+    return a
+
+
+def ba2int(a):
+    """ba2int(bitarray, /) -> int
+
+Convert the given bitarray into an integer.
+The bit-endianness of the bitarray is respected.
+"""
+    if not isinstance(a, (bitarray, frozenbitarray)):
+        raise TypeError("bitarray expected")
+    if not a:
+        raise ValueError("non-empty bitarray expected")
+
+    endian = a.endian()
+    big_endian = bool(endian == 'big')
+    if a.length() % 8:
+        # pad with leading zeros, such that length is multiple of 8
+        if big_endian:
+            a = zeros(8 - a.length() % 8, 'big') + a
+        else:
+            a = a + zeros(8 - a.length() % 8, 'little')
+    assert a.length() % 8 == 0
+    b = a.tobytes()
+
+    if _is_py2:
+        c = bytearray(b)
+        res = 0
+        j = len(c) - 1 if big_endian else 0
+        for x in c:
+            res |= x << 8 * j
+            j += -1 if big_endian else 1
+        return res
+    else: # py3
+        return int.from_bytes(b, byteorder=endian)
+
+
+def int2ba(i, length=None, endian='big'):
+    """int2ba(int, /, length=None, endian='big') -> bitarray
+
+Convert the given integer into a bitarray (with given endianness,
+and no leading (big-endian) / trailing (little-endian) zeros).
+If length is provided, the result will be of this length, and an
+`OverflowError` will be raised, if the integer cannot be represented
+within length bits.
+"""
+    if not isinstance(i, (int, long) if _is_py2 else int):
+        raise TypeError("integer expected")
+    if i < 0:
+        raise ValueError("non-negative integer expected")
+    if length is not None:
+        if not isinstance(length, int):
+            raise TypeError("integer expected for length")
+        if length <= 0:
+            raise ValueError("integer larger than 0 expected for length")
+    if not isinstance(endian, str):
+        raise TypeError("string expected for endian")
+    if endian not in ('big', 'little'):
+        raise ValueError("endian can only be 'big' or 'little'")
+
+    if i == 0:
+        # there a special cases for 0 which we'd rather not deal with below
+        return zeros(length or 1, endian=endian)
+
+    big_endian = bool(endian == 'big')
+    if _is_py2:
+        c = bytearray()
+        while i:
+            i, r = divmod(i, 256)
+            c.append(r)
+        if big_endian:
+            c.reverse()
+        b = bytes(c)
+    else: # py3
+        b = i.to_bytes(bits2bytes(i.bit_length()), byteorder=endian)
+
+    a = bitarray(endian=endian)
+    a.frombytes(b)
+    la = a.length()
+    if la == length:
+        return a
+
+    if length is None:
+        return strip(a, 'left' if big_endian else 'right')
+
+    if la > length:
+        size = (la - a.index(1)) if big_endian else (rindex(a) + 1)
+        if size > length:
+            raise OverflowError("cannot represent %d bit integer in "
+                                "%d bits" % (size, length))
+        a = a[la - length:] if big_endian else a[:length - la]
+
+    if la < length:
+        if big_endian:
+            a = zeros(length - la, 'big') + a
+        else:
+            a += zeros(length - la, 'little')
+
+    assert a.length() == length
+    return a
+
+
+def huffman_code(freq_map, endian='big'):
+    """huffman_code(dict, /, endian='big') -> dict
+
+Given a frequency map, a dictionary mapping symbols to thier frequency,
+calculate the Huffman code, i.e. a dict mapping those symbols to
+bitarrays (with given endianness).  Note that the symbols may be any
+hashable object (including `None`).
+"""
+    if not isinstance(freq_map, dict):
+        raise TypeError("dict expected")
+    if len(freq_map) == 0:
+        raise ValueError("non-empty dict expected")
+
+    class Node(object):
+        # a Node object will have either .symbol or .child set below,
+        # .freq will always be set
+        def __lt__(self, other):
+            # heapq needs to be able to compare the nodes
+            return self.freq < other.freq
+
+    def huff_tree(freq_map):
+        # given a dictionary mapping symbols to thier frequency,
+        # construct a Huffman tree and return its root node
+
+        minheap = []
+        # create all the leaf nodes and push them onto the queue
+        for sym, f in freq_map.items():
+            nd = Node()
+            nd.symbol = sym
+            nd.freq = f
+            heapq.heappush(minheap, nd)
+
+        # repeat the process until only one node remains
+        while len(minheap) > 1:
+            # take the nodes with smallest frequencies from the queue
+            child_0 = heapq.heappop(minheap)
+            child_1 = heapq.heappop(minheap)
+            # construct the new internal node and push it onto the queue
+            parent = Node()
+            parent.child = [child_0, child_1]
+            parent.freq = child_0.freq + child_1.freq
+            heapq.heappush(minheap, parent)
+
+        # the single remaining node is the root of the Huffman tree
+        return minheap[0]
+
+    result = {}
+
+    def traverse(nd, prefix=bitarray(endian=endian)):
+        if hasattr(nd, 'symbol'):  # leaf
+            result[nd.symbol] = prefix
+        else:  # parent, so traverse each of the children
+            traverse(nd.child[0], prefix + bitarray([0]))
+            traverse(nd.child[1], prefix + bitarray([1]))
+
+    traverse(huff_tree(freq_map))
+    return result
diff --git a/shell/ext-py/bitarray-0.9.0/setup.py b/shell/ext-py/bitarray-1.2.1/setup.py
similarity index 86%
rename from shell/ext-py/bitarray-0.9.0/setup.py
rename to shell/ext-py/bitarray-1.2.1/setup.py
index 0473b1f..363be01 100644
--- a/shell/ext-py/bitarray-0.9.0/setup.py
+++ b/shell/ext-py/bitarray-1.2.1/setup.py
@@ -5,7 +5,7 @@ from distutils.core import setup, Extension
 
 kwds = {}
 try:
-    kwds['long_description'] = open('README.rst').read()
+    kwds['long_description'] = open('README.md').read()
 except IOError:
     pass
 
@@ -28,7 +28,6 @@ setup(
         "Operating System :: OS Independent",
         "Programming Language :: C",
         "Programming Language :: Python :: 2",
-        "Programming Language :: Python :: 2.5",
         "Programming Language :: Python :: 2.6",
         "Programming Language :: Python :: 2.7",
         "Programming Language :: Python :: 3",
@@ -37,11 +36,14 @@ setup(
         "Programming Language :: Python :: 3.5",
         "Programming Language :: Python :: 3.6",
         "Programming Language :: Python :: 3.7",
+        "Programming Language :: Python :: 3.8",
         "Topic :: Utilities",
     ],
     description = "efficient arrays of booleans -- C extension",
     packages = ["bitarray"],
     ext_modules = [Extension(name = "bitarray._bitarray",
-                             sources = ["bitarray/_bitarray.c"])],
+                             sources = ["bitarray/_bitarray.c"]),
+                   Extension(name = "bitarray._util",
+                             sources = ["bitarray/_util.c"])],
     **kwds
 )
diff --git a/shell/ext-py/bitarray-1.2.1/update_readme.py b/shell/ext-py/bitarray-1.2.1/update_readme.py
new file mode 100644
index 0000000..985597c
--- /dev/null
+++ b/shell/ext-py/bitarray-1.2.1/update_readme.py
@@ -0,0 +1,112 @@
+import sys
+if not sys.version_info[0] == 3:
+    sys.exit("This program only runs with Python 3, sorry :-(")
+
+import re
+import doctest
+from io import StringIO
+
+import bitarray
+import bitarray.util
+
+
+fo = StringIO()
+
+
+def write_changelog():
+    fo.write("Change log\n"
+             "----------\n\n")
+    ver_pat = re.compile(r'(\d{4}-\d{2}-\d{2})\s+(\d+\.\d+\.\d+)')
+    count = 0
+    for line in open('CHANGE_LOG'):
+        m = ver_pat.match(line)
+        if m:
+            if count == 3:
+                break
+            count += 1
+            fo.write(m.expand(r'*\2* (\1):\n'))
+        elif line.startswith('---'):
+            fo.write('\n')
+        else:
+            fo.write(line)
+
+    url = "https://github.com/ilanschnell/bitarray/blob/master/CHANGE_LOG"
+    fo.write('Please find the complete change log\n'
+             '<a href="%s">here</a>.\n' % url)
+
+
+sig_pat = re.compile(r'(\w+\([^()]*\))( -> (.+))?')
+def write_doc(name):
+    doc = eval('bitarray.%s.__doc__' % name)
+    lines = doc.splitlines()
+    m = sig_pat.match(lines[0])
+    if m is None:
+        raise Exception("signature line invalid: %r" % lines[0])
+    s = '`%s`' %  m.group(1)
+    if m.group(3):
+        s += ' -> %s' % m.group(3)
+    fo.write(s + '\n\n')
+    assert lines[1] == ''
+    for line in lines[2:]:
+        fo.write(line.rstrip() + '\n')
+    fo.write('\n\n')
+
+
+def write_reference():
+    fo.write("Reference\n"
+             "=========\n\n"
+             "The bitarray object:\n"
+             "--------------------\n\n")
+    write_doc('bitarray')
+
+    fo.write("**A bitarray object supports the following methods:**\n\n")
+    for method in sorted(dir(bitarray.bitarray)):
+        if method.startswith('_'):
+            continue
+        write_doc('bitarray.%s' % method)
+
+    fo.write("The frozenbitarray object:\n"
+             "--------------------------\n\n")
+    write_doc('frozenbitarray')
+
+    fo.write("Functions defined in the module:\n"
+             "--------------------------------\n\n")
+    write_doc('test')
+    write_doc('bitdiff')
+    write_doc('bits2bytes')
+
+    fo.write("Functions defined in bitarray.util:\n"
+             "-----------------------------------\n\n")
+    for func in bitarray.util.__all__:
+        write_doc('util.%s' % func)
+
+
+def write_all(data):
+    ver_pat = re.compile(r'(bitarray.+?)(\d+\.\d+\.\d+)')
+    for line in data.splitlines():
+        if line == 'Reference':
+            break
+        line = ver_pat.sub(lambda m: m.group(1) + bitarray.__version__, line)
+        fo.write(line + '\n')
+
+    write_reference()
+    write_changelog()
+
+
+def main():
+    data = open('README.md').read()
+    write_all(data)
+    new_data = fo.getvalue()
+    fo.close()
+
+    if new_data == data:
+        print("already up-to-date")
+    else:
+        with open('README.md', 'w') as f:
+            f.write(new_data)
+
+    doctest.testfile('README.md')
+
+
+if __name__ == '__main__':
+    main()
diff --git a/shell/packaging/requirements.txt b/shell/packaging/requirements.txt
index 84bfe80..00e7f3c 100644
--- a/shell/packaging/requirements.txt
+++ b/shell/packaging/requirements.txt
@@ -1,4 +1,4 @@
-bitarray==1.0.1
+bitarray==1.2.1
 configparser==4.0.2
 prettytable==0.7.2
 sasl==0.2.1