Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-bitarray for openSUSE:Factory 
checked in at 2026-06-22 17:44:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-bitarray (Old)
 and      /work/SRC/openSUSE:Factory/.python-bitarray.new.1956 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-bitarray"

Mon Jun 22 17:44:44 2026 rev:44 rq:1361123 version:3.8.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-bitarray/python-bitarray.changes  
2026-04-04 19:08:51.148655325 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-bitarray.new.1956/python-bitarray.changes    
    2026-06-22 17:45:14.478989227 +0200
@@ -1,0 +2,8 @@
+Sun Jun 21 18:18:53 UTC 2026 - Martin Hauke <[email protected]>
+
+- Update to version 3.8.2
+  * clarity/wording improvements throughout project.
+  * add 'new_allocation()' to simplify 'resize()'.
+  * drop Python 3.6 support.
+
+-------------------------------------------------------------------

Old:
----
  bitarray-3.8.1.tar.gz

New:
----
  bitarray-3.8.2.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-bitarray.spec ++++++
--- /var/tmp/diff_new_pack.XVNcb2/_old  2026-06-22 17:45:15.307018249 +0200
+++ /var/tmp/diff_new_pack.XVNcb2/_new  2026-06-22 17:45:15.307018249 +0200
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-bitarray
-Version:        3.8.1
+Version:        3.8.2
 Release:        0
 Summary:        Efficient Arrays of Booleans
 License:        Python-2.0

++++++ bitarray-3.8.1.tar.gz -> bitarray-3.8.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/CHANGE_LOG 
new/bitarray-3.8.2/CHANGE_LOG
--- old/bitarray-3.8.1/CHANGE_LOG       2026-04-02 17:13:02.000000000 +0200
+++ new/bitarray-3.8.2/CHANGE_LOG       2026-06-17 17:58:51.000000000 +0200
@@ -1,3 +1,10 @@
+2026-06-17   3.8.2:
+-------------------
+  * clarity/wording improvements throughout project
+  * add `new_allocation()` to simplify `resize()`
+  * drop Python 3.6 support
+
+
 2026-04-02   3.8.1:
 -------------------
   * fixed critial findings in C Extension Analysis Report, see #250
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/README.rst 
new/bitarray-3.8.2/README.rst
--- old/bitarray-3.8.1/README.rst       2026-04-02 17:13:02.000000000 +0200
+++ new/bitarray-3.8.2/README.rst       2026-06-17 17:58:51.000000000 +0200
@@ -57,7 +57,7 @@
 
     $ python -c 'import bitarray; bitarray.test()'
     bitarray is installed in: /Users/ilan/bitarray/bitarray
-    bitarray version: 3.8.1
+    bitarray version: 3.8.2
     sys.version: 3.13.5 (main, Jun 16 2025) [Clang 18.1.8]
     sys.prefix: /Users/ilan/miniforge
     pointer size: 64 bit
@@ -320,7 +320,7 @@
 Reference
 =========
 
-bitarray version: 3.8.1 -- `change log 
<https://github.com/ilanschnell/bitarray/blob/master/doc/changelog.rst>`__
+bitarray version: 3.8.2 -- `change log 
<https://github.com/ilanschnell/bitarray/blob/master/doc/changelog.rst>`__
 
 In the following, ``item`` and ``value`` are usually a single bit -
 an integer 0 or 1.
@@ -344,7 +344,7 @@
 
    ``endian``: Specifies the bit-endianness of the created bitarray object.
    Allowed values are ``big`` and ``little`` (the default is ``big``).
-   The bit-endianness effects the buffer representation of the bitarray.
+   The bit-endianness affects the buffer representation of the bitarray.
 
    ``buffer``: Any object which exposes a buffer.  When provided, 
``initializer``
    cannot be present (or has to be ``None``).  The imported buffer may be
@@ -439,7 +439,7 @@
 
 
 ``extend(iterable, /)``
-   Append items from to the end of the bitarray.
+   Append items from iterable to the end of the bitarray.
    If ``iterable`` is a (Unicode) string, each ``0`` and ``1`` are appended as
    bits (ignoring whitespace and underscore).
 
@@ -470,7 +470,7 @@
 
 ``fromfile(f, n=-1, /)``
    Extend bitarray with up to ``n`` bytes read from file object ``f`` (or any
-   other binary stream what supports a ``.read()`` method, e.g. 
``io.BytesIO``).
+   other binary stream that supports a ``.read()`` method, e.g. 
``io.BytesIO``).
    Each read byte will add eight bits to the bitarray.  When ``n`` is omitted
    or negative, reads and extends all data until EOF.
    When ``n`` is non-negative but exceeds the available data, ``EOFError`` is
@@ -490,8 +490,9 @@
 
 
 ``invert(index=<all bits>, /)``
-   Invert all bits in bitarray (in-place).
-   When the optional ``index`` is given, only invert the single bit at 
``index``.
+   Invert bits in-place.  When ``index`` is omitted, invert all bits.
+   When ``index`` is an integer, invert the single bit at index.
+   When ``index`` is a slice, invert the selected bits.
 
    New in version 1.5.3: optional index argument
 
@@ -574,7 +575,7 @@
 
 ``unpack(zero=b'\x00', one=b'\x01')`` -> bytes
    Return bytes that contain one byte for each bit in the bitarray,
-   using specified mapping.
+   using the specified mapping.
 
 
 bitarray data descriptors:
@@ -649,7 +650,8 @@
 ``ba2base(n, bitarray, /, group=0, sep=' ')`` -> str
    Return a string containing the base ``n`` ASCII representation of
    the bitarray.  Allowed values for ``n`` are 2, 4, 8, 16, 32 and 64.
-   The bitarray has to be multiple of length 1, 2, 3, 4, 5 or 6 respectively.
+   The bitarray has to have a length divisible by 1, 2, 3, 4, 5 or 6
+   respectively.
    For ``n=32`` the RFC 4648 Base32 alphabet is used, and for ``n=64`` the
    standard base 64 alphabet is used.
    When grouped, the string ``sep`` is inserted between groups
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/bitarray/_bitarray.c 
new/bitarray-3.8.2/bitarray/_bitarray.c
--- old/bitarray-3.8.1/bitarray/_bitarray.c     2026-04-02 17:13:02.000000000 
+0200
+++ new/bitarray-3.8.2/bitarray/_bitarray.c     2026-06-17 17:58:51.000000000 
+0200
@@ -24,6 +24,34 @@
 #define bitarray_Check(obj)  PyObject_TypeCheck((obj), &Bitarray_Type)
 
 
+static size_t
+new_allocation(size_t size, size_t allocated, size_t newsize)
+{
+    assert(allocated >= size);
+    assert(newsize > 0);
+
+    if (allocated >= newsize) {
+        /* current buffer is large enough to host the requested size */
+        if (newsize >= allocated / 2)
+            return allocated;  /* minor downsize - keep current allocation */
+
+        return newsize;  /* major downsize - shrink to exact size */
+    }
+    else {
+          /* need to grow buffer */
+          size_t new_alloc = newsize;
+          /* overallocate when previous size isn't zero and when growth
+             is moderate */
+          if (size != 0 && newsize / 2 <= allocated) {
+              /* overallocate proportional to the bitarray size and
+                 add padding to make the allocated size multiple of 4 */
+              new_alloc += (newsize >> 4) + (newsize < 8 ? 3 : 7);
+              new_alloc &= ~(size_t) 3;
+          }
+          return new_alloc;
+    }
+}
+
 static int
 resize(bitarrayobject *self, Py_ssize_t nbits)
 {
@@ -69,28 +97,13 @@
         return 0;
     }
 
