bitarray 3.8.2__tar.gz → 3.9.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bitarray
3
- Version: 3.8.2
3
+ Version: 3.9.0
4
4
  Summary: efficient arrays of booleans -- C extension
5
5
  Home-page: https://github.com/ilanschnell/bitarray
6
6
  Author: Ilan Schnell
@@ -21,6 +21,7 @@ Classifier: Programming Language :: Python :: 3.13
21
21
  Classifier: Programming Language :: Python :: 3.14
22
22
  Classifier: Programming Language :: Python :: Free Threading :: 1 - Unstable
23
23
  Classifier: Topic :: Utilities
24
+ Requires-Python: >=3.7
24
25
  License-File: LICENSE
25
26
  Dynamic: author
26
27
  Dynamic: author-email
@@ -29,6 +30,7 @@ Dynamic: description
29
30
  Dynamic: home-page
30
31
  Dynamic: license
31
32
  Dynamic: license-file
33
+ Dynamic: requires-python
32
34
  Dynamic: summary
33
35
 
34
36
  bitarray: efficient arrays of booleans
@@ -90,8 +92,8 @@ Once you have installed the package, you may want to test it:
90
92
 
91
93
  $ python -c 'import bitarray; bitarray.test()'
92
94
  bitarray is installed in: /Users/ilan/bitarray/bitarray
93
- bitarray version: 3.8.2
94
- sys.version: 3.13.5 (main, Jun 16 2025) [Clang 18.1.8]
95
+ bitarray version: 3.9.0
96
+ sys.version: 3.14.5 (main, May 20 2026) [Clang 20.1.8]
95
97
  sys.prefix: /Users/ilan/miniforge
96
98
  pointer size: 64 bit
97
99
  sizeof(size_t): 8
@@ -103,12 +105,12 @@ Once you have installed the package, you may want to test it:
103
105
  Py_DEBUG: 0
104
106
  DEBUG: 0
105
107
  .........................................................................
106
- .........................................................................
107
- ................................................................
108
+ ................................................s........................
109
+ ......s.........................................................
108
110
  ----------------------------------------------------------------------
109
- Ran 598 tests in 0.165s
111
+ Ran 622 tests in 0.191s
110
112
 
111
- OK
113
+ OK (skipped=2)
112
114
 
113
115
  The ``test()`` function is part of the API. It will return
114
116
  a ``unittest.runner.TextTestResult`` object, such that one can verify that
@@ -353,7 +355,7 @@ and can therefore be used as a dictionary key:
353
355
  Reference
354
356
  =========
355
357
 
356
- bitarray version: 3.8.2 -- `change log <https://github.com/ilanschnell/bitarray/blob/master/doc/changelog.rst>`__
358
+ bitarray version: 3.9.0 -- `change log <https://github.com/ilanschnell/bitarray/blob/master/doc/changelog.rst>`__
357
359
 
358
360
  In the following, ``item`` and ``value`` are usually a single bit -
359
361
  an integer 0 or 1.
@@ -455,7 +457,7 @@ bitarray methods:
455
457
  New in version 2.9: add non-overlapping sub-bitarray count
456
458
 
457
459
 
458
- ``decode(code, /)`` -> iterator
460
+ ``decode(code, /)`` -> decodeiterator
459
461
  Given a prefix code (a dict mapping symbols to bitarrays, or ``decodetree``
460
462
  object), decode content of bitarray and return an iterator over
461
463
  corresponding symbols.
@@ -464,6 +466,8 @@ bitarray methods:
464
466
 
465
467
  New in version 3.0: returns iterator (equivalent to past ``.iterdecode()``)
466
468
 
469
+ New in version 3.9: returns public ``decodeiterator`` object
470
+
467
471
 
468
472
  ``encode(code, iterable, /)``
469
473
  Given a prefix code (a dict mapping symbols to bitarrays),
