def isolated(): """Returns a chroot for third_party isolated from the ``sys.path``. PEX will typically be installed in site-packages flat alongside many other distributions; as such, adding the location of the pex distribution to the ``sys.path`` will typically expose many other distributions. An isolated chroot can be used as a ``sys.path`` entry to effect only the exposure of pex. :return: The path of the chroot. :rtype: str """ global _ISOLATED if _ISOLATED is None: from pex import vendor from pex.common import safe_mkdtemp, Chroot chroot = Chroot(safe_mkdtemp()) with _tracer().timed('Isolating pex in {}'.format(chroot)): pex_path = os.path.join(vendor.VendorSpec.ROOT, 'pex') for root, _, files in os.walk(pex_path): for f in files: if not f.endswith('.pyc'): abs_file_path = os.path.join(root, f) relpath = os.path.relpath(abs_file_path, pex_path) chroot.copy(abs_file_path, os.path.join('pex', relpath), label='pex') _ISOLATED = chroot return _ISOLATED.path()
def __init__(self, path=None, interpreter=None, chroot=None, pex_info=None, preamble=None, copy=False): """Initialize a pex builder. :keyword path: The path to write the PEX as it is built. If ``None`` is specified, a temporary directory will be created. :keyword interpreter: The interpreter to use to build this PEX environment. If ``None`` is specified, the current interpreter is used. :keyword chroot: If specified, preexisting :class:`Chroot` to use for building the PEX. :keyword pex_info: A preexisting PexInfo to use to build the PEX. :keyword preamble: If supplied, execute this code prior to bootstrapping this PEX environment. :type preamble: str :keyword copy: If False, attempt to create the pex environment via hard-linking, falling back to copying across devices. If True, always copy. .. versionchanged:: 0.8 The temporary directory created when ``path`` is not specified is now garbage collected on interpreter exit. """ self._interpreter = interpreter or PythonInterpreter.get() self._chroot = chroot or Chroot(path or safe_mkdtemp()) self._pex_info = pex_info or PexInfo.default(self._interpreter) self._preamble = preamble or '' self._copy = copy self._shebang = self._interpreter.identity.hashbang() self._logger = logging.getLogger(__name__) self._frozen = False self._distributions = set()
def assert_chroot_perms(copyfn): with temporary_dir() as src: one = os.path.join(src, "one") touch(one) two = os.path.join(src, "two") touch(two) chmod_plus_x(two) with temporary_dir() as dst: chroot = Chroot(dst) copyfn(chroot, one, "one") copyfn(chroot, two, "two") assert extract_perms(one) == extract_perms( os.path.join(chroot.path(), "one")) assert extract_perms(two) == extract_perms( os.path.join(chroot.path(), "two")) zip_path = os.path.join(src, "chroot.zip") chroot.zip(zip_path) with temporary_dir() as extract_dir: with contextlib.closing(PermPreservingZipFile(zip_path)) as zf: zf.extractall(extract_dir) assert extract_perms(one) == extract_perms( os.path.join(extract_dir, "one")) assert extract_perms(two) == extract_perms( os.path.join(extract_dir, "two"))
def assert_chroot_perms(copyfn): with temporary_dir() as src: one = os.path.join(src, 'one') touch(one) two = os.path.join(src, 'two') touch(two) chmod_plus_x(two) with temporary_dir() as dst: chroot = Chroot(dst) copyfn(chroot, one, 'one') copyfn(chroot, two, 'two') assert extract_perms(one) == extract_perms(os.path.join(chroot.path(), 'one')) assert extract_perms(two) == extract_perms(os.path.join(chroot.path(), 'two')) zip_path = os.path.join(src, 'chroot.zip') chroot.zip(zip_path) with temporary_dir() as extract_dir: with contextlib.closing(PermPreservingZipFile(zip_path)) as zf: zf.extractall(extract_dir) assert extract_perms(one) == extract_perms(os.path.join(extract_dir, 'one')) assert extract_perms(two) == extract_perms(os.path.join(extract_dir, 'two'))
def test_chroot_zip(): with temporary_dir() as tmp: chroot = Chroot(os.path.join(tmp, "chroot")) chroot.write(b"data", "directory/subdirectory/file") zip_dst = os.path.join(tmp, "chroot.zip") chroot.zip(zip_dst) with open_zip(zip_dst) as zip: assert [ "directory/", "directory/subdirectory/", "directory/subdirectory/file", ] == sorted(zip.namelist()) assert b"" == zip.read("directory/") assert b"" == zip.read("directory/subdirectory/") assert b"data" == zip.read("directory/subdirectory/file")
def __init__( self, path=None, # type: Optional[str] interpreter=None, # type: Optional[PythonInterpreter] chroot=None, # type: Optional[Chroot] pex_info=None, # type: Optional[PexInfo] preamble=None, # type: Optional[str] copy_mode=CopyMode.LINK, # type: CopyMode.Value include_tools=False, # type: bool ): # type: (...) -> None """Initialize a pex builder. :keyword path: The path to write the PEX as it is built. If ``None`` is specified, a temporary directory will be created. :keyword interpreter: The interpreter to use to build this PEX environment. If ``None`` is specified, the current interpreter is used. :keyword chroot: If specified, preexisting :class:`Chroot` to use for building the PEX. :keyword pex_info: A preexisting PexInfo to use to build the PEX. :keyword preamble: If supplied, execute this code prior to bootstrapping this PEX environment. :keyword copy_mode: Create the pex environment using the given copy mode. :keyword include_tools: If True, include runtime tools which can be executed by exporting `PEX_TOOLS=1`. .. versionchanged:: 0.8 The temporary directory created when ``path`` is not specified is now garbage collected on interpreter exit. """ self._interpreter = interpreter or PythonInterpreter.get() self._chroot = chroot or Chroot(path or safe_mkdtemp()) self._pex_info = pex_info or PexInfo.default(self._interpreter) self._preamble = preamble or "" self._copy_mode = copy_mode self._include_tools = include_tools self._shebang = self._interpreter.identity.hashbang() self._logger = logging.getLogger(__name__) self._frozen = False self._distributions = {} # type: Dict[str, Distribution]
def test_chroot_zip_symlink(): # type: () -> None with temporary_dir() as tmp: chroot = Chroot(os.path.join(tmp, "chroot")) chroot.write(b"data", "directory/subdirectory/file") chroot.symlink( os.path.join(chroot.path(), "directory/subdirectory/file"), "directory/subdirectory/symlinked", ) cwd = os.getcwd() try: os.chdir(os.path.join(chroot.path(), "directory/subdirectory")) chroot.symlink( "file", "directory/subdirectory/rel-symlinked", ) finally: os.chdir(cwd) chroot.symlink(os.path.join(chroot.path(), "directory"), "symlinked") zip_dst = os.path.join(tmp, "chroot.zip") chroot.zip(zip_dst) with open_zip(zip_dst) as zip: assert [ "directory/", "directory/subdirectory/", "directory/subdirectory/file", "directory/subdirectory/rel-symlinked", "directory/subdirectory/symlinked", "symlinked/", "symlinked/subdirectory/", "symlinked/subdirectory/file", "symlinked/subdirectory/rel-symlinked", "symlinked/subdirectory/symlinked", ] == sorted(zip.namelist()) assert b"" == zip.read("directory/") assert b"" == zip.read("directory/subdirectory/") assert b"data" == zip.read("directory/subdirectory/file") assert b"data" == zip.read("directory/subdirectory/rel-symlinked") assert b"data" == zip.read("directory/subdirectory/symlinked") assert b"" == zip.read("symlinked/") assert b"" == zip.read("symlinked/subdirectory/") assert b"data" == zip.read("symlinked/subdirectory/file") assert b"data" == zip.read("symlinked/subdirectory/rel-symlinked") assert b"data" == zip.read("symlinked/subdirectory/symlinked")