Skip to content

Commit 8d95f75

Browse files
committed
Rework of compiled format class hierarchy.
1 parent b710344 commit 8d95f75

File tree

3 files changed

+98
-74
lines changed

3 files changed

+98
-74
lines changed

bitstruct.py

+86-65
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import binascii
77

88

9-
__version__ = "5.2.1"
9+
__version__ = "6.0.0"
1010

1111

1212
class Error(Exception):
@@ -246,27 +246,15 @@ def _unpack_bytearray(size, bits):
246246
return binascii.unhexlify(hex(int('10000000' + bits, 2))[4:].rstrip('L'))
247247

248248

249-
class CompiledFormat(object):
250-
"""A compiled format string that can be used to pack and/or unpack
251-
data multiple times.
252-
253-
Instances of this class are created by the factory function
254-
:func:`~bitstruct.compile()`.
255-
256-
"""
249+
class _CompiledFormat(object):
257250

258251
def __init__(self, fmt, names=None):
259252
infos, byte_order = _parse_format(fmt, names)
260253
self._infos = infos
261254
self._byte_order = byte_order
262255
self._number_of_bits_to_unpack = sum([info.size for info in infos])
263-
self._number_of_arguments = 0
264-
265-
for info in infos:
266-
if not isinstance(info, _Padding):
267-
self._number_of_arguments += 1
268256

269-
def _pack_value(self, info, value, bits):
257+
def pack_value(self, info, value, bits):
270258
value_bits = info.pack(value)
271259

272260
# Reverse the bit order in little endian values.
@@ -288,14 +276,14 @@ def _pack_value(self, info, value, bits):
288276

289277
return bits
290278

291-
def _pack(self, values):
279+
def pack_any(self, values):
292280
bits = ''
293281

294282
for info in self._infos:
295283
if isinstance(info, _Padding):
296284
bits += info.pack()
297285
else:
298-
bits = self._pack_value(info, values[info.name], bits)
286+
bits = self.pack_value(info, values[info.name], bits)
299287

300288
# Padding of last byte.
301289
tail = len(bits) % 8
@@ -305,7 +293,7 @@ def _pack(self, values):
305293

306294
return bytes(_unpack_bytearray(len(bits), bits))
307295

308-
def _unpack_from(self, data, offset):
296+
def unpack_from_any(self, data, offset):
309297
bits = bin(int(b'01' + binascii.hexlify(bytearray(data)), 16))[3 + offset:]
310298

311299
# Sanity check.
@@ -345,7 +333,7 @@ def _unpack_from(self, data, offset):
345333

346334
offset += info.size
347335

348-
def _pack_into(self, buf, offset, data, **kwargs):
336+
def pack_into_any(self, buf, offset, data, **kwargs):
349337
fill_padding = kwargs.get('fill_padding', True)
350338
buf_bits = _pack_bytearray(8 * len(buf), buf)
351339
bits = buf_bits[0:offset]
@@ -358,7 +346,7 @@ def _pack_into(self, buf, offset, data, **kwargs):
358346
else:
359347
bits += buf_bits[len(bits):len(bits) + info.size]
360348
else:
361-
bits = self._pack_value(info, data[info.name], bits)
349+
bits = self.pack_value(info, data[info.name], bits)
362350
i += 1
363351

364352
bits += buf_bits[len(bits):]
@@ -370,8 +358,33 @@ def _pack_into(self, buf, offset, data, **kwargs):
370358

371359
buf[:] = _unpack_bytearray(len(bits), bits)
372360

361+
def calcsize(self):
362+
"""Return the number of bits in the compiled format string.
363+
364+
"""
365+
366+
return self._number_of_bits_to_unpack
367+
368+
369+
class CompiledFormat(_CompiledFormat):
370+
"""A compiled format string that can be used to pack and/or unpack
371+
data multiple times.
372+
373+
Instances of this class are created by the factory function
374+
:func:`~bitstruct.compile()`.
375+
376+
"""
377+
378+
def __init__(self, fmt):
379+
super(CompiledFormat, self).__init__(fmt, None)
380+
self._number_of_arguments = 0
381+
382+
for info in self._infos:
383+
if not isinstance(info, _Padding):
384+
self._number_of_arguments += 1
385+
373386
def pack(self, *args):
374-
"""See :func:`pack()`.
387+
"""See :func:`~bitstruct.pack()`.
375388
376389
"""
377390

@@ -382,17 +395,17 @@ def pack(self, *args):
382395
self._number_of_arguments,
383396
len(args)))
384397

385-
return self._pack(args)
398+
return self.pack_any(args)
386399

387400
def unpack(self, data):
388-
"""See :func:`unpack()`.
401+
"""See :func:`~bitstruct.unpack()`.
389402
390403
"""
391404