@@ -556,6 +560,19 @@ bitarray methods:
556
560
  Reverse all bits in bitarray (in-place).
557
561
 
558
562
 
563
+ ``rotate(k=1, /)``
564
+ Rotate bitarray in-place by ``k`` positions.
565
+ Positive ``k`` rotates right, negative ``k`` rotates left.
566
+
567
+ When bitarray is not empty, rotating one step to the right is
568
+ equivalent to ``a.insert(0, a.pop())``, and rotating one step to the left
569
+ is equivalent to ``a.append(a.pop(0))``.
570
+ The same convention is used by the ``.rotate()`` method of
571
+ the ``collections.deque`` object.
572
+
573
+ New in version 3.9
574
+
575
+
559
576
  ``search(sub_bitarray, start=0, stop=<end>, /, right=False)`` -> iterator
560
577
  Return iterator over indices where sub_bitarray is found, such that
561
578
  sub_bitarray is contained within ``[start:stop]``.
@@ -634,6 +651,25 @@ Data descriptors were added in version 2.6.
634
651
  bool indicating whether buffer is read-only
635
652
 
636
653
 
654
+ decodeiterator methods:
655
+ -----------------------
656
+
657
+ ``skipbits(n, /)`` -> bitarray
658
+ Skip over the next ``n`` bits and return them.
659
+ Raises ``ValueError`` if count is out of range.
660
+
661
+ New in version 3.9
662
+
663
+
664
+ decodeiterator data descriptors:
665
+ --------------------------------
666
+
667
+ ``index`` -> int
668
+ current bit position to be decoded by subsequent ``next``
669
+
670
+ New in version 3.9
671
+
672
+
637
673
  Other objects:
638
674
  --------------
639
675
 
@@ -57,8 +57,8 @@ Once you have installed the package, you may want to test it:
57
57
 
58
58
  $ python -c 'import bitarray; bitarray.test()'
59
59
  bitarray is installed in: /Users/ilan/bitarray/bitarray
60
- bitarray version: 3.8.2
61
- sys.version: 3.13.5 (main, Jun 16 2025) [Clang 18.1.8]
60
+ bitarray version: 3.9.0
61
+ sys.version: 3.14.5 (main, May 20 2026) [Clang 20.1.8]
62
62
  sys.prefix: /Users/ilan/miniforge
63
63
  pointer size: 64 bit
64
64
  sizeof(size_t): 8
@@ -70,12 +70,12 @@ Once you have installed the package, you may want to test it:
70
70
  Py_DEBUG: 0
71
71
  DEBUG: 0
72
72
  .........................................................................
73
- .........................................................................
74
- ................................................................
73
+ ................................................s........................
74
+ ......s.........................................................
75
75
  ----------------------------------------------------------------------
76
- Ran 598 tests in 0.165s
76
+ Ran 622 tests in 0.191s
77
77
 
78
- OK
78
+ OK (skipped=2)
79
79
 
80
80
  The ``test()`` function is part of the API. It will return
81
81
  a ``unittest.runner.TextTestResult`` object, such that one can verify that
@@ -320,7 +320,7 @@ and can therefore be used as a dictionary key:
320
320
  Reference
321
321
  =========
322
322
 
323
- bitarray version: 3.8.2 -- `change log <https://github.com/ilanschnell/bitarray/blob/master/doc/changelog.rst>`__
323
+ bitarray version: 3.9.0 -- `change log <https://github.com/ilanschnell/bitarray/blob/master/doc/changelog.rst>`__
324
324
 
325
325
  In the following, ``item`` and ``value`` are usually a single bit -
326
326
  an integer 0 or 1.
@@ -422,7 +422,7 @@ bitarray methods:
422
422
  New in version 2.9: add non-overlapping sub-bitarray count
423
423
 
424
424
 
425
- ``decode(code, /)`` -> iterator
425
+ ``decode(code, /)`` -> decodeiterator
426
426
  Given a prefix code (a dict mapping symbols to bitarrays, or ``decodetree``
427
427
  object), decode content of bitarray and return an iterator over