-    if (allocated >= newsize) {
-        /* current buffer is large enough to host the requested size */
-        if (newsize >= allocated / 2) {
-            /* minor downsize, bypass reallocation */
-            Py_SET_SIZE(self, newsize);
-            self->nbits = nbits;
-            return 0;
-        }
-        /* major downsize, resize down to exact size */
-        new_allocated = newsize;
-    }
-    else {
-        /* need to grow buffer */
-        new_allocated = newsize;
-        /* overallocate when previous size isn't zero and when growth
-           is moderate */
-        if (size != 0 && newsize / 2 <= allocated) {
-            /* overallocate proportional to the bitarray size and
-               add padding to make the allocated size multiple of 4 */
-            new_allocated += (newsize >> 4) + (newsize < 8 ? 3 : 7);
-            new_allocated &= ~(size_t) 3;
-        }
+    new_allocated = new_allocation(size, allocated, newsize);
+
+    if (new_allocated == allocated) {
+        /* bypass reallocation */
+        Py_SET_SIZE(self, newsize);
+        self->nbits = nbits;
+        return 0;
     }
 
     assert(new_allocated >= newsize);
@@ -203,7 +216,7 @@
 /* The following two functions operate on first n bytes in buffer.
    Within this region, they shift all bits by k positions to right,
    i.e. towards higher addresses.
-   They operate on little-endian and bit-endian bitarrays respectively.
+   They operate on little-endian and big-endian bitarrays respectively.
    As we shift right, we need to start with the highest address and loop
    downwards such that lower bytes are still unaltered.
    See also devel/shift_r8.c
@@ -1194,7 +1207,7 @@
 PyDoc_STRVAR(extend_doc,
 "extend(iterable, /)\n\
 \n\
-Append items from to the end of the bitarray.\n\
+Append items from iterable to the end of the bitarray.\n\
 If `iterable` is a (Unicode) string, each `0` and `1` are appended as\n\
 bits (ignoring whitespace and underscore).");
 
@@ -1346,7 +1359,8 @@
         invert_span(self, 0, self->nbits);
     }
     else {
-        return PyErr_Format(PyExc_TypeError, "index expect, not '%s' object",
+        return PyErr_Format(PyExc_TypeError,
+                            "index expected, not '%s' object",
                             Py_TYPE(arg)->tp_name);
     }
     Py_RETURN_NONE;
@@ -1355,8 +1369,9 @@
 PyDoc_STRVAR(invert_doc,
 "invert(index=<all bits>, /)\n\
 \n\
-Invert all bits in bitarray (in-place).\n\
-When the optional `index` is given, only invert the single bit at `index`.");
+Invert bits in-place.  When `index` is omitted, invert all bits.\n\
+When `index` is an integer, invert the single bit at index.\n\
+When `index` is a slice, invert the selected bits.");
 
 
 static PyObject *
@@ -1557,7 +1572,7 @@
     assert(Py_SIZE(self) == n + view.len);
     memcpy(self->ob_item + n, (char *) view.buf, (size_t) view.len);
 
-    /* remove pad bits staring at previous bit length (8 * n - p) */
+    /* remove pad bits starting at previous bit length (8 * n - p) */
     if (delete_n(self, 8 * n - p, p) < 0)
         goto error;
 
@@ -1654,7 +1669,7 @@
 "fromfile(f, n=-1, /)\n\
 \n\
 Extend bitarray with up to `n` bytes read from file object `f` (or any\n\
-other binary stream what supports a `.read()` method, e.g. `io.BytesIO`).\n\
+other binary stream that supports a `.read()` method, e.g. `io.BytesIO`).\n\
 Each read byte will add eight bits to the bitarray.  When `n` is omitted\n\
 or negative, reads and extends all data until EOF.\n\
 When `n` is non-negative but exceeds the available data, `EOFError` is\n\
@@ -1673,7 +1688,7 @@
         Py_ssize_t size = Py_MIN(nbytes - offset, BLOCKSIZE);
 
         assert(size >= 0 && offset + size <= nbytes);
-        /* basically: f.write(memoryview(self)[offset:offset + size] */
+        /* basically: f.write(memoryview(self)[offset:offset + size]) */
         ret = PyObject_CallMethod(f, "write", "y#",
                                   self->ob_item + offset, size);
         if (ret == NULL)
@@ -1763,7 +1778,7 @@
 "unpack(zero=b'\\x00', one=b'\\x01') -> bytes\n\
 \n\
 Return bytes that contain one byte for each bit in the bitarray,\n\
-using specified mapping.");
+using the specified mapping.");
 
 
 static PyObject *
@@ -3167,7 +3182,7 @@
 "complete() -> bool\n\
 \n\
 Return whether tree is complete.  That is, whether or not all\n\
-nodes have both children (unless they are symbols nodes).");
+nodes have both children (unless they are symbol nodes).");
 
 
 static PyObject *
@@ -3332,7 +3347,7 @@
     PyObject *symbol;
 
     symbol = binode_traverse(it->tree, it->self, &(it->index));
-    if (symbol == NULL)  /* stop iteration OR error occured */
+    if (symbol == NULL)  /* stop iteration OR error occurred */
         return NULL;
     Py_INCREF(symbol);
     return symbol;
@@ -3723,9 +3738,9 @@
 }
 
 /* As of bitarray version 2.9.0, "bitarray(nbits)" will initialize all items
-   to 0 (previously, the buffer was be uninitialized).
+   to 0 (previously, the buffer was uninitialized).
    However, for speed, one might want to create an uninitialized bitarray.
-   In 2.9.1, we added the ability to created uninitialized bitarrays again,
+   In 2.9.1, we added the ability to create uninitialized bitarrays again,
    using "bitarray(nbits, endian, Ellipsis)".
 */
 static PyObject *
@@ -4003,7 +4018,7 @@
 \n\
 `endian`: Specifies the bit-endianness of the created bitarray object.\n\
 Allowed values are `big` and `little` (the default is `big`).\n\
-The bit-endianness effects the buffer representation of the bitarray.\n\
+The bit-endianness affects the buffer representation of the bitarray.\n\
 \n\
 `buffer`: Any object which exposes a buffer.  When provided, `initializer`\n\
 cannot be present (or has to be `None`).  The imported buffer may be\n\
@@ -4203,7 +4218,7 @@
 PyDoc_STRVAR(sysinfo_doc,
 "_sysinfo(key) -> int\n\
 \n\
-Return system and compile specific information given a key.");
+Return system- and compile-specific information given a key.");
 
 
 static PyMethodDef module_functions[] = {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/bitarray/_util.c 
new/bitarray-3.8.2/bitarray/_util.c
--- old/bitarray-3.8.1/bitarray/_util.c 2026-04-02 17:13:02.000000000 +0200
+++ new/bitarray-3.8.2/bitarray/_util.c 2026-06-17 17:58:51.000000000 +0200
@@ -31,7 +31,7 @@
 
 /* Return new bitarray of length 'nbits', endianness given by the PyObject
    'endian' (which may be Py_None).
-   Unless -1, 'c' is placed into all characters of buffer. */
+   Unless -1, 'c' is written to all bytes of the buffer. */
 static bitarrayobject *
 new_bitarray(Py_ssize_t nbits, PyObject *endian, int c)
 {
@@ -494,7 +494,7 @@
         v = zlw(b);
         not_u = ~u;
         not_v = ~v;
-        /* for nff we need to substract the number of unused 1 bits */
+        /* for nff we need to subtract the number of unused 1 bits */
         nff += popcnt_64(not_u & not_v) - (64 - rbits);
         nft += popcnt_64(not_u & v);
         ntf += popcnt_64(u & not_v);
@@ -552,7 +552,7 @@
 
     if (n < 0)
         return PyErr_Format(PyExc_ValueError,
-                            "positive int expect, got %zd", n);
+                            "positive int expected, got %zd", n);
 
     if (PyObject_GetBuffer(buffer, &view, PyBUF_SIMPLE | PyBUF_WRITABLE) < 0)
         return NULL;
@@ -839,7 +839,7 @@
     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
 /* Given the length of the base m in [1..6] and a character c, return
-   its index in the base 2**m alphabet , or -1 if when c is not included.
+   its index in the base 2**m alphabet, or -1 if c is not included.
    Note: i >> m is true when i is not in range(0, 2**m) */
 static int
 digit_to_int(int m, char c)
@@ -981,7 +981,8 @@
 \n\
 Return a string containing the base `n` ASCII representation of\n\
 the bitarray.  Allowed values for `n` are 2, 4, 8, 16, 32 and 64.\n\
-The bitarray has to be multiple of length 1, 2, 3, 4, 5 or 6 respectively.\n\
+The bitarray has to have a length divisible by 1, 2, 3, 4, 5 or 6\n\
+respectively.\n\
 For `n=32` the RFC 4648 Base32 alphabet is used, and for `n=64` the\n\
 standard base 64 alphabet is used.\n\
 When grouped, the string `sep` is inserted between groups\n\
@@ -1200,7 +1201,7 @@
      * The last element rts[NSEG(self)] is always the total count.
        Here: rts[NSEG(self)] = rts[4] = 12
 
-     * The last segment may be partial.  In that case, its size it given
+     * The last segment may be partial.  In that case, its size is given
        by nbits % 256.  Here: nbits % 256 = 987 % 256 = 219
 
    As each segment (at large) covers 256 bits (32 bytes), and each element
@@ -1284,7 +1285,7 @@
 
       a.count(1, 8 * offset, 8 * offset + (1 << (8 * n)))
 
-   The offset must be divisible by SEGSIZE, as this functions makes use of
+   The offset must be divisible by SEGSIZE, as this function makes use of
    running totals, stored in rts[].
    Here, and in the following, 'offset' is in units of bytes. */
 static Py_ssize_t
@@ -1301,7 +1302,7 @@
 /* Write a raw block, and return number of bytes copied.
    Note that the encoded block size is the return value + 1 (the head byte).
 
-   The header byte is in range(0x01, 0xa0).
+   The head byte is in range(0x01, 0xa0).
      * range(0x01, 0x20) number of raw bytes
      * range(0x20, 0xa0) number of 32-byte segments */
 static int
@@ -1341,7 +1342,6 @@
 sc_write_indices(char *str, bitarrayobject *a, Py_ssize_t *rts,
                  Py_ssize_t offset, int n, int k)
 {
-    const char *str_stop = str + n * k;  /* stop position in buffer 'str' */
     const char *buff = a->ob_item + offset;
     Py_ssize_t m;
 
@@ -1370,12 +1370,13 @@
                 if (buff[i] & BITMASK(a, j)) {
                     write_n(str, n, 8 * i + j);
                     str += n;
-                    if (--ni == 0) {
+                    if (--k == 0)
+                        /* we have encountered all indices in this block */
+                        return;
+
+                    if (--ni == 0)
                         /* we have encountered all indices in this segment */
-                        if (str == str_stop)
-                            return;
                         goto next_segment;
-                    }
                 }
             }
         }
