Skip to content
This repository has been archived by the owner on Sep 1, 2021. It is now read-only.

Commit

Permalink
Move Repeater docs, add unit tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
MostAwesomeDude committed Dec 27, 2010
1 parent ddcf923 commit 5fb603f
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 47 deletions.
47 changes: 39 additions & 8 deletions construct/core.py
Expand Up @@ -352,18 +352,49 @@ class Range(Subconstruct):
A range-array. The subcon will iterate between `mincount` to `maxcount`
times. If less than `mincount` elements are found, raises RangeError.
See also GreedyRange and OptionalGreedyRange.
Notes:
* requires a seekable stream.
The general-case repeater. Repeats the given unit for at least mincount
times, and up to maxcount times. If an exception occurs (EOF, validation
error), the repeater exits. If less than mincount units have been
successfully parsed, a RepeaterError is raised.
.. note::
This object requires a seekable stream for parsing.
Parameters:
* mincount - the minimal count (an integer)
* maxcount - the maximal count (an integer)
* subcon - the subcon to repeat
* mincount - the minimal count (an integer)
* maxcount - the maximal count (an integer)
* subcon - the subcon to repeat
Example:
Range(5, 8, UBInt8("foo"))
>>> c = Repeater(3, 7, UBInt8("foo"))
>>> c.parse("\\x01\\x02")
Traceback (most recent call last):
...
construct.core.RepeaterError: expected 3..7, found 2
>>> c.parse("\\x01\\x02\\x03")
[1, 2, 3]
>>> c.parse("\\x01\\x02\\x03\\x04\\x05\\x06")
[1, 2, 3, 4, 5, 6]
>>> c.parse("\\x01\\x02\\x03\\x04\\x05\\x06\\x07")
[1, 2, 3, 4, 5, 6, 7]
>>> c.parse("\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09")
[1, 2, 3, 4, 5, 6, 7]
>>> c.build([1,2])
Traceback (most recent call last):
...
construct.core.RepeaterError: expected 3..7, found 2
>>> c.build([1,2,3,4])
'\\x01\\x02\\x03\\x04'
>>> c.build([1,2,3,4,5,6,7,8])
Traceback (most recent call last):
...
construct.core.RepeaterError: expected 3..7, found 8
"""

__slots__ = ["mincount", "maxcout"]
def __init__(self, mincount, maxcout, subcon):
Subconstruct.__init__(self, subcon)
Expand Down
27 changes: 27 additions & 0 deletions construct/tests/test_repeaters.py
@@ -1,9 +1,36 @@
import unittest

from construct import UBInt8
from construct import Repeater
from construct import StrictRepeater, GreedyRepeater, OptionalGreedyRepeater
from construct import ArrayError, RangeError

class TestRepeater(unittest.TestCase):

def setUp(self):
self.c = Repeater(3, 7, UBInt8("foo"))

def test_trivial(self):
pass

def test_parse(self):
self.assertEqual(self.c.parse("\x01\x02\x03"), [1, 2, 3])
self.assertEqual(self.c.parse("\x01\x02\x03\x04\x05\x06"),
[1, 2, 3, 4, 5, 6])
self.assertEqual(self.c.parse("\x01\x02\x03\x04\x05\x06\x07"),
[1, 2, 3, 4, 5, 6, 7])
self.assertEqual(self.c.parse("\x01\x02\x03\x04\x05\x06\x07\x08\x09"),
[1, 2, 3, 4, 5, 6, 7])

def test_build(self):
self.assertEqual(self.c.build([1, 2, 3, 4]), "\x01\x02\x03\x04")

def test_build_undersized(self):
self.assertRaises(RangeError, self.c.build, [1, 2])

def test_build_oversized(self):
self.assertRaises(RangeError, self.c.build, [1, 2, 3, 4, 5, 6, 7, 8])

class TestStrictRepeater(unittest.TestCase):

def setUp(self):
Expand Down
40 changes: 1 addition & 39 deletions docs/basics.rst
Expand Up @@ -249,45 +249,7 @@ will be covered in the Meta constructs tutorial.
We have four kinds of static repeaters. In fact, for those of you who wish to
go under the hood, three of these repeaters are but wrappers around Repeater.

Repeater
--------

The general-case repeater. Repeats the given unit for at least mincount times,
and up to maxcount times. If an exception occurs (EOF, validation error), the
repeater exits. If less than mincount units have been successfully parsed, a
RepeaterError is raised.

# at least 3 times, at most 7 times
>>> c = Repeater(3, 7, UBInt8("foo"))

# parsing
>>> c.parse("\x01\x02")
Traceback (most recent call last):
.
.
construct.core.RepeaterError: expected 3..7, found 2
>>> c.parse("\x01\x02\x03")
[1, 2, 3]
>>> c.parse("\x01\x02\x03\x04\x05\x06")
[1, 2, 3, 4, 5, 6]
>>> c.parse("\x01\x02\x03\x04\x05\x06\x07")
[1, 2, 3, 4, 5, 6, 7]
>>> c.parse("\x01\x02\x03\x04\x05\x06\x07\x08\x09")
[1, 2, 3, 4, 5, 6, 7]

# building
>>> c.build([1,2])
Traceback (most recent call last):
.
.
construct.core.RepeaterError: expected 3..7, found 2
>>> c.build([1,2,3,4])
'\x01\x02\x03\x04'
>>> c.build([1,2,3,4,5,6,7,8])
Traceback (most recent call last):
.
.
construct.core.RepeaterError: expected 3..7, found 8
.. autofunction:: construct.Repeater

.. autofunction:: construct.StrictRepeater

Expand Down

0 comments on commit 5fb603f

Please sign in to comment.