bitarray 3.12.2__cp314-cp314-pyemscripten_2026_0_wasm32.whl

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.
bitarray/__init__.py ADDED
@@ -0,0 +1,66 @@
1
+ # Copyright (c) 2008 - 2026, Ilan Schnell; All Rights Reserved
2
+ """
3
+ This package defines an object type which can efficiently represent
4
+ a bitarray. Bitarrays are sequence types and behave very much like lists.
5
+
6
+ Please find a description of this package at:
7
+
8
+ https://github.com/ilanschnell/bitarray
9
+
10
+ Author: Ilan Schnell
11
+ """
12
+ from collections import namedtuple
13
+
14
+ from bitarray._bitarray import (
15
+ bitarray, decodetree, decodeiterator, _bitarray_reconstructor,
16
+ get_default_endian, bits2bytes, BITARRAY_VERSION as __version__
17
+ )
18
+
19
+ __all__ = ['bitarray', 'frozenbitarray', 'decodetree', 'decodeiterator',
20
+ 'bits2bytes']
21
+
22
+ BufferInfo = namedtuple('BufferInfo',
23
+ ['address', 'nbytes', 'endian', 'padbits',
24
+ 'alloc', 'readonly', 'imported', 'exports'])
25
+
26
+ class frozenbitarray(bitarray):
27
+ """frozenbitarray(initializer=0, /, endian='big', buffer=None) -> \
28
+ frozenbitarray
29
+
30
+ Return a `frozenbitarray` object. Initialized the same way a `bitarray`
31
+ object is initialized. A `frozenbitarray` is immutable and hashable,
32
+ and may therefore be used as a dictionary key.
33
+ """
34
+ def __init__(self, *args, **kwargs):
35
+ self._freeze()
36
+
37
+ def __repr__(self):
38
+ return 'frozen' + bitarray.__repr__(self)
39
+
40
+ def __hash__(self):
41
+ "Return hash(self)."
42
+ # ensure hash is independent of endianness
43
+ a = bitarray(self, 'big')
44
+ return hash((len(a), a.tobytes()))
45
+
46
+ # Technically the code below is not necessary, as all these methods will
47
+ # raise a TypeError on read-only memory. However, with a different error
48
+ # message.
49
+ def __delitem__(self, *args, **kwargs):
50
+ "" # no docstring
51
+ raise TypeError("frozenbitarray is immutable")
52
+
53
+ append = bytereverse = clear = extend = encode = fill = __delitem__
54
+ frombytes = fromfile = insert = invert = pack = pop = __delitem__
55
+ remove = rotate = reverse = setall = sort = __setitem__ = __delitem__
56
+ __iadd__ = __iand__ = __imul__ = __ior__ = __ixor__ = __delitem__
57
+ __ilshift__ = __irshift__ = __delitem__
58
+
59
+
60
+ def test(verbosity=1):
61
+ """test(verbosity=1) -> TextTestResult
62
+
63
+ Run self-test, and return `unittest.runner.TextTestResult` object.
64
+ """
65
+ from bitarray import test_bitarray
66
+ return test_bitarray.run(verbosity=verbosity)
bitarray/__init__.pyi ADDED
@@ -0,0 +1,176 @@
1
+ # Copyright (c) 2021 - 2026, Ilan Schnell; All Rights Reserved
2
+ #
3
+ # This stub, as well as util.pyi, are tested with Python 3.10 and mypy 1.11.2
4
+
5
+ from abc import ABCMeta
6
+ from collections.abc import Iterable, Iterator, Sequence
7
+ from unittest.runner import TextTestResult
8
+
9
+ from typing import Any, BinaryIO, Dict, Union, overload, NamedTuple
10
+
11
+
12
+ CodeDict = Dict[Any, bitarray]
13
+ # Python 3.12 has abc.Buffer which should be used instead
14
+ BytesLike = Union[bytes, bytearray]
15
+
16
+
17
+ class BufferInfo(NamedTuple):
18
+ address: int
19
+ nbytes: int
20
+ endian: str
21
+ padbits: int
22
+ alloc: int
23
+ readonly: bool
24
+ imported: bool
25
+ exports: int
26
+
27
+
28
+ class decodetree:
29
+ def __init__(self, code: CodeDict) -> None: ...
30
+ def nodes(self) -> tuple[int, int, int]: ...
31
+ def todict(self) -> CodeDict: ...
32
+
33
+
34
+ class decodeiterator(Iterator, metaclass=ABCMeta):
35
+ @property
36
+ def index(self) -> int: ...
37
+ def skipbits(self, count: int = ...) -> bitarray: ...
38
+
39
+
40
+ class bitarray:
41
+ def __init__(self,
42
+ initializer: Union[int, str, Iterable[int], None] = ...,
43
+ endian: Union[str, None] = ...,
44
+ buffer: Any = ...) -> None: ...
45
+
46
+ def all(self) -> bool: ...
47
+ def any(self) -> bool: ...
48
+ def append(self, value: int) -> None: ...
49
+ def buffer_info(self) -> BufferInfo: ...
50
+ def bytereverse(self,
51
+ start: int = ...,
52
+ stop: int = ...) -> None: ...
53
+
54
+ def clear(self) -> None: ...
55
+ def copy(self) -> bitarray: ...
56
+ def count(self,
57
+ sub_bitarray: Union[bitarray, int] = ...,
58
+ start: int = ...,
59
+ stop: int = ...,
60
+ step: int = ...) -> int: ...
61
+
62
+ def encode(self, code: CodeDict, x: Iterable) -> None: ...
63
+ def decode(self,
64
+ code: Union[CodeDict, decodetree]) -> decodeiterator: ...
65
+
66
+ def extend(self, x: Union[str, Iterable[int]]) -> None: ...
67
+ def fill(self, m: int = ...) -> int: ...
68
+ def find(self,
69
+ sub_bitarray: Union[bitarray, int],
70
+ start: int = ...,
71
+ stop: int = ...,
72
+ right: int = ...) -> int: ...
73
+
74
+ def frombytes(self, a: BytesLike) -> None: ...
75
+ def fromfile(self, f: BinaryIO, n: int = ...) -> None: ...
76
+ def index(self,
77
+ sub_bitarray: Union[bitarray, int],
78
+ start: int = ...,
79
+ stop: int = ...,
80
+ right: int = ...) -> int: ...
81
+
82
+ def insert(self, i: int, value: int) -> None: ...
83
+ def invert(self, i: int = ...) -> None: ...
84
+
85
+ def search(self,
86
+ sub_bitarray: Union[bitarray, int],
87
+ start: int = ...,
88
+ stop: int = ...,
89
+ right: int = ...) -> Iterator[int]: ...
90
+
91
+ def pack(self, b: BytesLike) -> None: ...
92
+ def pop(self, i: int = ...) -> int: ...
93
+ def remove(self, value: int) -> None: ...
94
+ def rotate(self, k: int = ...) -> None: ...
95
+ def reverse(self) -> None: ...
96
+
97
+ def setall(self, value: int) -> None: ...
98
+ def sort(self, reverse: int) -> None: ...
99
+ def to01(self,
100
+ group: int = ...,
101
+ sep: str = ...) -> str: ...
102
+ def tobytes(self) -> bytes: ...
103
+ def tofile(self, f: BinaryIO) -> None: ...
104
+ def tolist(self) -> list[int]: ...
105
+ def unpack(self,
106
+ zero: bytes = ...,
107
+ one: bytes = ...) -> bytes: ...
108
+
109
+ def __len__(self) -> int: ...
110
+ def __iter__(self) -> Iterator[int]: ...
111
+ @overload
112
+ def __getitem__(self, i: int) -> int: ...
113
+ @overload
114
+ def __getitem__(self,
115
+ s: Union[slice, bitarray, Sequence]) -> bitarray: ...
116
+ @overload
117
+ def __setitem__(self,
118
+ i: Union[int, slice, Sequence],
119
+ o: int) -> None: ...
120
+ @overload
121
+ def __setitem__(self,
122
+ s: Union[slice, bitarray, Sequence],
123
+ o: bitarray) -> None: ...
124
+ def __delitem__(self,
125
+ i: Union[int, slice, bitarray, Sequence]) -> None: ...
126
+
127
+ def __buffer__(self, flags: int, /) -> memoryview: ...
128
+ def __release_buffer__(self, buffer: memoryview, /) -> None: ...
129
+
130
+ def __add__(self, other: bitarray) -> bitarray: ...
131
+ def __iadd__(self, other: bitarray) -> bitarray: ...
132
+ def __mul__(self, n: int) -> bitarray: ...
133
+ def __imul__(self, n: int) -> bitarray: ...
134
+ def __rmul__(self, n: int) -> bitarray: ...
135
+
136
+ def __ge__(self, other: bitarray) -> bool: ...
137
+ def __gt__(self, other: bitarray) -> bool: ...
138
+ def __le__(self, other: bitarray) -> bool: ...
139
+ def __lt__(self, other: bitarray) -> bool: ...
140
+
141
+ def __and__(self, other: bitarray) -> bitarray: ...
142
+ def __or__(self, other: bitarray) -> bitarray: ...
143
+ def __xor__(self, other: bitarray) -> bitarray: ...
144
+ def __iand__(self, other: bitarray) -> bitarray: ...
145
+ def __ior__(self, other: bitarray) -> bitarray: ...
146
+ def __ixor__(self, other: bitarray) -> bitarray: ...
147
+ def __invert__(self) -> bitarray: ...
148
+ def __lshift__(self, n: int) -> bitarray: ...
149
+ def __rshift__(self, n: int) -> bitarray: ...
150
+ def __ilshift__(self, n: int) -> bitarray: ...
151
+ def __irshift__(self, n: int) -> bitarray: ...
152
+
153
+ # data descriptors
154
+ @property
155
+ def endian(self) -> str: ...
156
+ @property
157
+ def nbytes(self) -> int: ...
158
+ @property
159
+ def padbits(self) -> int: ...
160
+ @property
161
+ def readonly(self) -> bool: ...
162
+
163
+
164
+ class frozenbitarray(bitarray):
165
+ def __hash__(self) -> int: ...
166
+
167
+
168
+ __version__: str
169
+ def bits2bytes(n: int) -> int: ...
170
+ def get_default_endian() -> str: ...
171
+ def test(verbosity: int = ...) -> TextTestResult: ...
172
+ def _bitarray_reconstructor(cls: type,
173
+ buffer: bytes,
174
+ endian: str,
175
+ padbits: int,
176
+ readonly: int) -> bitarray: ...
bitarray/bitarray.h ADDED
@@ -0,0 +1,357 @@
1
+ /*
2
+ Copyright (c) 2008 - 2026, Ilan Schnell; All Rights Reserved
3
+ bitarray is published under the PSF license.
4
+
5
+ Author: Ilan Schnell
6
+ */
7
+ #define BITARRAY_VERSION "3.12.2"
8
+
9
+ #ifdef STDC_HEADERS
10
+ # include <stddef.h>
11
+ #else
12
+ # ifdef HAVE_SYS_TYPES_H
13
+ # include <sys/types.h> /* For size_t */
14
+ # endif
15
+ #endif
16
+
17
+ /* Compatibility with Visual Studio 2013 and older which don't support
18
+ the inline keyword in C (only in C++): use __inline instead.
19
+ (copied from pythoncapi_compat.h) */
20
+ #if (defined(_MSC_VER) && _MSC_VER < 1900 \
21
+ && !defined(__cplusplus) && !defined(inline))
22
+ #define inline __inline
23
+ #endif
24
+
25
+ #ifdef _MSC_VER
26
+ #include <intrin.h> /* For _byteswap_uint64() */
27
+ #endif
28
+
29
+ /* --- bitarrayobject --- */
30
+
31
+ /* .ob_size is the buffer size (in bytes), not the number of elements.
32
+ The number of elements (bits) is .nbits. */
33
+ typedef struct {
34
+ PyObject_VAR_HEAD
35
+ char *ob_item; /* buffer */
36
+ Py_ssize_t allocated; /* allocated buffer size (in bytes) */
37
+ Py_ssize_t nbits; /* length of bitarray, i.e. elements */
38
+ int endian; /* bit-endianness of bitarray */
39
+ int ob_exports; /* how many buffer exports */
40
+ PyObject *weakreflist; /* list of weak references */
41
+ Py_buffer *buffer; /* used when importing a buffer */
42
+ int readonly; /* buffer is readonly */
43
+ } bitarrayobject;
44
+
45
+ /* --- bit-endianness --- */
46
+ #define ENDIAN_LITTLE 0
47
+ #define ENDIAN_BIG 1
48
+ /* default bit-endianness */
49
+ #define ENDIAN_DEFAULT ENDIAN_BIG
50
+
51
+ #define IS_LE(self) ((self)->endian == ENDIAN_LITTLE)
52
+ #define IS_BE(self) ((self)->endian == ENDIAN_BIG)
53
+
54
+ /* endianness as string */
55
+ #define ENDIAN_STR(endian) ((endian) == ENDIAN_LITTLE ? "little" : "big")
56
+
57
+ /* number of pad bits */
58
+ #define PADBITS(self) ((8 - (self)->nbits % 8) % 8)
59
+
60
+ /* number of bytes necessary to store given number of bits */
61
+ #define BYTES(bits) (((size_t) (bits) + 7) >> 3)
62
+
63
+ /* we're not using bitmask_table here, as it is actually slower */
64
+ #define BITMASK(self, i) (((char) 1) << ((self)->endian == ENDIAN_LITTLE ? \
65
+ ((i) % 8) : (7 - (i) % 8)))
66
+
67
+ /* buffer as uint64 array */
68
+ #define WBUFF(self) ((uint64_t *) (self)->ob_item)
69
+
70
+ /* assert that .nbits is in agreement with .ob_size */
71
+ #define assert_nbits(self) assert(BYTES((self)->nbits) == Py_SIZE(self))
72
+
73
+ /* ------------ low level access to bits in bitarrayobject ------------- */
74
+
75
+ static inline int
76
+ getbit(bitarrayobject *self, Py_ssize_t i)
77
+ {
78
+ assert_nbits(self);
79
+ assert(0 <= i && i < self->nbits);
80
+ return self->ob_item[i >> 3] & BITMASK(self, i) ? 1 : 0;
81
+ }
82
+
83
+ static inline void
84
+ setbit(bitarrayobject *self, Py_ssize_t i, int vi)
85
+ {
86
+ char *cp, mask;
87
+
88
+ assert_nbits(self);
89
+ assert(0 <= i && i < self->nbits);
90
+ assert(self->readonly == 0);
91
+
92
+ mask = BITMASK(self, i);
93
+ cp = self->ob_item + (i >> 3);
94
+ if (vi)
95
+ *cp |= mask;
96
+ else
97
+ *cp &= ~mask;
98
+ }
99
+
100
+ static const char bitmask_table[2][8] = {
101
+ {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}, /* little endian */
102
+ {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}, /* big endian */
103
+ };
104
+
105
+ /* character with n leading ones is: ones_table[endian][n] */
106
+ static const char ones_table[2][8] = {
107
+ {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f}, /* little endian */
108
+ {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe}, /* big endian */
109
+ };
110
+
111
+ /* Return last byte in buffer with pad bits zeroed out.
112
+ If the length of the bitarray is a multiple of 8 (which includes an empty
113
+ bitarray), 0 is returned. */
114
+ static inline char
115
+ zlc(bitarrayobject *self) /* zlc = zeroed last char */
116
+ {
117
+ const int r = self->nbits % 8; /* index into mask table */
118
+
119
+ if (r == 0)
120
+ return 0;
121
+ return self->ob_item[Py_SIZE(self) - 1] & ones_table[IS_BE(self)][r];
122
+ }
123
+
124
+ /* Return a uint64_t word representing the last (up to 63) remaining bits
125
+ of the buffer. All missing bytes (to complete the word) and padbits are
126
+ treated as zeros.
127
+ If the length of the bitarray is a multiple of 64 (which also includes
128
+ an empty bitarray), 0 is returned. */
129
+ static inline uint64_t
130
+ zlw(bitarrayobject *self) /* zlw = zeroed last word */
131
+ {
132
+ const size_t nbits = self->nbits;
133
+ const size_t nw = (nbits / 64) * 8; /* bytes in complete words */
134
+ const size_t nr = (nbits % 64) / 8; /* complete remaining bytes */
135
+ uint64_t res = 0;
136
+
137
+ assert(nw + nr == nbits / 8 && 8 * (nw + nr) + nbits % 8 == nbits);
138
+ if (nr)
139
+ memcpy((char *) &res, self->ob_item + nw, nr);
140
+ if (nbits % 8)
141
+ *(((char *) &res) + nr) = zlc(self);
142
+
143
+ return res;
144
+ }
145
+
146
+ /* unless buffer is readonly, zero out pad bits - self->nbits is unchanged */
147
+ static inline void
148
+ set_padbits(bitarrayobject *self)
149
+ {
150
+ if (self->readonly == 0) {
151
+ int r = self->nbits % 8; /* index into mask table */
152
+ if (r)
153
+ self->ob_item[Py_SIZE(self) - 1] &= ones_table[IS_BE(self)][r];
154
+ }
155
+ }
156
+
157
+ /* population count - number of 1's in uint64 */
158
+ static inline int
159
+ popcnt_64(uint64_t x)
160
+ {
161
+ #if (defined(__clang__) || defined(__GNUC__))
162
+ return __builtin_popcountll(x);
163
+ #else
164
+ /* https://en.wikipedia.org/wiki/Hamming_weight popcount64c */
165
+ const uint64_t m1 = 0x5555555555555555;
166
+ const uint64_t m2 = 0x3333333333333333;
167
+ const uint64_t m4 = 0x0f0f0f0f0f0f0f0f;
168
+ const uint64_t h01 = 0x0101010101010101;
169
+
170
+ x -= (x >> 1) & m1;
171
+ x = (x & m2) + ((x >> 2) & m2);
172
+ x = (x + (x >> 4)) & m4;
173
+ return (x * h01) >> 56;
174
+ #endif
175
+ }
176
+
177
+ static inline int
178
+ parity_64(uint64_t x)
179
+ {
180
+ #if (defined(__clang__) || defined(__GNUC__))
181
+ return __builtin_parityll(x);
182
+ #else
183
+ int i;
184
+ for (i = 32; i > 0; i /= 2)
185
+ x ^= x >> i;
186
+ return x & 1;
187
+ #endif
188
+ }
189
+
190
+ static inline uint64_t
191
+ builtin_bswap64(uint64_t word)
192
+ {
193
+ #if (defined(__clang__) || \
194
+ (defined(__GNUC__) \
195
+ && ((__GNUC__ >= 5) || (__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))))
196
+ /* __builtin_bswap64() is available since GCC 4.3 */
197
+ # define HAVE_BUILTIN_BSWAP64 1
198
+ return __builtin_bswap64(word);
199
+ #elif defined(_MSC_VER)
200
+ # define HAVE_BUILTIN_BSWAP64 1
201
+ return _byteswap_uint64(word);
202
+ #else
203
+ # define HAVE_BUILTIN_BSWAP64 0
204
+ Py_UNREACHABLE();
205
+ #endif
206
+ }
207
+
208
+ /* reverse order of first n bytes of p */
209
+ static inline void
210
+ swap_bytes(char *p, Py_ssize_t n)
211
+ {
212
+ Py_ssize_t i, j;
213
+ for (i = 0, j = n - 1; i < j; i++, j--) {
214
+ char t = p[i];
215
+ p[i] = p[j];
216
+ p[j] = t;
217
+ }
218
+ }
219
+
220
+ /* write 256 characters into table for given kernel operation */
221
+ static inline void
222
+ setup_table(char *table, char kop)
223
+ {
224
+ int k;
225
+ for (k = 0; k < 256; k++) {
226
+ char t = 0, j;
227
+ for (j = 0; j < 8; j++) {
228
+ if (k & 1 << j) {
229
+ /* j are the indices of active bits in k (little endian) */
230
+ switch (kop) {
231
+ case 'a': t += j; break; /* add active indices */
232
+ case 'A': t += 7 - j; break; /* 'a' for big endian */
233
+ case 's': t += j * j; /* add squares of active indices */
234
+ break;
235
+ case 'S': t += (7-j) * (7-j); /* 's' for big endian */
236
+ break;
237
+ case 'x': t ^= j; break; /* xor active indices */
238
+ case 'X': t ^= 7 - j; break; /* 'x' for big endian */
239
+ case 'c': t++; break; /* bit count */
240
+ case 'p': t ^= 1; break; /* parity */
241
+ case 'r': t |= 128 >> j; break; /* reverse bits */
242
+ default: Py_UNREACHABLE();
243
+ }
244
+ }
245
+ }
246
+ table[k] = t;
247
+ }
248
+ }
249
+
250
+ /* Return distance [0..7] to next aligned pointer.
251
+ While on modern compilers uint64_t pointers may be misaligned, it may
252
+ cause problems on older ones. Moreover, it may lead to slowdown (even
253
+ on modern compilers). */
254
+ static inline int
255
+ to_aligned(void *p)
256
+ {
257
+ int r = ((uintptr_t) p) % 8;
258
+ return (8 - r) % 8;
259
+ }
260
+
261
+ /* population count of n words starting at uint64_t pointer w */
262
+ static inline Py_ssize_t
263
+ popcnt_words(uint64_t *w, Py_ssize_t n)
264
+ {
265
+ Py_ssize_t cnt = 0;
266
+
267
+ assert(n >= 0);
268
+ assert(n == 0 || ((uintptr_t) w) % 8 == 0);
269
+ while (n--)
270
+ cnt += popcnt_64(*w++);
271
+ return cnt;
272
+ }
273
+
274
+ /* Adjust slice indices to length and make step positive.
275
+ A positive step will produce simpler loops over items when their
276
+ order is irrelevant. Also, for example, for step = -1, we can now
277
+ use set_span() in set_range().
278
+ */
279
+ static inline Py_ssize_t
280
+ adjust_slice(Py_ssize_t length,
281
+ Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
282
+ {
283
+ Py_ssize_t slicelength;
284
+
285
+ assert(*step != 0 && length >= 0);
286
+
287
+ slicelength = PySlice_AdjustIndices(length, start, stop, *step);
288
+
289
+ if (*step < 0) { /* make step positive */
290
+ *stop = *start + 1;
291
+ *start = *stop + *step * (slicelength - 1) - 1;
292
+ *step = -(*step);
293
+ }
294
+ #ifndef NDEBUG
295
+ assert(*start >= 0 && *stop >= 0 && *step > 0 && slicelength >= 0);
296
+ assert((slicelength == 0) == (*stop <= *start));
297
+ if (slicelength) {
298
+ assert(*start <= length && *stop <= length);
299
+ if (*step == 1)
300
+ assert(*stop - *start == slicelength);
301
+ }
302
+ #endif
303
+
304
+ return slicelength;
305
+ }
306
+
307
+ /* convert Python object to C int at address *vi -
308
+ return 1 on success, 0 on failure (and set exception) */
309
+ static inline int
310
+ conv_pybit(PyObject *value, int *vi)
311
+ {
312
+ Py_ssize_t n;
313
+
314
+ n = PyNumber_AsSsize_t(value, NULL);
315
+ if (n == -1 && PyErr_Occurred())
316
+ return 0;
317
+
318
+ if (n < 0 || n > 1) {
319
+ PyErr_Format(PyExc_ValueError, "bit must be 0 or 1, got %zd", n);
320
+ return 0;
321
+ }
322
+ *vi = (int) n;
323
+ return 1;
324
+ }
325
+
326
+ /* Return 0 if bitarrays have equal length and bit-endianness.
327
+ Otherwise, set exception and return -1. */
328
+ static inline int
329
+ ensure_eq_size_endian(bitarrayobject *a, bitarrayobject *b)
330
+ {
331
+ if (a->nbits != b->nbits) {
332
+ PyErr_SetString(PyExc_ValueError,
333
+ "bitarrays of equal length expected");
334
+ return -1;
335
+ }
336
+ if (a->endian != b->endian) {
337
+ PyErr_SetString(PyExc_ValueError,
338
+ "bitarrays of equal bit-endianness expected");
339
+ return -1;
340
+ }
341
+ return 0;
342
+ }
343
+
344
+ /* Equivalent to: import bitarray; return getattr(bitarray, name) */
345
+ static inline PyObject *
346
+ bitarray_module_attr(char *name)
347
+ {
348
+ PyObject *bitarray_module, *result;
349
+
350
+ bitarray_module = PyImport_ImportModule("bitarray");
351
+ if (bitarray_module == NULL)
352
+ return NULL;
353
+
354
+ result = PyObject_GetAttrString(bitarray_module, name);
355
+ Py_DECREF(bitarray_module);
356
+ return result;
357
+ }