428
428
  corresponding symbols.
@@ -431,6 +431,8 @@ bitarray methods:
431
431
 
432
432
  New in version 3.0: returns iterator (equivalent to past ``.iterdecode()``)
433
433
 
434
+ New in version 3.9: returns public ``decodeiterator`` object
435
+
434
436
 
435
437
  ``encode(code, iterable, /)``
436
438
  Given a prefix code (a dict mapping symbols to bitarrays),
@@ -523,6 +525,19 @@ bitarray methods:
523
525
  Reverse all bits in bitarray (in-place).
524
526
 
525
527
 
528
+ ``rotate(k=1, /)``
529
+ Rotate bitarray in-place by ``k`` positions.
530
+ Positive ``k`` rotates right, negative ``k`` rotates left.
531
+
532
+ When bitarray is not empty, rotating one step to the right is
533
+ equivalent to ``a.insert(0, a.pop())``, and rotating one step to the left
534
+ is equivalent to ``a.append(a.pop(0))``.
535
+ The same convention is used by the ``.rotate()`` method of
536
+ the ``collections.deque`` object.
537
+
538
+ New in version 3.9
539
+
540
+
526
541
  ``search(sub_bitarray, start=0, stop=<end>, /, right=False)`` -> iterator
527
542
  Return iterator over indices where sub_bitarray is found, such that
528
543
  sub_bitarray is contained within ``[start:stop]``.
@@ -601,6 +616,25 @@ Data descriptors were added in version 2.6.
601
616
  bool indicating whether buffer is read-only
602
617
 
603
618
 
619
+ decodeiterator methods:
620
+ -----------------------
621
+
622
+ ``skipbits(n, /)`` -> bitarray
623
+ Skip over the next ``n`` bits and return them.
624
+ Raises ``ValueError`` if count is out of range.
625
+
626
+ New in version 3.9
627
+
628
+
629
+ decodeiterator data descriptors:
630
+ --------------------------------
631
+
632
+ ``index`` -> int
633
+ current bit position to be decoded by subsequent ``next``
634
+
635
+ New in version 3.9
636
+
637
+
604
638
  Other objects:
605
639
  --------------
606
640
 
@@ -12,11 +12,13 @@ Author: Ilan Schnell
12
12
  from collections import namedtuple
13
13
 
14
14
  from bitarray._bitarray import (
15
- bitarray, decodetree, bits2bytes, _bitarray_reconstructor,
16
- get_default_endian, _sysinfo, BITARRAY_VERSION as __version__
15
+ bitarray, decodetree, decodeiterator, _bitarray_reconstructor,
16
+ get_default_endian, bits2bytes, _sysinfo,
17
+ BITARRAY_VERSION as __version__
17
18
  )
18
19
 
19
- __all__ = ['bitarray', 'frozenbitarray', 'decodetree', 'bits2bytes']
20
+ __all__ = ['bitarray', 'frozenbitarray', 'decodetree', 'decodeiterator',
21
+ 'bits2bytes']
20
22
 