392405
return self.unpack_from(data)
393406

394407
def pack_into(self, buf, offset, *args, **kwargs):
395-
"""See :func:`pack_into()`.
408+
"""See :func:`~bitstruct.pack_into()`.
396409
397410
"""
398411

@@ -403,55 +416,54 @@ def pack_into(self, buf, offset, *args, **kwargs):
403416
self._number_of_arguments,
404417
len(args)))
405418

406-
self._pack_into(buf, offset, args, **kwargs)
419+
self.pack_into_any(buf, offset, args, **kwargs)
407420

408421
def unpack_from(self, data, offset=0):
409-
"""See :func:`unpack_from()`.
422+
"""See :func:`~bitstruct.unpack_from()`.
410423
411424
"""
412425

413-
return tuple([v[1] for v in self._unpack_from(data, offset)])
426+
return tuple([v[1] for v in self.unpack_from_any(data, offset)])
427+
428+
429+
class CompiledFormatDict(_CompiledFormat):
430+
"""See :class:`~bitstruct.CompiledFormat`.
431+
432+
"""
414433

415-
def pack_dict(self, data):
416-
"""See :func:`pack_dict()`.
434+
def pack(self, data):
435+
"""See :func:`~bitstruct.pack_dict()`.
417436
418437
"""
419438

420439
try:
421-
return self._pack(data)
440+
return self.pack_any(data)
422441
except KeyError as e:
423442
raise Error('{} not found in data dictionary'.format(str(e)))
424443

425-
def unpack_dict(self, data):
426-
"""See :func:`unpack_dict()`.
444+
def unpack(self, data):
445+
"""See :func:`~bitstruct.unpack_dict()`.
427446
428447
"""
429448

430-
return self.unpack_from_dict(data)
449+
return self.unpack_from(data)
431450

432-
def pack_into_dict(self, buf, offset, data, **kwargs):
433-
"""See :func:`pack_into_dict()`.
451+
def pack_into(self, buf, offset, data, **kwargs):
452+
"""See :func:`~bitstruct.pack_into_dict()`.
434453
435454
"""
436455

437456
try:
438-
self._pack_into(buf, offset, data, **kwargs)
457+
self.pack_into_any(buf, offset, data, **kwargs)
439458
except KeyError as e:
440459
raise Error('{} not found in data dictionary'.format(str(e)))
441460

442-
def unpack_from_dict(self, data, offset=0):
443-
"""See :func:`unpack_from_dict()`.
444-
445-
"""
446-
447-
return {info.name: v for info, v in self._unpack_from(data, offset)}
448-
449-
def calcsize(self):
450-
"""Return the number of bits in the compiled format string.
461+
def unpack_from(self, data, offset=0):
462+
"""See :func:`~bitstruct.unpack_from_dict()`.
451463
452464
"""
453465

454-
return self._number_of_bits_to_unpack
466+
return {info.name: v for info, v in self.unpack_from_any(data, offset)}
455467

456468

457469
def pack(fmt, *args):
@@ -542,7 +554,8 @@ def unpack_from(fmt, data, offset=0):
542554

543555

544556
def pack_dict(fmt, names, data):
545-
"""Same as :func:`pack()`, but data is read from a dictionary.
557+
"""Same as :func:`~bitstruct.pack()`, but data is read from a
558+
dictionary.
546559
547560
The names list `names` contains the format group names, used as
548561
keys in the dictionary.
@@ -552,43 +565,45 @@ def pack_dict(fmt, names, data):
552565
553566
"""
554567

555-
return CompiledFormat(fmt, names).pack_dict(data)
568+
return CompiledFormatDict(fmt, names).pack(data)
556569

557570

558571
def unpack_dict(fmt, names, data):
559-
"""Same as :func:`unpack()`, but returns a dictionary.
572+
"""Same as :func:`~bitstruct.unpack()`, but returns a dictionary.
560573
561-
See :func:`pack_dict()` for details on `names`.
574+
See :func:`~bitstruct.pack_dict()` for details on `names`.
562575
563576
>>> unpack_dict('u4u4', ['foo', 'bar'], b'\\x12')
564577
{'foo': 1, 'bar': 2}
565578
566579
"""
567580

