pickle ``obj`` to a file, then unpickle it in a new interpreter. ``code`` is Python source run by that interpreter, which receives the name of the pickle file as ``sys.argv[1]``. The new interpreter has the current ``sys.path``, so that the SQLAlchemy under test, as well as the ``t
(obj, code)
| 66 | |
| 67 | |
| 68 | def unpickle_in_subprocess(obj, code): |
| 69 | """pickle ``obj`` to a file, then unpickle it in a new interpreter. |
| 70 | |
| 71 | ``code`` is Python source run by that interpreter, which receives the |
| 72 | name of the pickle file as ``sys.argv[1]``. The new interpreter has |
| 73 | the current ``sys.path``, so that the SQLAlchemy under test, as well |
| 74 | as the ``test`` package, are importable. |
| 75 | |
| 76 | Returns the stripped stdout of the subprocess; a non-zero exit status |
| 77 | fails the test, reporting its stderr. |
| 78 | |
| 79 | """ |
| 80 | |
| 81 | fd, filename = mkstemp("pkl") |
| 82 | try: |
| 83 | with os.fdopen(fd, "wb") as file_: |
| 84 | pickle.dump(obj, file_) |
| 85 | |
| 86 | parts = list(sys.path) |
| 87 | if os.environ.get("PYTHONPATH"): |
| 88 | parts.append(os.environ["PYTHONPATH"]) |
| 89 | |
| 90 | proc = subprocess.run( |
| 91 | [sys.executable, "-c", code, filename.replace(os.sep, "/")], |
| 92 | stdout=subprocess.PIPE, |
| 93 | stderr=subprocess.PIPE, |
| 94 | env={**os.environ, "PYTHONPATH": os.pathsep.join(parts)}, |
| 95 | ) |
| 96 | finally: |
| 97 | os.unlink(filename) |
| 98 | |
| 99 | if proc.returncode != 0: |
| 100 | raise AssertionError( |
| 101 | "subprocess failed: %s" % proc.stderr.decode(errors="replace") |
| 102 | ) |
| 103 | return proc.stdout.strip() |
| 104 | |
| 105 | |
| 106 | def random_choices(population, k=1): |