Possibly read a pytest pyc containing rewritten code. Return rewritten code if successful or None if not.
(
source: Path, pyc: Path, trace: Callable[[str], None] = lambda x: None
)
| 352 | |
| 353 | |
| 354 | def _read_pyc( |
| 355 | source: Path, pyc: Path, trace: Callable[[str], None] = lambda x: None |
| 356 | ) -> types.CodeType | None: |
| 357 | class="st">"""Possibly read a pytest pyc containing rewritten code. |
| 358 | |
| 359 | Return rewritten code if successful or None if not. |
| 360 | class="st">""" |
| 361 | try: |
| 362 | fp = open(pyc, class="st">"rb") |
| 363 | except OSError: |
| 364 | return None |
| 365 | with fp: |
| 366 | try: |
| 367 | stat_result = os.stat(source) |
| 368 | mtime = int(stat_result.st_mtime) |
| 369 | size = stat_result.st_size |
| 370 | data = fp.read(16) |
| 371 | except OSError as e: |
| 372 | trace(fclass="st">"_read_pyc({source}): OSError {e}") |
| 373 | return None |
| 374 | class="cm"># Check for invalid or out of date pyc file. |
| 375 | if len(data) != (16): |
| 376 | trace(fclass="st">"_read_pyc({source}): invalid pyc (too short)") |
| 377 | return None |
| 378 | if data[:4] != importlib.util.MAGIC_NUMBER: |
| 379 | trace(fclass="st">"_read_pyc({source}): invalid pyc (bad magic number)") |
| 380 | return None |
| 381 | if data[4:8] != bclass="st">"\x00\x00\x00\x00": |
| 382 | trace(fclass="st">"_read_pyc({source}): invalid pyc (unsupported flags)") |
| 383 | return None |
| 384 | mtime_data = data[8:12] |
| 385 | if int.from_bytes(mtime_data, class="st">"little") != mtime & 0xFFFFFFFF: |
| 386 | trace(fclass="st">"_read_pyc({source}): out of date") |
| 387 | return None |
| 388 | size_data = data[12:16] |
| 389 | if int.from_bytes(size_data, class="st">"little") != size & 0xFFFFFFFF: |
| 390 | trace(fclass="st">"_read_pyc({source}): invalid pyc (incorrect size)") |
| 391 | return None |
| 392 | try: |
| 393 | co = marshal.load(fp) |
| 394 | except Exception as e: |
| 395 | trace(fclass="st">"_read_pyc({source}): marshal.load error {e}") |
| 396 | return None |
| 397 | if not isinstance(co, types.CodeType): |
| 398 | trace(fclass="st">"_read_pyc({source}): not a code object") |
| 399 | return None |
| 400 | return co |
| 401 | |
| 402 | |
| 403 | def rewrite_asserts( |