@@ -1407,7 +1408,7 @@
         str[len++] = (char) (0xc0 + n);  /* block type */
         str[len++] = (char) k;           /* index count */
     }
-    if (k == 0)  /* no index bytes - sc_write_sparse() does not allow k = 0 */
+    if (k == 0)  /* no index bytes to write */
         return len;
 
     /* write block data - k indices, n bytes per index */
@@ -1423,7 +1424,7 @@
 
    - 32 index bytes take up as much space as a raw buffer of 32 bytes.
      Hence, if the bit count of the first 32 bytes of the bitarray buffer
-     is greater or equal to 32, we choose a raw block (type 0).
+     is greater than or equal to 32, we choose a raw block (type 0).
 
    - Arguably, n index bytes always take up as much space as n raw bytes.
      So what makes 32 special here?  A bitarray with a 32 byte buffer has
@@ -1459,7 +1460,7 @@
 
              header_size   +   (n + 1)  *  population
 
-         As n >= 1, the header_size will is always 2 bytes here.
+         As n >= 1, the header_size is always 2 bytes here.
 
    - As we only need to know which of these sizes is bigger, we can
      subtract (n * population) from both sizes.  Hence, the costs are:
@@ -1480,7 +1481,7 @@
     assert(nbytes > 0);
 
     count = (int) sc_count(a, rts, offset, 1);
-    /* the number of index bytes exceeds the number of raw bytes */
+    /* the number of index bytes is no smaller than the number of raw bytes */
     if (count >= Py_MIN(32, nbytes)) {           /* type 0 - raw bytes */
         int k = sc_write_raw(str + *len, a, rts, offset);
         *len += 1 + k;
@@ -1515,7 +1516,7 @@
     return BSI(n);
 }
 
