| 348 | |
| 349 | @attr.s(frozen=True) |
| 350 | class PythonpathIsolationTest(object): |
| 351 | @staticmethod |
| 352 | def pex_info(inherit_path): |
| 353 | # type: (Union[str, bool]) -> PexInfo |
| 354 | return PexInfo.from_json(json.dumps({"inherit_path": inherit_path})) |
| 355 | |
| 356 | pythonpath = attr.ib() # type: str |
| 357 | dists = attr.ib() # type: Iterable[Distribution] |
| 358 | exe = attr.ib() # type: str |
| 359 | |
| 360 | def assert_isolation(self, inherit_path, expected_output): |
| 361 | # type: (Union[str, bool], str) -> None |
| 362 | env = dict(PYTHONPATH=self.pythonpath) |
| 363 | with temporary_dir() as temp_dir: |
| 364 | pex_builder = write_simple_pex( |
| 365 | temp_dir, |
| 366 | pex_info=self.pex_info(inherit_path), |
| 367 | dists=self.dists, |
| 368 | exe_contents=self.exe, |
| 369 | ) |
| 370 | |
| 371 | interpreter = PythonInterpreter.get() |
| 372 | if PY2: |
| 373 | # Under Python 2 venvs (created by Pex via Virtualenv 16.7.12), the venv interpreter |
| 374 | # can fail to resolve stdlib weakref internals. We side-step by just resolving out |
| 375 | # of the venv since this test is aimed squarely at PYTHONPATH isolation. |
| 376 | interpreter = interpreter.resolve_base_interpreter() |
| 377 | |
| 378 | # Test the PEX.run API. |
| 379 | process = PEX(pex_builder.path(), interpreter=interpreter).run( |
| 380 | stdout=subprocess.PIPE, |
| 381 | stderr=subprocess.PIPE, |
| 382 | env=env, |
| 383 | blocking=False, |
| 384 | ) |
| 385 | stdout, stderr = process.communicate() |
| 386 | assert process.returncode == 0, stderr.decode("utf-8") |
| 387 | assert expected_output == stdout.decode("utf-8") |
| 388 | |
| 389 | # Test direct PEX execution. |
| 390 | assert expected_output == subprocess.check_output( |
| 391 | [interpreter.binary, pex_builder.path()], env=env |
| 392 | ).decode("utf-8") |
| 393 | |
| 394 | |
| 395 | @pytest.fixture(scope="module") |
no outgoing calls