core: teach iter_split() to break on callback returning False.

pull/607/head
David Wilson 6 years ago
parent 33ecc8a5d2
commit 37beb3a5c5

@ -634,16 +634,23 @@ def iter_split(buf, delim, func):
"""
Invoke `func(s)` for each `delim`-delimited chunk in the potentially large
`buf`, avoiding intermediate lists and quadratic string operations. Return
the trailing undelimited portion of `buf`.
the trailing undelimited portion of `buf`, or any unprocessed portion of
`buf` after `func(s)` returned :data:`False`.
:returns:
`(trailer, cont)`, where `cont` is :data:`False` if the last call to
`func(s)` returned :data:`False`.
"""
dlen = len(delim)
start = 0
while True:
cont = True
while cont:
nl = buf.find(delim, start)
if nl == -1:
return buf[start:]
func(buf[start:nl])
break
cont = not func(buf[start:nl]) is False
start = nl + dlen
return buf[start:], cont
class Py24Pickler(py_pickle.Pickler):

@ -12,30 +12,49 @@ class IterSplitTest(unittest2.TestCase):
def test_empty_buffer(self):
lst = []
trailer = self.func(buf='', delim='\n', func=lst.append)
trailer, cont = self.func(buf='', delim='\n', func=lst.append)
self.assertTrue(cont)
self.assertEquals('', trailer)
self.assertEquals([], lst)
def test_empty_line(self):
lst = []
trailer = self.func(buf='\n', delim='\n', func=lst.append)
trailer, cont = self.func(buf='\n', delim='\n', func=lst.append)
self.assertTrue(cont)
self.assertEquals('', trailer)
self.assertEquals([''], lst)
def test_one_line(self):
buf = 'xxxx\n'
lst = []
trailer = self.func(buf=buf, delim='\n', func=lst.append)
trailer, cont = self.func(buf=buf, delim='\n', func=lst.append)
self.assertTrue(cont)
self.assertEquals('', trailer)
self.assertEquals(lst, ['xxxx'])
def test_one_incomplete(self):
buf = 'xxxx\nyy'
lst = []
trailer = self.func(buf=buf, delim='\n', func=lst.append)
trailer, cont = self.func(buf=buf, delim='\n', func=lst.append)
self.assertTrue(cont)
self.assertEquals('yy', trailer)
self.assertEquals(lst, ['xxxx'])
def test_returns_false_immediately(self):
buf = 'xxxx\nyy'
func = lambda buf: False
trailer, cont = self.func(buf=buf, delim='\n', func=func)
self.assertFalse(cont)
self.assertEquals('yy', trailer)
def test_returns_false_second_call(self):
buf = 'xxxx\nyy\nzz'
it = iter([True, False])
func = lambda buf: next(it)
trailer, cont = self.func(buf=buf, delim='\n', func=func)
self.assertFalse(cont)
self.assertEquals('zz', trailer)
if __name__ == '__main__':
unittest2.main()

Loading…
Cancel
Save