-/* write header and return number or bytes written to buffer 'str' */
+/* write header and return number of bytes written to buffer 'str' */
 static int
 sc_encode_header(char *str, bitarrayobject *a)
 {
@@ -1565,7 +1566,7 @@
 
         /* Make sure we have enough memory in output buffer for next block.
            The largest block possible is a type 0 block with 128 segments.
-           Its size is: 1 head bytes + 128 * 32 raw bytes.
+           Its size is: 1 head byte + 128 * 32 raw bytes.
            Plus, we also may have the stop byte. */
         if (allocated < len + 1 + 128 * 32 + 1) {
             if (_PyBytes_Resize(&out, allocated + ALLOC_SIZE) < 0)
@@ -1597,7 +1598,7 @@
 
 
 /* read header from 'iter' and set 'endian' and 'nbits', return 0 on success
-   and -1 of failure (after setting exception) */
+   and -1 on failure (after setting exception) */
 static int
 sc_decode_header(PyObject *iter, int *endian, Py_ssize_t *nbits)
 {
@@ -1759,12 +1760,12 @@
    'padding' refers to the pad bits within the variable length format.
    This is not the same as the pad bits of the actual bitarray.
    For example, b'\x10' has padding = 1, and decodes to bitarray('000'),
-   which has 5 pad bits.  'padding' can take values to up 6.
+   which has 5 pad bits.  'padding' can take values up to 6.
  */
 #define LEN_PAD_BITS  3
 
 /* initial number of bits we allocate in vl_decode(), and amount by which
-   we increase our allocation by in vl_decode_core() if we run out */
+   we increase the allocation in vl_decode_core() */
 #define ALLOC_BITS  1024
 
 /* Consume 'iter' while extending bitarray 'a'.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/bitarray/bitarray.h 
new/bitarray-3.8.2/bitarray/bitarray.h
--- old/bitarray-3.8.1/bitarray/bitarray.h      2026-04-02 17:13:02.000000000 
+0200
+++ new/bitarray-3.8.2/bitarray/bitarray.h      2026-06-17 17:58:51.000000000 
+0200
@@ -4,7 +4,7 @@
 
    Author: Ilan Schnell
 */
-#define BITARRAY_VERSION  "3.8.1"
+#define BITARRAY_VERSION  "3.8.2"
 
 #ifdef STDC_HEADERS
 #  include <stddef.h>
@@ -64,7 +64,7 @@
 /* number of pad bits */
 #define PADBITS(self)  ((8 - (self)->nbits % 8) % 8)
 
-/* number of bytes necessary to store given nunmber of bits */
+/* number of bytes necessary to store given number of bits */
 #define BYTES(bits)  (((bits) + 7) >> 3)
 
 /* we're not using bitmask_table here, as it is actually slower */
@@ -268,7 +268,7 @@
     return (4 - r) % 4;
 }
 
-/* population count of n words starting from at uint64_t pointer w */
+/* population count of n words starting at uint64_t pointer w */
 static inline Py_ssize_t
 popcnt_words(uint64_t *w, Py_ssize_t n)
 {
@@ -301,7 +301,7 @@
     assert(*step != 1 || slicelength == 0 || *stop - *start == slicelength);
 }
 
-/* convert Python object to C int and set value at address -
+/* convert Python object to C int at address *vi -
    return 1 on success, 0 on failure (and set exception) */
 static inline int
 conv_pybit(PyObject *value, int *vi)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/bitarray/pythoncapi_compat.h 
new/bitarray-3.8.2/bitarray/pythoncapi_compat.h
--- old/bitarray-3.8.1/bitarray/pythoncapi_compat.h     2026-04-02 
17:13:02.000000000 +0200
+++ new/bitarray-3.8.2/bitarray/pythoncapi_compat.h     2026-06-17 
17:58:51.000000000 +0200
@@ -25,9 +25,6 @@
 #if PY_VERSION_HEX < 0x030b00B4 && !defined(PYPY_VERSION)
 #  include "frameobject.h"        // PyFrameObject, PyFrame_GetBack()
 #endif
-#if PY_VERSION_HEX < 0x030C00A3
-#  include <structmember.h>       // T_SHORT, READONLY
-#endif
 
 
 #ifndef _Py_CAST
@@ -1428,6 +1425,11 @@
 static inline int
 PyUnicodeWriter_WriteRepr(PyUnicodeWriter *writer, PyObject *obj)
 {
+    if (obj == NULL) {
+        return _PyUnicodeWriter_WriteASCIIString((_PyUnicodeWriter*)writer,
+                                                 "<NULL>", 6);
+    }
+
     PyObject *str = PyObject_Repr(obj);
     if (str == NULL) {
         return -1;
@@ -1572,6 +1574,11 @@
 
 // gh-124502 added PyUnicode_Equal() to Python 3.14.0a0
 #if PY_VERSION_HEX < 0x030E00A0
+
+#if PY_VERSION_HEX >= 0x030d0000 && !defined(PYPY_VERSION)
+PyAPI_FUNC(int) _PyUnicode_Equal(PyObject *str1, PyObject *str2);
+#endif
+
 static inline int PyUnicode_Equal(PyObject *str1, PyObject *str2)
 {
     if (!PyUnicode_Check(str1)) {
@@ -1586,8 +1593,6 @@
     }
 
 #if PY_VERSION_HEX >= 0x030d0000 && !defined(PYPY_VERSION)
-    PyAPI_FUNC(int) _PyUnicode_Equal(PyObject *str1, PyObject *str2);
-
     return _PyUnicode_Equal(str1, str2);
 #elif PY_VERSION_HEX >= 0x03060000 && !defined(PYPY_VERSION)
     return _PyUnicode_EQ(str1, str2);
@@ -1610,11 +1615,14 @@
 
 
 #if PY_VERSION_HEX < 0x030E00A0
+
+#if PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION)
+PyAPI_FUNC(Py_hash_t) _Py_HashBytes(const void *src, Py_ssize_t len);
+#endif
+
 static inline Py_hash_t Py_HashBuffer(const void *ptr, Py_ssize_t len)
 {
 #if PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION)
-    PyAPI_FUNC(Py_hash_t) _Py_HashBytes(const void *src, Py_ssize_t len);
-
     return _Py_HashBytes(ptr, len);
 #else
     Py_hash_t hash;
@@ -1919,43 +1927,46 @@
 
 
 #if PY_VERSION_HEX < 0x030C00A3
-#  define Py_T_SHORT      T_SHORT
-#  define Py_T_INT        T_INT
-#  define Py_T_LONG       T_LONG
-#  define Py_T_FLOAT      T_FLOAT
-#  define Py_T_DOUBLE     T_DOUBLE
-#  define Py_T_STRING     T_STRING
-#  define _Py_T_OBJECT    T_OBJECT
-#  define Py_T_CHAR       T_CHAR
-#  define Py_T_BYTE       T_BYTE
-#  define Py_T_UBYTE      T_UBYTE
-#  define Py_T_USHORT     T_USHORT
-#  define Py_T_UINT       T_UINT
-#  define Py_T_ULONG      T_ULONG
-#  define Py_T_STRING_INPLACE  T_STRING_INPLACE
-#  define Py_T_BOOL       T_BOOL
-#  define Py_T_OBJECT_EX  T_OBJECT_EX
-#  define Py_T_LONGLONG   T_LONGLONG
-#  define Py_T_ULONGLONG  T_ULONGLONG
-#  define Py_T_PYSSIZET   T_PYSSIZET
+#  define Py_T_SHORT      0
+#  define Py_T_INT        1
+#  define Py_T_LONG       2
+#  define Py_T_FLOAT      3
+#  define Py_T_DOUBLE     4
+#  define Py_T_STRING     5
+#  define _Py_T_OBJECT    6
+#  define Py_T_CHAR       7
+#  define Py_T_BYTE       8
+#  define Py_T_UBYTE      9
+#  define Py_T_USHORT     10
+#  define Py_T_UINT       11
+#  define Py_T_ULONG      12
+#  define Py_T_STRING_INPLACE  13
+#  define Py_T_BOOL       14
+#  define Py_T_OBJECT_EX  16
+#  define Py_T_LONGLONG   17
+#  define Py_T_ULONGLONG  18
+#  define Py_T_PYSSIZET   19
 
 #  if PY_VERSION_HEX >= 0x03000000 && !defined(PYPY_VERSION)
-#    define _Py_T_NONE      T_NONE
+#    define _Py_T_NONE      20
 #  endif
 
-#  define Py_READONLY            READONLY
-#  define Py_AUDIT_READ          READ_RESTRICTED
-#  define _Py_WRITE_RESTRICTED   PY_WRITE_RESTRICTED
+#  define Py_READONLY            1
+#  define Py_AUDIT_READ          2
+#  define _Py_WRITE_RESTRICTED   4
 #endif
 
 
 // gh-127350 added Py_fopen() and Py_fclose() to Python 3.14a4
 #if PY_VERSION_HEX < 0x030E00A4
+
+#if 0x030400A2 <= PY_VERSION_HEX && !defined(PYPY_VERSION)
+PyAPI_FUNC(FILE*) _Py_fopen_obj(PyObject *path, const char *mode);
+#endif
+
 static inline FILE* Py_fopen(PyObject *path, const char *mode)
 {
 #if 0x030400A2 <= PY_VERSION_HEX && !defined(PYPY_VERSION)
-    PyAPI_FUNC(FILE*) _Py_fopen_obj(PyObject *path, const char *mode);
-
     return _Py_fopen_obj(path, mode);
 #else
     FILE *f;
@@ -1992,6 +2003,8 @@
 
 
 #if 0x03080000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030E0000 && 
!defined(PYPY_VERSION)
+PyAPI_FUNC(const PyConfig*) _Py_GetConfig(void);
+
 static inline PyObject*
 PyConfig_Get(const char *name)
 {
@@ -2127,8 +2140,6 @@
             return Py_NewRef(value);
         }
 
-        PyAPI_FUNC(const PyConfig*) _Py_GetConfig(void);
-
         const PyConfig *config = _Py_GetConfig();
         void *member = (char *)config + spec->offset;
         switch (spec->type) {
@@ -2231,6 +2242,81 @@
 }
 #endif
 
+// gh-128926 added PyUnstable_TryIncRef() and PyUnstable_EnableTryIncRef() to
+// Python 3.14.0a5. Adapted from _Py_TryIncref() and 
_PyObject_SetMaybeWeakref().
+#if PY_VERSION_HEX < 0x030E00A5
+static inline int PyUnstable_TryIncRef(PyObject *op)
+{
+#ifndef Py_GIL_DISABLED
+    if (Py_REFCNT(op) > 0) {
+        Py_INCREF(op);
+        return 1;
+    }
+    return 0;
+#else
+    // _Py_TryIncrefFast()
+    uint32_t local = _Py_atomic_load_uint32_relaxed(&op->ob_ref_local);
+    local += 1;
+    if (local == 0) {
+        // immortal
+        return 1;
+    }
+    if (_Py_IsOwnedByCurrentThread(op)) {
+        _Py_INCREF_STAT_INC();
+        _Py_atomic_store_uint32_relaxed(&op->ob_ref_local, local);
+#ifdef Py_REF_DEBUG
+        _Py_INCREF_IncRefTotal();
+#endif
+        return 1;
+    }
+
+    // _Py_TryIncRefShared()
+    Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&op->ob_ref_shared);
+    for (;;) {
+        // If the shared refcount is zero and the object is either merged
+        // or may not have weak references, then we cannot incref it.
+        if (shared == 0 || shared == _Py_REF_MERGED) {
+            return 0;
+        }
+
+        if (_Py_atomic_compare_exchange_ssize(
+                &op->ob_ref_shared,
+                &shared,
+                shared + (1 << _Py_REF_SHARED_SHIFT))) {
+#ifdef Py_REF_DEBUG
+            _Py_INCREF_IncRefTotal();
+#endif
+            _Py_INCREF_STAT_INC();
+            return 1;
+        }
+    }
+#endif
+}
+
+static inline void PyUnstable_EnableTryIncRef(PyObject *op)
+{
+#ifdef Py_GIL_DISABLED
+    // _PyObject_SetMaybeWeakref()
+    if (_Py_IsImmortal(op)) {
+        return;
+    }
+    for (;;) {
+        Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&op->ob_ref_shared);
+        if ((shared & _Py_REF_SHARED_FLAG_MASK) != 0) {
+            // Nothing to do if it's in WEAKREFS, QUEUED, or MERGED states.
+            return;
+        }
+        if (_Py_atomic_compare_exchange_ssize(
+                &op->ob_ref_shared, &shared, shared | _Py_REF_MAYBE_WEAKREF)) {
+            return;
+        }
+    }
+#else
+    (void)op;  // unused argument
+#endif
+}
+#endif
+
 
 #if PY_VERSION_HEX < 0x030F0000
 static inline PyObject*
@@ -2587,6 +2673,40 @@
 }
 #endif
 
+#if 0x030D0000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030F00A7 && 
!defined(PYPY_VERSION)
+// Immortal objects were implemented in Python 3.12, however there is no easy 
API
+// to make objects immortal until 3.14 which has _Py_SetImmortal(). Since
+// immortal objects are primarily needed for free-threading, this API is 
implemented
+// for 3.14 using _Py_SetImmortal() and uses private macros on 3.13.
+#if 0x030E0000 <= PY_VERSION_HEX
+PyAPI_FUNC(void) _Py_SetImmortal(PyObject *op);
+#endif
+
+static inline int
+PyUnstable_SetImmortal(PyObject *op)
+{
+    assert(op != NULL);
+    if (!PyUnstable_Object_IsUniquelyReferenced(op) || PyUnicode_Check(op)) {
+        return 0;
+    }
+#if 0x030E0000 <= PY_VERSION_HEX
+    _Py_SetImmortal(op);
+#else
+    // Python 3.13 doesn't export _Py_SetImmortal() function
+    if (PyObject_GC_IsTracked(op)) {
+        PyObject_GC_UnTrack(op);
+    }
+#ifdef Py_GIL_DISABLED
+    op->ob_tid = _Py_UNOWNED_TID;
+    op->ob_ref_local = _Py_IMMORTAL_REFCNT_LOCAL;
+    op->ob_ref_shared = 0;
+#else
+    op->ob_refcnt = _Py_IMMORTAL_REFCNT;
+#endif
+#endif
+    return 1;
+}
+#endif
 
 #ifdef __cplusplus
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/bitarray/util.py 
new/bitarray-3.8.2/bitarray/util.py
--- old/bitarray-3.8.1/bitarray/util.py 2026-04-02 17:13:02.000000000 +0200
+++ new/bitarray-3.8.2/bitarray/util.py 2026-06-17 17:58:51.000000000 +0200
@@ -179,13 +179,13 @@
             diff = a.count() - k
 
         randrange = random.randrange
-        if diff < 0:  # not enough bits 1 - increase count
+        if diff < 0:  # not enough 1 bits - increase count
             for _ in range(-diff):
                 i = randrange(n)
                 while a[i]:
                     i = randrange(n)
                 a[i] = 1
-        elif diff > 0:  # too many bits 1 - decrease count
+        elif diff > 0:  # too many 1 bits - decrease count
             for _ in range(diff):
                 i = randrange(n)
                 while not a[i]:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/devel/resize/resize.c 
new/bitarray-3.8.2/devel/resize/resize.c
--- old/bitarray-3.8.1/devel/resize/resize.c    2026-04-02 17:13:02.000000000 
+0200
+++ new/bitarray-3.8.2/devel/resize/resize.c    2026-06-17 17:58:51.000000000 
+0200
@@ -3,9 +3,9 @@
 
 
 typedef struct {
-    int size;
-    int nbits;
-    int allocated;
+    size_t size;
+    size_t nbits;
+    size_t allocated;
 } bitarrayobject;
 
 
@@ -21,10 +21,34 @@
     return s % 8000;
 }
 
-void resize(bitarrayobject *self, int nbits)
+size_t new_allocation(size_t size, size_t allocated, size_t newsize)
 {
-    int size = self->size, allocated = self->allocated;
-    int newsize = BYTES(nbits), new_allocated;
+    if (allocated >= newsize) {
+        /* current buffer is large enough to host the requested size */
+        if (newsize >= allocated / 2)
+            return allocated;  /* minor downsize - keep current allocation */
+
+        return newsize;  /* major downsize - shrink to exact size */
+    }
+    else {
+          /* need to grow buffer */
+          size_t new_alloc = newsize;
+          /* overallocate when previous size isn't zero and when growth
+             is moderate */
+          if (size != 0 && newsize / 2 <= allocated) {
+              /* overallocate proportional to the bitarray size and
+                 add padding to make the allocated size multiple of 4 */
+              new_alloc += (newsize >> 4) + (newsize < 8 ? 3 : 7);
+              new_alloc &= ~(size_t) 3;
+          }
+          return new_alloc;
+    }
+}
+
+void resize(bitarrayobject *self, size_t nbits)
+{
+    size_t size = self->size, allocated = self->allocated;
+    size_t newsize = BYTES(nbits), new_allocated;
 
     if (newsize == size) {
         self->nbits = nbits;
@@ -39,20 +63,13 @@
         return;
     }
 
-    if (allocated >= newsize) {
-        if (newsize >= allocated / 2) {
-            self->size = newsize;
-            self->nbits = nbits;
-            return;
-        }
-        new_allocated = newsize;
-    }
-    else {
-        new_allocated = newsize;
-        if (size != 0 && newsize / 2 <= allocated) {
-            new_allocated += (newsize >> 4) + (newsize < 8 ? 3 : 7);
-            new_allocated &= ~(int) 3;
-        }
+    new_allocated = new_allocation(size, allocated, newsize);
+
+    if (new_allocated == allocated) {
+        /* bypass reallocation */
+        self->size = newsize;
+        self->nbits = nbits;
+        return;
     }
 
     /* realloc(self->ob_item) */
@@ -67,7 +84,7 @@
     int i, nbits, prev_alloc = -1;
     bitarrayobject x;
 
-#define SHOW  printf("%d  %d\n", x.size, x.allocated)
+#define SHOW  printf("%lu  %lu\n", x.size, x.allocated)
 
     x.size = 0;
     x.allocated = 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/devel/sc/notes.txt 
new/bitarray-3.8.2/devel/sc/notes.txt
--- old/bitarray-3.8.1/devel/sc/notes.txt       1970-01-01 01:00:00.000000000 
+0100
+++ new/bitarray-3.8.2/devel/sc/notes.txt       2026-06-17 17:58:51.000000000 
+0200
@@ -0,0 +1,21 @@
+The correspondence between bytecode and the sc format is unusually clean:
+
+instruction byte     -> block head
+opcode               -> block type
+instruction operands -> count and indices, or raw bytes
+machine state        -> current output position / output bitarray
+halt instruction     -> stop byte 0x00
+
+And like a bytecode interpreter, the decoder trusts the instruction stream
+only conditionally: it validates block heads, lengths, and index bounds as
+it executes.
+
+The encoder is then analogous to a tiny compiler or optimizer: inspect
+the source bitarray, calculate representation costs, and emit an efficient
+instruction stream for the decoder to execute.
+
+That is a nice way to teach the format because it makes
+the asymmetry intuitive:
+
+sc_encode() -> planner / compiler
+sc_decode() -> interpreter / virtual machine
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/devel/test_debug.py 
new/bitarray-3.8.2/devel/test_debug.py
--- old/bitarray-3.8.1/devel/test_debug.py      2026-04-02 17:13:02.000000000 
+0200
+++ new/bitarray-3.8.2/devel/test_debug.py      2026-06-17 17:58:51.000000000 
+0200
@@ -125,6 +125,8 @@
         for n in range(200):
             a = ones(n, self.random_endian())
             b = _zlw(a)
+            self.assertEqual(len(b), 64)
+            self.assertEqual(b.endian, a.endian)
             r = n % 64
             self.assertEqual(b, ones(r) + zeros(64 - r))
 
@@ -347,8 +349,7 @@
             n = randrange(1024)
             a = urandom_2(n)
             i = randrange(20)
-            res = _cfw(a, i)
-            self.assertEqual(res, a[64 * i:].count())
+            self.assertEqual(_cfw(a, i), a[64 * i:].count())
 
 
 class DigitToInt_Tests(unittest.TestCase):
@@ -397,7 +398,7 @@
     def test_example(self):
         # see example before sc_calc_rts() in _util.c
         a = zeros(987)
-        a[:5] = a[512:515] = a[768:772] = 1
+        a[[0, 17, 31, 149, 255, 512, 637, 767, 768, 813, 899, 986]] = 1
         self.assertEqual(a.count(), 12)
         rts = _sc_rts(a)
         self.assertEqual(type(rts), list)
@@ -426,8 +427,8 @@
             self.assertEqual(rts[0], 0)
             self.assertEqual(rts[-1], a.count())
             for i in range(self.nseg(a)):
-                seg_pop = a.count(1, SEGBITS * i, SEGBITS * (i + 1))
-                self.assertEqual(rts[i + 1] - rts[i], seg_pop)
+                self.assertEqual(rts[i + 1] - rts[i],
+                                 a.count(1, SEGBITS * i, SEGBITS * (i + 1)))
 
 
 class ReadN_WriteN_Tests(unittest.TestCase, Util):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/doc/bitarray3.rst 
new/bitarray-3.8.2/doc/bitarray3.rst
--- old/bitarray-3.8.1/doc/bitarray3.rst        2026-04-02 17:13:02.000000000 
+0200
+++ new/bitarray-3.8.2/doc/bitarray3.rst        2026-06-17 17:58:51.000000000 
+0200
@@ -7,21 +7,21 @@
 This is similar to how Python's ``dict.keys()``, ``.values()``
 and ``.items()`` methods were revamped in the Python 2 to 3 transition.
 
-In the following table, ``a`` is assumed to a bitarray object.
+In the following table, ``a`` is assumed to be a bitarray object.
 
 +----------------------+----------------------+
 | before version 3     | version 3            |
 +======================+======================+
 | ``a.iterdecode()``   | ``a.decode()``       |
 +----------------------+----------------------+
-| ``a.decode()``       | ``list(a.decode()``  |
+| ``a.decode()``       | ``list(a.decode())`` |
 +----------------------+----------------------+
 | ``a.itersearch()``   | ``a.search()``       |
 +----------------------+----------------------+
-| ``a.search()``       | ``list(a.search()``  |
+| ``a.search()``       | ``list(a.search())`` |
 +----------------------+----------------------+
 
-Aside from these changes which will make bitarray 3 more pythonic, there
+Aside from these changes, which will make bitarray 3 more pythonic, there
 are a few other minor changes (see changelog).
 It should be emphasized that in most common use cases the bitarray 3
 transition will require only minor code changes, or no changes at all.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/doc/buffer.rst 
new/bitarray-3.8.2/doc/buffer.rst
--- old/bitarray-3.8.1/doc/buffer.rst   2026-04-02 17:13:02.000000000 +0200
+++ new/bitarray-3.8.2/doc/buffer.rst   2026-06-17 17:58:51.000000000 +0200
@@ -58,7 +58,7 @@
 -----------------
 
 As of bitarray version 2.3, it is also possible to import the buffer
-from an object which exposes its buffer.  Here the bytearray:
+from an object that exposes its buffer.  Here a ``bytearray`` object:
 
 .. code-block:: python
 
@@ -73,9 +73,9 @@
     >>> a
     bitarray('000011111111100000001111')
 
-Again, the shared buffer can be represented and modify by either object ``a``
-and ``c``.  When importing a buffer into a bitarray, the length of the
-bitarray will always be multiple of 8 bits, as buffers are bases on bytes.
+Again, the shared buffer can be represented and modified by either object
+``a`` or ``c``.  When importing a buffer into a bitarray, the length of the
+bitarray will always be a multiple of 8 bits, as buffers are based on bytes.
 Also, we may specify the endianness of the bitarray:
 
 .. code-block:: python
@@ -86,7 +86,7 @@
 
 The bytearray ``c`` is now exporting its buffer twice:
 to big-endian bitarray ``a``, and a little-endian bitarray ``b``.
-At this point all three object ``a``, ``b`` and ``c`` share the same buffer.
+At this point all three objects ``a``, ``b`` and ``c`` share the same buffer.
 Using the ``.buffer_info()`` method, we can actually verify that the
 bitarrays ``a`` and ``b`` point to the same address:
 
@@ -97,7 +97,7 @@
     ...     return info[0]  # using bitarray 3.7, we can also: info.address
     >>> assert address(a) == address(b)
 
-As bitarray's expose their buffer, we can also directly create a bitarray
+As bitarrays expose their buffer, we can also directly create a bitarray
 which imports the buffer from another bitarray:
 
 .. code-block:: python
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/doc/canonical.rst 
new/bitarray-3.8.2/doc/canonical.rst
--- old/bitarray-3.8.1/doc/canonical.rst        2026-04-02 17:13:02.000000000 
+0200
+++ new/bitarray-3.8.2/doc/canonical.rst        2026-06-17 17:58:51.000000000 
+0200
@@ -26,9 +26,9 @@
     >>> symbol
     ['a', 'b', 'r', 'c', 'd']
 
-The output is tuple with the following elements:
+The output is a tuple with the following elements:
 
-* A dictionary mapping each symbols to a ``bitarray``
+* A dictionary mapping each symbol to a ``bitarray``
 * A list containing the number of symbols for each code length,
   e.g. `count[3] = 1` because there is one symbol (``r``) with
   code length ``3``.
@@ -65,7 +65,7 @@
     bitarray('01011001110011110101100')
     >>> assert ''.join(a.decode(codedict)) == msg
 
-And now decode using not ``codedict``, but the canonical decoding
+And now decode using the canonical decoding
 tables ``count`` and ``symbol`` instead:
 
 .. code-block:: python
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/doc/changelog.rst 
new/bitarray-3.8.2/doc/changelog.rst
--- old/bitarray-3.8.1/doc/changelog.rst        2026-04-02 17:13:02.000000000 
+0200
+++ new/bitarray-3.8.2/doc/changelog.rst        2026-06-17 17:58:51.000000000 
+0200
@@ -1,6 +1,13 @@
 Change log
 ==========
 
+**3.8.2** (2026-06-17):
+
+* clarity/wording improvements throughout project
+* add ``new_allocation()`` to simplify ``resize()``
+* drop Python 3.6 support
+
+
 **3.8.1** (2026-04-02):
 
 * fixed critial findings in C Extension Analysis Report, see `#250 
<https://github.com/ilanschnell/bitarray/issues/250>`__
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/doc/endianness.rst 
new/bitarray-3.8.2/doc/endianness.rst
--- old/bitarray-3.8.1/doc/endianness.rst       2026-04-02 17:13:02.000000000 
+0200
+++ new/bitarray-3.8.2/doc/endianness.rst       2026-06-17 17:58:51.000000000 
+0200
@@ -6,7 +6,7 @@
 or ``.fromfile()``, as well as using ``memoryview()``, the bit-endianness
 will have no effect on any computation, and one can skip this section.
 
-Since bitarrays allows addressing individual bits, where the machine
+Since bitarrays allow addressing individual bits, where the machine
 represents 8 bits in one byte, there are two obvious choices for this
 mapping: little-endian and big-endian.
 
@@ -70,7 +70,7 @@
 Therefore, it is not possible to perform bitwise operators on bitarrays
 with different endianness.
 
-As mentioned above, the endianness can not be changed once an object is
+As mentioned above, the endianness cannot be changed once an object is
 created.  However, you can create a new bitarray with different endianness:
 
 .. code-block:: python
@@ -86,7 +86,7 @@
 Utility functions
 -----------------
 
-A number of utility functions take into the bit-endianness into account.
+A number of utility functions take the bit-endianness into account.
 For example consider:
 
 .. code-block:: python
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/doc/random_p.rst 
new/bitarray-3.8.2/doc/random_p.rst
--- old/bitarray-3.8.1/doc/random_p.rst 2026-04-02 17:13:02.000000000 +0200
+++ new/bitarray-3.8.2/doc/random_p.rst 2026-06-17 17:58:51.000000000 +0200
@@ -9,8 +9,8 @@
 
     bitarray(random() < p for _ in range(n))
 
-While this expression work well for small ``n``, it is quite slow when ``n``
-is large.  In the following we focus on the case of ``n`` being large.
+While this expression works well for small ``n``, it is quite slow when ``n``
+is large.  In the following we focus on the case of large ``n``.
 
 When ``p`` is small, a fast implementation of ``random_p()`` is to (a)
 calculate the population of the bitarray, and then (b) set the required
@@ -19,16 +19,18 @@
 need to determine the bitarray's population.
 
 When ``p == 0.5``, we use ``random.getrandbits()`` to initialize our bitarray
-buffer.  It should be noted that ``util.urandom()`` uses ``os.urandom()``,
+buffer.  It should be noted that ``bitarray.util.urandom()``
+uses ``os.urandom()``,
 but since ``util.random_p()`` is designed to give reproducible pseudo-random
-bitarrays, it uses ``getrandbits()``.
+bitarrays, it uses ``random.getrandbits()``.
 
 Taking two (independent) such bitarrays and combining them
 using the bitwise AND operation, gives us a random bitarray with
 probability 1/4.
-Likewise, taking two bitwise OR operation gives us probability 3/4.
+Likewise, applying a bitwise OR operation to two such bitarrays gives us
+probability 3/4.
 Without going into too much further detail, it is possible to combine
-more than two "getrandbits" bitarray to get probabilities ``i / 2**M``,
+more than two "getrandbits" bitarrays to get probabilities ``i / 2**M``,
 where ``M`` is the maximal number of "getrandbits" bitarrays we combine,
 and ``i`` is an integer.
 The required sequence of AND and OR operations is calculated from
@@ -47,9 +49,8 @@
 
 It should be noted that ``x`` is always small (once symmetry is applied in
 case of AND) such that it always uses the "small p" case.
-Unlike the combinations, this gives us a bitarray
-with exact probability ``x``.  Therefore, the requested probability ``p``
-is exactly obtained.
+Therefore, the bitarray has exactly probability ``x``, and hence
+the requested probability ``p`` is exact.
 For more details, see ``VerificationTests`` in the
 additional `random tests <../devel/test_random.py>`__.
 
@@ -57,7 +58,7 @@
 Speedup
 -------
 
-The speedup is largest, when the number of number of random numbers our
+The speedup is largest when the number of random numbers our
 algorithm uses is smallest.
 In the following, let ``k`` be the number of calls to ``getrandbits()``.
 For example, when ``p=0.5`` we have ``k=1``.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/doc/reference.rst 
new/bitarray-3.8.2/doc/reference.rst
--- old/bitarray-3.8.1/doc/reference.rst        2026-04-02 17:13:02.000000000 
+0200
+++ new/bitarray-3.8.2/doc/reference.rst        2026-06-17 17:58:51.000000000 
+0200
@@ -1,7 +1,7 @@
 Reference
 =========
 
-bitarray version: 3.8.1 -- `change log 
<https://github.com/ilanschnell/bitarray/blob/master/doc/changelog.rst>`__
+bitarray version: 3.8.2 -- `change log 
<https://github.com/ilanschnell/bitarray/blob/master/doc/changelog.rst>`__
 
 In the following, ``item`` and ``value`` are usually a single bit -
 an integer 0 or 1.
@@ -25,7 +25,7 @@
 
    ``endian``: Specifies the bit-endianness of the created bitarray object.
    Allowed values are ``big`` and ``little`` (the default is ``big``).
-   The bit-endianness effects the buffer representation of the bitarray.
+   The bit-endianness affects the buffer representation of the bitarray.
 
    ``buffer``: Any object which exposes a buffer.  When provided, 
``initializer``
    cannot be present (or has to be ``None``).  The imported buffer may be
@@ -120,7 +120,7 @@
 
 
 ``extend(iterable, /)``
-   Append items from to the end of the bitarray.
+   Append items from iterable to the end of the bitarray.
    If ``iterable`` is a (Unicode) string, each ``0`` and ``1`` are appended as
    bits (ignoring whitespace and underscore).
 
@@ -151,7 +151,7 @@
 
 ``fromfile(f, n=-1, /)``
    Extend bitarray with up to ``n`` bytes read from file object ``f`` (or any
-   other binary stream what supports a ``.read()`` method, e.g. 
``io.BytesIO``).
+   other binary stream that supports a ``.read()`` method, e.g. 
``io.BytesIO``).
    Each read byte will add eight bits to the bitarray.  When ``n`` is omitted
    or negative, reads and extends all data until EOF.
    When ``n`` is non-negative but exceeds the available data, ``EOFError`` is
@@ -171,8 +171,9 @@
 
 
 ``invert(index=<all bits>, /)``
-   Invert all bits in bitarray (in-place).
-   When the optional ``index`` is given, only invert the single bit at 
``index``.
+   Invert bits in-place.  When ``index`` is omitted, invert all bits.
+   When ``index`` is an integer, invert the single bit at index.
+   When ``index`` is a slice, invert the selected bits.
 
    New in version 1.5.3: optional index argument
 
@@ -255,7 +256,7 @@
 
 ``unpack(zero=b'\x00', one=b'\x01')`` -> bytes
    Return bytes that contain one byte for each bit in the bitarray,
-   using specified mapping.
+   using the specified mapping.
 
 
 bitarray data descriptors:
@@ -330,7 +331,8 @@
 ``ba2base(n, bitarray, /, group=0, sep=' ')`` -> str
    Return a string containing the base ``n`` ASCII representation of
    the bitarray.  Allowed values for ``n`` are 2, 4, 8, 16, 32 and 64.
-   The bitarray has to be multiple of length 1, 2, 3, 4, 5 or 6 respectively.
+   The bitarray has to have a length divisible by 1, 2, 3, 4, 5 or 6
+   respectively.
    For ``n=32`` the RFC 4648 Base32 alphabet is used, and for ``n=64`` the
    standard base 64 alphabet is used.
    When grouped, the string ``sep`` is inserted between groups
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/doc/represent.rst 
new/bitarray-3.8.2/doc/represent.rst
--- old/bitarray-3.8.1/doc/represent.rst        2026-04-02 17:13:02.000000000 
+0200
+++ new/bitarray-3.8.2/doc/represent.rst        2026-06-17 17:58:51.000000000 
+0200
@@ -9,7 +9,7 @@
 Binary representation
 ---------------------
 
-The most common representation of bitarrays is its native binary string
+The most common representation of bitarrays is their native binary string
 representation, which is great for interactively analyzing bitarray objects:
 
 .. code-block:: python
@@ -22,7 +22,7 @@
     '11001'
 
 However, this representation is very large compared to the bitarray object
-itself, and it not efficient for large bitarrays.
+itself, and it is not efficient for large bitarrays.
 
 
 Byte representation
@@ -69,7 +69,7 @@
 only valid values for the header are 0 or 16 (corresponding to a
 little-endian and big-endian empty bitarray).
 The functions ``serialize()`` and ``deserialize()`` are the recommended and
-fasted way to (de-) serialize bitarray objects to bytes objects (and vice
+fastest way to (de-) serialize bitarray objects to ``bytes`` objects (and vice
 versa).  The exact format of this representation is guaranteed to not
 change in future releases.
 
@@ -113,7 +113,7 @@
 
 The utility function ``ba2base()`` allows representing bitarrays by
 base ``n``, with possible bases 2, 4, 8, 16, 32 and 64.
-The bitarray has to be multiple of length 1, 2, 3, 4, 5 or 6 respectively:
+The bitarray length has to be a multiple of 1, 2, 3, 4, 5 or 6 respectively:
 
 .. code-block:: python
 
@@ -145,7 +145,7 @@
 ------------------------------
 
 In some cases, it is useful to represent bitarrays in a binary format that
-is "self terminating" (in the same way that C strings are NUL terminated).
+is "self-terminating" (in the same way that C strings are NUL terminated).
 That is, when an encoded bitarray of unknown length is encountered in a
 stream of binary data, the format lets us know when the end of the encoded
 bitarray is reached.
@@ -157,9 +157,9 @@
 
 Another representation
 is `compressed sparse bitarrays <./sparse_compression.rst>`__,
-whose format is also "self terminating".  This, format actually uses different
-representations dependent on how sparsely the population of the bitarray (even
-sections of the bitarray) is.
+whose format is also "self-terminating".  This format actually uses different
+representations depending on how sparse the bitarray (or even sections of the
+bitarray) is.
 For large sparse bitarrays, the format reduces (compresses) the amount of data
 very efficiently, while only requiring a very tiny overhead for non-sparsely
 populated bitarrays.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/doc/sparse_compression.rst 
new/bitarray-3.8.2/doc/sparse_compression.rst
--- old/bitarray-3.8.1/doc/sparse_compression.rst       2026-04-02 
17:13:02.000000000 +0200
+++ new/bitarray-3.8.2/doc/sparse_compression.rst       2026-06-17 
17:58:51.000000000 +0200
@@ -1,16 +1,17 @@
 Compression of sparse bitarrays
 ===============================
 
-In a ``bitarray`` object each byte in memory represents eight bits.
+In a ``bitarray`` object, each byte in memory represents eight bits.
 While this representation is very compact and efficient when dealing with
 most data, there are situations when this representation is inefficient.
-One such situation are sparsely populated bitarray.
-That is, bitarray in which only a few bits are 1, but most bits are 0.
+One such situation is a sparsely populated bitarray.
+That is, a bitarray in which only a few bits are 1, but most bits are 0.
 In this situation, one might consider using a data structure which stores
 the indices of the 1 bits and not use the ``bitarray`` object at all.
 However, having all of bitarray's functionality is very convenient.
-It may be desired to convert ``bitarray`` objects into a more compact (index
-based) format when storing objects on disk or sending them over the network.
+It may be desirable to convert ``bitarray`` objects into a more compact
+(index-based) format when storing objects on disk or sending them over the
+network.
 This is the use case of the utility functions ``sc_encode()``
 and ``sc_decode()``.
 The lower the population count, the more efficient the compression will be:
@@ -31,8 +32,8 @@
 ------------
 
 Consider a ``bitarray`` of length 256, that is 32 bytes of memory.
-If we represent this object by the indices of 1 bits as one byte each,
-the object will be represent more efficiently when the population (number
+If we represent this object by the indices of 1 bits, using one byte each,
+the object will be represented more efficiently when the population (number
 of 1 bits) is less than 32.  Based on the population, the
 function ``sc_encode()`` chooses to represent the object as either raw bytes
 or as bytes of indices of 1 bits.  These are the block types 0 and 1.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/doc/variable_length.rst 
new/bitarray-3.8.2/doc/variable_length.rst
--- old/bitarray-3.8.1/doc/variable_length.rst  2026-04-02 17:13:02.000000000 
+0200
+++ new/bitarray-3.8.2/doc/variable_length.rst  2026-06-17 17:58:51.000000000 
+0200
@@ -2,11 +2,11 @@
 ===============================
 
 In some cases, it is useful to represent bitarrays in a binary format that
-is "self terminating" (in the same way that C strings are NUL terminated).
+is "self-terminating" (in the same way that C strings are NUL terminated).
 That is, when an encoded bitarray of unknown length is encountered in a
 stream of binary data, the format lets us know when the end of the encoded
 bitarray is reached.
-Such a "variable length format" (most memory efficient for small bitarrays)
+Such a "variable-length format" (most memory-efficient for small bitarrays)
 is implemented in ``vl_encode()`` and ``vl_decode()``:
 
 .. code-block:: python
@@ -26,9 +26,9 @@
     >>> bytes(stream)
     b'other stuff'
 
-The variable length format is similar to LEB128.  A single byte can store
-bitarrays up to 4 element, every additional byte stores up to 7 more elements.
-The most significant bit of each byte indicated whether more bytes follow.
+The variable-length format is similar to LEB128.  A single byte can store
+bitarrays up to 4 elements; every additional byte stores up to 7 more elements.
+The most significant bit of each byte indicates whether more bytes follow.
 In addition, the first byte contains 3 bits which indicate the number of
 padding bits at the end of the stream.  Here is an example of
 encoding ``bitarray('01010110111001110')``:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/examples/double.py 
new/bitarray-3.8.2/examples/double.py
--- old/bitarray-3.8.1/examples/double.py       2026-04-02 17:13:02.000000000 
+0200
+++ new/bitarray-3.8.2/examples/double.py       2026-06-17 17:58:51.000000000 
+0200
@@ -77,39 +77,66 @@
 
 from math import pi, inf, nan, isnan
 from random import getrandbits, randint
+import re
 import unittest
 
-from bitarray.util import urandom
+from bitarray.util import urandom, gen_primes
 
 
 EXAMPLES = [
-    ( 0.0, "0 00000000000 " + 52 * "0"),
-    ( 1.0, "0 01111111111 " + 52 * "0"),
-    ( 1.5, "0 01111111111 1" + 51 * "0"),
-    ( 2.0, "0 10000000000 " + 52 * "0"),
-    ( 5.0, "0 10000000001 01" + 50 * "0"),
-    (-5.0, "1 10000000001 01" + 50 * "0"),
+    ( 0.0, "0 00000000000 (52*0)"),
+    ( 1.0, "0 01111111111 (52*0)"),
+    ( 1.5, "0 01111111111 1(51*0)"),
+    ( 2.0, "0 10000000000 (52*0)"),
+    ( 4.0, "0 10000000001 (52*0)"),
+    ( 5.0, "0 10000000001 01(50*0)"),
+    (-5.0, "1 10000000001 01(50*0)"),
     # smallest number > 1
-    (1.0000000000000002, "0 01111111111 " + 51 * "0" + "1"),
+    (1.0000000000000002, "0 01111111111 (51*0)1"),
     # minimal subnormal double
-    (4.9406564584124654e-324, "0 00000000000 " + 51 * "0" + "1"),
+    (4.9406564584124654e-324, "0 00000000000 (51*0)1"),
     # maximal subnormal double
-    (2.2250738585072009e-308, "0 00000000000 " + 52 * "1"),
+    (2.2250738585072009e-308, "0 00000000000 (52*1)"),
     # minimal normal double
-    (2.2250738585072014e-308, "0 00000000001 " + 52 * "0"),
+    (2.2250738585072014e-308, "0 00000000001 (52*0)"),
     # maximal (normal) double
-    (1.7976931348623157e+308, "0 11111111110 " + 52 * "1"),
-    ( inf, "0 11111111111 " + 52 * "0"),
-    (-inf, "1 11111111111 " + 52 * "0"),
-    ( 1/3, "0 01111111101 " + 26 * "01"),
+    (1.7976931348623157e+308, "0 11111111110 (52*1)"),
+    ( inf, "0 11111111111 (52*0)"),
+    (-inf, "1 11111111111 (52*0)"),
+    ( 1/2, "0 01111111110 (52*0)"),
+    ( 1/3, "0 01111111101 (26*01)"),
+    ( 1/4, "0 01111111101 (52*0)"),
     (  pi, "0 10000000000 "
        "1001001000011111101101010100010001000010110100011000"),
     # largest number exactly representated as integer
-    (2 ** 53 - 1, "0 10000110011 " + 52 * "1"),
+    (2 ** 53 - 1, "0 10000110011 (52*1)"),
 ]
 
+def expand_str(s):
+    pat = re.compile(r"""
+    \(
+        (\d+)     # multiplier
+        \*        # literal *
+        ([01]+)   # bit string
+    \)""", re.X)
+
+    def repl(match):
+        return int(match.group(1)) * match.group(2)
+
+    return pat.sub(repl, s)
+
+
 class DoubleTests(unittest.TestCase):
 
+    def test_expand_str(self):
+        for s, res in [
+                ("(0*0)(0*1)", ""),
+                ("(1*1)(1*0)", "10"),
+                ("(3*1100)", "110011001100"),
+                ("(2*10) (3*1)", "1010 111"),
+        ]:
+            self.assertEqual(expand_str(s), res)
+
     def test_zero(self):
         d = Double()
         self.assertEqual(float(d), 0.0)
@@ -119,10 +146,18 @@
 
     def test_examples(self):
         for x, s in EXAMPLES:
+            s = expand_str(s)
             for d in Double(x), Double(s):
                 self.assertEqual(float(d), x)
                 self.assertEqual(str(d), s)
 
+    def test_numberphile(self):
+        # https://www.youtube.com/watch?v=c066hLi78B0
+        d = Double(0.41468_25098_51111_66024)
+        self.assertEqual(d.sign, 0)
+        self.assertEqual(d.exponent, -2)
+        self.assertEqual(d.fraction[::-1], gen_primes(55)[3:])
+
     def test_nan(self):
         s = "0 11111111111 1" + 51 * "0"
         for x in nan, s:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/examples/puff/_puff.c 
new/bitarray-3.8.2/examples/puff/_puff.c
--- old/bitarray-3.8.1/examples/puff/_puff.c    2026-04-02 17:13:02.000000000 
+0200
+++ new/bitarray-3.8.2/examples/puff/_puff.c    2026-06-17 17:58:51.000000000 
+0200
@@ -3,7 +3,7 @@
 
       https://github.com/madler/zlib/blob/master/contrib/puff
 
-  This is Marks's copyright notice:
+  This is Mark's copyright notice:
 
   Copyright (C) 2002-2013 Mark Adler, all rights reserved
   version 2.3, 21 Jan 2013
@@ -32,7 +32,7 @@
 #define MAXBITS    15           /* maximum bits in a code */
 #define MAXLCODES 286           /* maximum number of literal/length codes */
 #define MAXDCODES  30           /* maximum number of distance codes */
-#define MAXCODES (MAXLCODES + MAXDCODES)  /* maximum codes lengths to read */
+#define MAXCODES (MAXLCODES + MAXDCODES)  /* maximum code lengths to read */
 #define FIXLCODES 288           /* number of fixed literal/length codes */
 
 
@@ -228,7 +228,6 @@
             return -1;
 
         if (symbol < 256) {             /* literal: symbol is the byte */
-            /* write out the literal */
             if (append_byte(s, symbol) < 0)
                 return -1;
         }
@@ -266,7 +265,7 @@
 /* set during module init */
 static PyTypeObject *bitarray_type;
 
-/* create a new initialized canonical Huffman decode iterator object */
+/* create a new initialized State object */
 static PyObject *
 state_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
@@ -392,7 +391,7 @@
         return PyErr_Format(PyExc_ValueError,                          \
               "size of length list too large: %zd > %d", n, maxcodes)
 
-/* given the liter/lengths and distance lengths as one big list,
+/* given the literal/lengths and distance lengths as one big list,
    decode literal/length and distance codes until an end-of-block code */
 static PyObject *
 state_decode_block(state_obj *self, PyObject *args)
@@ -466,7 +465,7 @@
 }
 
 /* given the code length code lengths (always 19 of them),
-   decode the liter/lengths and distance lengths into one big list */
+   decode the literal/lengths and distance lengths into one big list */
 static PyObject *
 state_decode_lengths(state_obj *self, PyObject *args)
 {
@@ -511,7 +510,7 @@
             lengths[index++] = symbol;
         else {                          /* repeat instruction */
             int len = 0;  /* last length to repeat, assume repeating zeros */
-            int n;                      /* time to repeat last length */
+            int n;        /* number of time to repeat last length */
 
             if (symbol == 16) {         /* repeat last length 3..6 times */
                 if (index == 0) {
@@ -544,9 +543,9 @@
     return list_from_shorts(lengths, ncode);
 }
 
-/* copy 'len' bytes starting at 'dist' bytes ago in self->out,
-   if the count 'len' exceeds the distance 'dist, then some of the output
-   data will be a copy of data that was copied earlier in the process */
+/* Copy 'len' bytes starting at 'dist' bytes ago in self->out.
+   If the count 'len' exceeds the distance 'dist, then some of the output
+   data will be a copy of data that was copied earlier in the process. */
 static PyObject *
 state_copy(state_obj *self, PyObject *args)
 {
@@ -607,6 +606,8 @@
 static void
 state_dealloc(state_obj *self)
 {
+    Py_DECREF(self->in);
+    Py_DECREF(self->out);
     Py_TYPE(self)->tp_free((PyObject *) self);
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bitarray-3.8.1/setup.py new/bitarray-3.8.2/setup.py
--- old/bitarray-3.8.1/setup.py 2026-04-02 17:13:02.000000000 +0200
+++ new/bitarray-3.8.2/setup.py 2026-06-17 17:58:51.000000000 +0200
@@ -3,10 +3,10 @@
 import platform
 
 
-if sys.version_info[:3] < (3, 6, 1):
+if sys.version_info[:3] < (3, 7):
     sys.exit("""\
 ****************************************************************************
-*   bitarray requires Python 3.6.1 or later.
+*   bitarray requires Python 3.7 or later.
 *   The last bitarray version supporting Python 2.7 is bitarray 2.9.3.
 ****************************************************************************
 """)
@@ -47,7 +47,6 @@
         "Operating System :: OS Independent",
         "Programming Language :: C",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.6",
         "Programming Language :: Python :: 3.7",
         "Programming Language :: Python :: 3.8",
         "Programming Language :: Python :: 3.9",

Reply via email to