| 2266 | # A pickle opcode generator. |
| 2267 | |
| 2268 | def _genops(data, yield_end_pos=False): |
| 2269 | if isinstance(data, bytes_types): |
| 2270 | data = io.BytesIO(data) |
| 2271 | |
| 2272 | if hasattr(data, "tell"): |
| 2273 | getpos = data.tell |
| 2274 | else: |
| 2275 | getpos = lambda: None |
| 2276 | |
| 2277 | while True: |
| 2278 | pos = getpos() |
| 2279 | code = data.read(1) |
| 2280 | opcode = code2op.get(code.decode("latin-1")) |
| 2281 | if opcode is None: |
| 2282 | if code == b"": |
| 2283 | raise ValueError("pickle exhausted before seeing STOP") |
| 2284 | else: |
| 2285 | raise ValueError("at position %s, opcode %r unknown" % ( |
| 2286 | "<unknown>" if pos is None else pos, |
| 2287 | code)) |
| 2288 | if opcode.arg is None: |
| 2289 | arg = None |
| 2290 | else: |
| 2291 | arg = opcode.arg.reader(data) |
| 2292 | if yield_end_pos: |
| 2293 | yield opcode, arg, pos, getpos() |
| 2294 | else: |
| 2295 | yield opcode, arg, pos |
| 2296 | if code == b'.': |
| 2297 | assert opcode.name == 'STOP' |
| 2298 | break |
| 2299 | |
| 2300 | def genops(pickle): |
| 2301 | """Generate all the opcodes in a pickle. |