21
23
  BufferInfo = namedtuple('BufferInfo',
22
24
  ['address', 'nbytes', 'endian', 'padbits',
@@ -51,7 +53,7 @@ and may therefore be used as a dictionary key.
51
53
 
52
54
  append = bytereverse = clear = extend = encode = fill = __delitem__
53
55
  frombytes = fromfile = insert = invert = pack = pop = __delitem__
54
- remove = reverse = setall = sort = __setitem__ = __delitem__
56
+ remove = rotate = reverse = setall = sort = __setitem__ = __delitem__
55
57
  __iadd__ = __iand__ = __imul__ = __ior__ = __ixor__ = __delitem__
56
58
  __ilshift__ = __irshift__ = __delitem__
57
59
 
@@ -2,6 +2,7 @@
2
2
  #
3
3
  # This stub, as well as util.pyi, are tested with Python 3.10 and mypy 1.11.2
4
4
 
5
+ from abc import ABCMeta
5
6
  from collections.abc import Iterable, Iterator, Sequence
6
7
  from unittest.runner import TextTestResult
7
8
 
@@ -31,6 +32,12 @@ class decodetree:
31
32
  def todict(self) -> CodeDict: ...
32
33
 
33
34
 
35
+ class decodeiterator(Iterator, metaclass=ABCMeta):
36
+ @property
37
+ def index(self) -> int: ...
38
+ def skipbits(self, count: int = ...) -> bitarray: ...
39
+
40
+
34
41
  class bitarray:
35
42
  def __init__(self,
36
43
  initializer: Union[int, str, Iterable[int], None] = ...,
@@ -55,7 +62,7 @@ class bitarray:
55
62
 
56
63
  def encode(self, code: CodeDict, x: Iterable) -> None: ...
57
64
  def decode(self,
58
- code: Union[CodeDict, decodetree]) -> Iterator: ...
65
+ code: Union[CodeDict, decodetree]) -> decodeiterator: ...
59
66
 
60
67
  def extend(self, x: Union[str, Iterable[int]]) -> None: ...
61
68
  def fill(self) -> int: ...
@@ -85,6 +92,7 @@ class bitarray:
85
92
  def pack(self, b: BytesLike) -> None: ...
86
93
  def pop(self, i: int = ...) -> int: ...
87
94
  def remove(self, value: int) -> None: ...
95
+ def rotate(self, k: int = ...) -> None: ...
88
96
  def reverse(self) -> None: ...
89
97
 
90
98
  def setall(self, value: int) -> None: ...
@@ -11,6 +11,7 @@
11
11
  #define PY_SSIZE_T_CLEAN
12
12
  #include "Python.h"
13
13
  #include "pythoncapi_compat.h"
14
+ #include "structmember.h"
14
15
  #include "bitarray.h"
15
16
 
16
17
  /* size used when reading / writing blocks from files (in bytes) */
@@ -609,11 +610,78 @@ count_range(bitarrayobject *self,
609
610
 
610
611
  /* return first (or rightmost in case right=1) occurrence
611
612
  of vi in self[a:b], -1 when not found */
613
+ static Py_ssize_t
614
+ find_bit(bitarrayobject *self, int vi, Py_ssize_t a, Py_ssize_t b, int right);
615
+
616
+ static Py_ssize_t
617
+ find_bit_words(bitarrayobject *self, int vi,
618
+ Py_ssize_t a, Py_ssize_t b, int right)
619
+ {
620
+ const Py_ssize_t wa = (a + 63) / 64; /* word-range(wa, wb) */
621
+ const Py_ssize_t wb = b / 64;
622
+ const uint64_t *wbuff = WBUFF(self);
623
+ const uint64_t w = vi ? 0 : ~0;
624
+ Py_ssize_t res, i;
625
+
626
+ if (right) {
627
+ if ((res = find_bit(self, vi, 64 * wb, b, 1)) >= 0)
628
+ return res;
629
+
630
+ for (i = wb - 1; i >= wa; i--) { /* skip uint64 words */
631
+ if (w ^ wbuff[i])
632
+ return find_bit(self, vi, 64 * i, 64 * i + 64, 1);
633
+ }
634
+ return find_bit(self, vi, a, 64 * wa, 1);
635
+ }
636
+ else {
637
+ if ((res = find_bit(self, vi, a, 64 * wa, 0)) >= 0)
638
+ return res;
639
+
640
+ for (i = wa; i < wb; i++) { /* skip uint64 words */
641
+ if (w ^ wbuff[i])
642
+ return find_bit(self, vi, 64 * i, 64 * i + 64, 0);
643
+ }
644
+ return find_bit(self, vi, 64 * wb, b, 0);
645
+ }
646
+ }
647
+
648
+ static Py_ssize_t
649
+ find_bit_bytes(bitarrayobject *self, int vi,
650
+ Py_ssize_t a, Py_ssize_t b, int right)
651
+ {
652
+ const Py_ssize_t ca = BYTES(a); /* char-range(ca, cb) */
653
+ const Py_ssize_t cb = b / 8;
654
+ const char *buff = self->ob_item;
655
+ const char c = vi ? 0 : ~0;
656
+ Py_ssize_t res, i;
657
+
658
+ if (right) {
659
+ if ((res = find_bit(self, vi, 8 * cb, b, 1)) >= 0)
660
+ return res;
661
+
662
+ for (i = cb - 1; i >= ca; i--) { /* skip bytes */
663
+ if (c ^ buff[i])
664
+ return find_bit(self, vi, 8 * i, 8 * i + 8, 1);
665
+ }
666
+ return find_bit(self, vi, a, 8 * ca, 1);
667
+ }
668
+ else {
669
+ if ((res = find_bit(self, vi, a, 8 * ca, 0)) >= 0)
670
+ return res;
671
+
672
+ for (i = ca; i < cb; i++) { /* skip bytes */
673
+ if (c ^ buff[i])
674
+ return find_bit(self, vi, 8 * i, 8 * i + 8, 0);
675
+ }
676
+ return find_bit(self, vi, 8 * cb, b, 0);
677
+ }
678
+ }
679
+
612
680
  static Py_ssize_t
613
681
  find_bit(bitarrayobject *self, int vi, Py_ssize_t a, Py_ssize_t b, int right)
614
682
  {
615
683
  const Py_ssize_t n = b - a;
616
- Py_ssize_t res, i;
684
+ Py_ssize_t i;
617
685
 
618
686
  assert(0 <= a && a <= self->nbits);
619
687
  assert(0 <= b && b <= self->nbits);
@@ -624,63 +692,13 @@ find_bit(bitarrayobject *self, int vi, Py_ssize_t a, Py_ssize_t b, int right)
624
692
  /* When the search range is greater than 64 bits, we skip uint64 words.
625
693
  Note that we cannot check for n >= 64 here as the function could then
626
694
  go into an infinite recursive loop when a word is found. */
627
- if (n > 64) {
628
- const Py_ssize_t wa = (a + 63) / 64; /* word-range(wa, wb) */
629
- const Py_ssize_t wb = b / 64;
630
- const uint64_t *wbuff = WBUFF(self);
631
- const uint64_t w = vi ? 0 : ~0;
632
-
633
- if (right) {
634
- if ((res = find_bit(self, vi, 64 * wb, b, 1)) >= 0)
635
- return res;
636
-
637
- for (i = wb - 1; i >= wa; i--) { /* skip uint64 words */
638
- if (w ^ wbuff[i])
639
- return find_bit(self, vi, 64 * i, 64 * i + 64, 1);
640
- }
641
- return find_bit(self, vi, a, 64 * wa, 1);
642
- }
643
- else {
644
- if ((res = find_bit(self, vi, a, 64 * wa, 0)) >= 0)
645
- return res;
695
+ if (n > 64)
696
+ return find_bit_words(self, vi, a, b, right);
646
697
 
647
- for (i = wa; i < wb; i++) { /* skip uint64 words */
648
- if (w ^ wbuff[i])
649
- return find_bit(self, vi, 64 * i, 64 * i + 64, 0);
650
- }
651
- return find_bit(self, vi, 64 * wb, b, 0);
652
- }
653
- }
654
698
  /* For the same reason as above, we cannot check for n >= 8 here. */
655
- if (n > 8) {
656
- const Py_ssize_t ca = BYTES(a); /* char-range(ca, cb) */
657
- const Py_ssize_t cb = b / 8;
658
- const char *buff = self->ob_item;
659
- const char c = vi ? 0 : ~0;
699
+ if (n > 8)
700
+ return find_bit_bytes(self, vi, a, b, right);
660
701
 
661
- if (right) {
662
- if ((res = find_bit(self, vi, 8 * cb, b, 1)) >= 0)
663
- return res;
664
-
665
- for (i = cb - 1; i >= ca; i--) { /* skip bytes */
666
- assert_byte_in_range(self, i);
667
- if (c ^ buff[i])
668
- return find_bit(self, vi, 8 * i, 8 * i + 8, 1);
669
- }
670
- return find_bit(self, vi, a, 8 * ca, 1);
671
- }
672
- else {
673
- if ((res = find_bit(self, vi, a, 8 * ca, 0)) >= 0)
674
- return res;
675
-
676
- for (i = ca; i < cb; i++) { /* skip bytes */
677
- assert_byte_in_range(self, i);
678
- if (c ^ buff[i])
679
- return find_bit(self, vi, 8 * i, 8 * i + 8, 0);
680
- }
681
- return find_bit(self, vi, 8 * cb, b, 0);
682
- }
683
- }
684
702
  /* finally, search for the desired bit by stepping one-by-one */
685
703
  for (i = right ? b - 1 : a; a <= i && i < b; i += right ? -1 : 1)
686
704
  if (getbit(self, i) == vi)
@@ -1874,6 +1892,56 @@ Remove the first occurrence of `value`.\n\
1874
1892
  Raises `ValueError` if value is not present.");
1875
1893
 
1876
1894
 
1895
+ static PyObject *
1896
+ bitarray_rotate(bitarrayobject *self, PyObject *args)
1897
+ {
1898
+ bitarrayobject *tmp;
1899
+ Py_ssize_t n = self->nbits, k = 1;
1900
+
1901
+ RAISE_IF_READONLY(self, NULL);
1902
+ if (!PyArg_ParseTuple(args, "|n:rotate", &k))
1903
+ return NULL;
1904
+
1905
+ if (n < 2)
1906
+ Py_RETURN_NONE;
1907
+
1908
+ k %= n; /* C remainder may be negative, as it preserves the sign of k */
1909
+ if (k < 0)
1910
+ k += n; /* make it equivalent to Python's k %= n */
1911
+ if (k == 0)
1912
+ Py_RETURN_NONE;
1913
+
1914
+ assert(0 < k && k < n);
1915
+
1916
+ /* temporary bitarray to store head or tail (whichever is smaller) */
1917
+ tmp = newbitarrayobject(&Bitarray_Type, Py_MIN(k, n - k), self->endian);
1918
+ if (tmp == NULL)
1919
+ return NULL;
1920
+
1921
+ assert(tmp->nbits <= n / 2); /* at most half size */
1922
+
1923
+ if (tmp->nbits == k) { /* tail is smaller */
1924
+ copy_n(tmp, 0, self, n - k, k); /* save tail */
1925
+ copy_n(self, k, self, 0, n - k); /* shift whole array right by k */
1926
+ copy_n(self, 0, tmp, 0, k); /* copy stored tail at front */
1927
+ }
1928
+ else { /* head is smaller */
1929
+ assert(tmp->nbits == n - k);
1930
+ copy_n(tmp, 0, self, 0, n - k); /* save head */
1931
+ copy_n(self, 0, self, n - k, k); /* shift whole array left by n-k */
1932
+ copy_n(self, k, tmp, 0, n - k); /* copy stored head at end */
1933
+ }
1934
+ Py_DECREF(tmp);
1935
+ Py_RETURN_NONE;
1936
+ }
1937
+
1938
+ PyDoc_STRVAR(rotate_doc,
1939
+ "rotate(k=1, /)\n\
1940
+ \n\
1941
+ Rotate bitarray in-place by `k` positions.\n\
1942
+ Positive `k` rotates right, negative `k` rotates left.");
1943
+
1944
+
1877
1945
  static PyObject *
1878
1946
  bitarray_sizeof(bitarrayobject *self)
1879
1947
  {
@@ -2096,18 +2164,13 @@ static PySequenceMethods bitarray_as_sequence = {
2096
2164
 
2097
2165
  /* ----------------------- bitarray_as_mapping ------------------------- */
2098
2166
 
2099
- /* return new bitarray with item in self, specified by slice */
2167
+ /* return new bitarray with item in self, specified by slice indices */
2100
2168
  static PyObject *
2101
- getslice(bitarrayobject *self, PyObject *slice)
2169
+ getslice_indices(bitarrayobject *self, Py_ssize_t start, Py_ssize_t step,
2170
+ Py_ssize_t slicelength)
2102
2171
  {
2103
- Py_ssize_t start, stop, step, slicelength;
2104
2172
  bitarrayobject *res;
2105
2173
 
2106
- assert(PySlice_Check(slice));
2107
- if (PySlice_GetIndicesEx(slice, self->nbits,
2108
- &start, &stop, &step, &slicelength) < 0)
2109
- return NULL;
2110
-
2111
2174
  res = newbitarrayobject(Py_TYPE(self), slicelength, self->endian);
2112
2175
  if (res == NULL)
2113
2176
  return NULL;
@@ -2124,6 +2187,20 @@ getslice(bitarrayobject *self, PyObject *slice)
2124
2187
  return freeze_if_frozen(res);
2125
2188
  }
2126
2189
 
2190
+ /* return new bitarray with item in self, specified by slice */
2191
+ static PyObject *
2192
+ getslice(bitarrayobject *self, PyObject *slice)
2193
+ {
2194
+ Py_ssize_t start, stop, step, slicelength;
2195
+
2196
+ assert(PySlice_Check(slice));
2197
+ if (PySlice_GetIndicesEx(slice, self->nbits,
2198
+ &start, &stop, &step, &slicelength) < 0)
2199
+ return NULL;
2200
+
2201
+ return getslice_indices(self, start, step, slicelength);
2202
+ }
2203
+
2127
2204
  static int
2128
2205
  ensure_mask_size(bitarrayobject *self, bitarrayobject *mask)
2129
2206
  {
@@ -3334,7 +3411,7 @@ bitarray_decode(bitarrayobject *self, PyObject *obj)
3334
3411
  }
3335
3412
 
3336
3413
  PyDoc_STRVAR(decode_doc,
3337
- "decode(code, /) -> iterator\n\
3414
+ "decode(code, /) -> decodeiterator\n\
3338
3415
  \n\
3339
3416
  Given a prefix code (a dict mapping symbols to bitarrays, or `decodetree`\n\
3340
3417
  object), decode content of bitarray and return an iterator over\n\
@@ -3374,6 +3451,51 @@ decodeiter_traverse(decodeiterobject *it, visitproc visit, void *arg)
3374
3451
  return 0;
3375
3452
  }
3376
3453
 
3454
+ static PyObject *
3455
+ decodeiter_skipbits(decodeiterobject *it, PyObject *args)
3456
+ {
3457
+ PyObject *skipped;
3458
+ Py_ssize_t n; /* number of bits to skip */
3459
+
3460
+ if (!PyArg_ParseTuple(args, "n:skipbits", &n))
3461
+ return NULL;
3462
+
3463
+ if (n < 0)
3464
+ return PyErr_Format(PyExc_ValueError, "skip count cannot be "
3465
+ "negative, got %zd", n);
3466
+
3467
+ if (n > it->self->nbits - it->index)
3468
+ return PyErr_Format(PyExc_ValueError, "skip count %zd cannot be "
3469
+ "larger than remaining bits %zd",
3470
+ n, it->self->nbits - it->index);
3471
+
3472
+ skipped = getslice_indices(it->self, it->index, 1, n);
3473
+ if (skipped == NULL)
3474
+ return NULL;
3475
+
3476
+ it->index += n;
3477
+ return skipped;
3478
+ }
3479
+
3480
+ PyDoc_STRVAR(decodeiter_skipbits_doc,
3481
+ "skipbits(n, /) -> bitarray\n\
3482
+ \n\
3483
+ Skip over the next `n` bits and return them.\n\
3484
+ Raises `ValueError` if count is out of range.");
3485
+
3486
+
3487
+ static PyMethodDef decodeiter_methods[] = {
3488
+ {"skipbits", (PyCFunction) decodeiter_skipbits, METH_VARARGS,
3489
+ decodeiter_skipbits_doc},
3490
+ {NULL}
3491
+ };
3492
+
3493
+ static PyMemberDef decodeiter_members[] = {
3494
+ {"index", Py_T_PYSSIZET, offsetof(decodeiterobject, index), Py_READONLY,
3495
+ PyDoc_STR("current bit position to be decoded by subsequent `next`")},
3496
+ {NULL}
3497
+ };
3498
+
3377
3499
  static PyTypeObject DecodeIter_Type = {
3378
3500
  PyVarObject_HEAD_INIT(NULL, 0)
3379
3501
  "bitarray.decodeiterator", /* tp_name */
@@ -3403,7 +3525,8 @@ static PyTypeObject DecodeIter_Type = {
3403
3525
  0, /* tp_weaklistoffset */
3404
3526
  PyObject_SelfIter, /* tp_iter */
3405
3527
  (iternextfunc) decodeiter_next, /* tp_iternext */
3406
- 0, /* tp_methods */
3528
+ decodeiter_methods, /* tp_methods */
3529
+ decodeiter_members, /* tp_members */
3407
3530
  };
3408
3531
 
3409
3532
  /*********************** (Bitarray) Search Iterator ***********************/
@@ -3586,6 +3709,8 @@ static PyMethodDef bitarray_methods[] = {
3586
3709
  remove_doc},
3587
3710
  {"reverse", (PyCFunction) bitarray_reverse, METH_NOARGS,
3588
3711
  reverse_doc},
3712
+ {"rotate", (PyCFunction) bitarray_rotate, METH_VARARGS,
3713
+ rotate_doc},
3589
3714
  {"search", (PyCFunction) bitarray_search, METH_VARARGS |
3590
3715
  METH_KEYWORDS,
3591
3716
  search_doc},
@@ -4298,6 +4423,8 @@ PyInit__bitarray(void)
4298
4423
  if (PyType_Ready(&DecodeIter_Type) < 0)
4299
4424
  return NULL;
4300
4425
  Py_SET_TYPE(&DecodeIter_Type, &PyType_Type);
4426
+ Py_INCREF((PyObject *) &DecodeIter_Type);
4427
+ PyModule_AddObject(m, "decodeiterator", (PyObject *) &DecodeIter_Type);
4301
4428
 
4302
4429
  if (PyType_Ready(&BitarrayIter_Type) < 0)
4303
4430
  return NULL;
@@ -4,7 +4,7 @@
4
4
 
5
5
  Author: Ilan Schnell
6
6
  */
7
- #define BITARRAY_VERSION "3.8.2"
7
+ #define BITARRAY_VERSION "3.9.0"
8
8
 
9
9
  #ifdef STDC_HEADERS
10
10
  # include <stddef.h>
@@ -77,10 +77,6 @@ typedef struct {
77
77
  /* assert that .nbits is in agreement with .ob_size */
78
78
  #define assert_nbits(self) assert(BYTES((self)->nbits) == Py_SIZE(self))
79
79
 
80
- /* assert byte index is in range */
81
- #define assert_byte_in_range(self, j) \
82
- assert(self->ob_item && 0 <= (j) && (j) < Py_SIZE(self))
83
-
84
80
  /* ------------ low level access to bits in bitarrayobject ------------- */
85
81
 
86
82
  static inline int