568-
return CompiledFormat(fmt, names).unpack_dict(data)
581+
return CompiledFormatDict(fmt, names).unpack(data)
569582

570583

571584
def pack_into_dict(fmt, names, buf, offset, data, **kwargs):
572-
"""Same as :func:`pack_into()`, but data is read from a dictionary.
585+
"""Same as :func:`~bitstruct.pack_into()`, but data is read from a
586+
dictionary.
573587
574-
See :func:`pack_dict()` for details on `names`.
588+
See :func:`~bitstruct.pack_dict()` for details on `names`.
575589
576590
"""
577591

578-
return CompiledFormat(fmt, names).pack_into_dict(buf,
579-
offset,
580-
data,
581-
**kwargs)
592+
return CompiledFormatDict(fmt, names).pack_into(buf,
593+
offset,
594+
data,
595+
**kwargs)
582596

583597

584598
def unpack_from_dict(fmt, names, data, offset=0):
585-
"""Same as :func:`unpack_from_dict()`, but returns a dictionary.
599+
"""Same as :func:`~bitstruct.unpack_from_dict()`, but returns a
600+
dictionary.
586601
587-
See :func:`pack_dict()` for details on `names`.
602+
See :func:`~bitstruct.pack_dict()` for details on `names`.
588603
589604
"""
590605

591-
return CompiledFormat(fmt, names).unpack_from_dict(data, offset)
606+
return CompiledFormatDict(fmt, names).unpack_from(data, offset)
592607

593608

594609
def calcsize(fmt):
@@ -623,12 +638,18 @@ def byteswap(fmt, data, offset=0):
623638

624639

625640
def compile(fmt, names=None):
626-
"""Compile given format string `fmt` and return a
627-
:class:`~bitstruct.CompiledFormat` object that can be used to pack
628-
and/or unpack data multiple times.
641+
"""Compile given format string `fmt` and return a compiled format
642+
object that can be used to pack and/or unpack data multiple times.
643+
644+
Returns a :class:`~bitstruct.CompiledFormat` object if `names` is
645+
``None``, and otherwise a :class:`~bitstruct.CompiledFormatDict`
646+
object.
629647
630-
See :func:`pack_dict()` for details on `names`.
648+
See :func:`~bitstruct.pack_dict()` for details on `names`.
631649
632650
"""
633651

634-
return CompiledFormat(fmt, names)
652+
if names is None:
653+
return CompiledFormat(fmt)
654+
else:
655+
return CompiledFormatDict(fmt, names)

docs/index.rst

+11-8
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,14 @@ Classes
3131

3232
.. autoclass:: bitstruct.CompiledFormat
3333

34-
.. automethod:: pack
35-
.. automethod:: unpack
36-
.. automethod:: pack_into
37-
.. automethod:: unpack_from
38-
.. automethod:: pack_dict
39-
.. automethod:: unpack_dict
40-
.. automethod:: pack_into_dict
41-
.. automethod:: unpack_from_dict
34+
.. automethod:: bitstruct.CompiledFormat.pack
35+
.. automethod:: bitstruct.CompiledFormat.unpack
36+
.. automethod:: bitstruct.CompiledFormat.pack_into
37+
.. automethod:: bitstruct.CompiledFormat.unpack_from
38+
39+
.. autoclass:: bitstruct.CompiledFormatDict
40+
41+
.. automethod:: bitstruct.CompiledFormatDict.pack
42+
.. automethod:: bitstruct.CompiledFormatDict.unpack
43+
.. automethod:: bitstruct.CompiledFormatDict.pack_into
44+
.. automethod:: bitstruct.CompiledFormatDict.unpack_from

tests/test_bitstruct.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ def test_compile_pack_unpack_formats(self):
727727
packed_2 = pack(fmt, *decoded)
728728
else:
729729
cf = bitstruct.compile(fmt, names)
730-
packed_1 = cf.pack_dict(decoded)
730+
packed_1 = cf.pack(decoded)
731731
packed_2 = pack_dict(fmt, names, decoded)
732732

733733
self.assertEqual(packed_1, b'\xe0')

0 commit comments

Comments
 (0)