from itertools import chain, groupby
def group2_jfs(iterable, isstart):
# ABNF Grammar:# iterable = [ body ] *( header [ body ] )
it = groupby(iterable, isstart)
# [ body ]
start, headers_or_body = next(it)
if not start: # body
yield headers_or_body
start, headers = next(it)
else: # 1*header
headers = headers_or_body
while True: # 1*( header [ body ] )
assert start
bodyless_header = None
for header in headers: # yield all but last header
if bodyless_header is not None:
yield iter([bodyless_header])
bodyless_header = header
try:
start, body = next(it)
except StopIteration:
yield iter([header]) # the last header is bodyless
break
else:
assert not start
assert header is not None
yield chain([header], body)
start, headers = next(it)
from collections import deque
deque(group2_jfs(range(10**7), lambda x: x % 1000 == 0), maxlen=0)
ZnJvbSBpdGVydG9vbHMgaW1wb3J0IGNoYWluLCBncm91cGJ5CgpkZWYgZ3JvdXAyX2pmcyhpdGVyYWJsZSwgaXNzdGFydCk6CiAgICAjIEFCTkYgR3JhbW1hcjojIGl0ZXJhYmxlID0gWyBib2R5IF0gKiggaGVhZGVyIFsgYm9keSBdICkKICAgIGl0ID0gZ3JvdXBieShpdGVyYWJsZSwgaXNzdGFydCkKCiAgICAjIFsgYm9keSBdCiAgICBzdGFydCwgaGVhZGVyc19vcl9ib2R5ID0gbmV4dChpdCkKICAgIGlmIG5vdCBzdGFydDogICMgYm9keQogICAgICAgIHlpZWxkIGhlYWRlcnNfb3JfYm9keQogICAgICAgIHN0YXJ0LCBoZWFkZXJzID0gbmV4dChpdCkKICAgIGVsc2U6ICAjIDEqaGVhZGVyCiAgICAgICAgaGVhZGVycyA9IGhlYWRlcnNfb3JfYm9keQoKICAgIHdoaWxlIFRydWU6ICAjIDEqKCBoZWFkZXIgWyBib2R5IF0gKQogICAgICAgIGFzc2VydCBzdGFydAogICAgICAgIGJvZHlsZXNzX2hlYWRlciA9IE5vbmUKICAgICAgICBmb3IgaGVhZGVyIGluIGhlYWRlcnM6ICAjIHlpZWxkIGFsbCBidXQgbGFzdCBoZWFkZXIKICAgICAgICAgICAgaWYgYm9keWxlc3NfaGVhZGVyIGlzIG5vdCBOb25lOgogICAgICAgICAgICAgICAgeWllbGQgaXRlcihbYm9keWxlc3NfaGVhZGVyXSkKICAgICAgICAgICAgYm9keWxlc3NfaGVhZGVyID0gaGVhZGVyCgogICAgICAgIHRyeToKICAgICAgICAgICAgc3RhcnQsIGJvZHkgPSBuZXh0KGl0KQogICAgICAgIGV4Y2VwdCBTdG9wSXRlcmF0aW9uOgogICAgICAgICAgICB5aWVsZCBpdGVyKFtoZWFkZXJdKSAgIyB0aGUgbGFzdCBoZWFkZXIgaXMgYm9keWxlc3MKICAgICAgICAgICAgYnJlYWsKICAgICAgICBlbHNlOgogICAgICAgICAgICBhc3NlcnQgbm90IHN0YXJ0CiAgICAgICAgICAgIGFzc2VydCBoZWFkZXIgaXMgbm90IE5vbmUKICAgICAgICAgICAgeWllbGQgY2hhaW4oW2hlYWRlcl0sIGJvZHkpCiAgICAgICAgc3RhcnQsIGhlYWRlcnMgPSBuZXh0KGl0KQoKZnJvbSBjb2xsZWN0aW9ucyBpbXBvcnQgZGVxdWUKCmRlcXVlKGdyb3VwMl9qZnMocmFuZ2UoMTAqKjcpLCBsYW1iZGEgeDogeCAlIDEwMDAgPT0gMCksIG1heGxlbj0wKQo=