示例#1
0
    def identify_distributions(self, files):
        unknown_files = set(files)
        found_package_count = 0

        venv_paths = map(self._get_venv_path, files)
        venv_paths = set(filter(None, venv_paths))

        venvs = []
        for venv_path in venv_paths:
            package_details, file_to_pkg = self._get_package_details(venv_path)
            local_pkgs = set(
                piputils.get_pip_packages(self._session,
                                          venv_path + "/bin/pip",
                                          restriction="local"))
            pkg_to_found_files = defaultdict(list)
            for path in set(unknown_files):  # Clone the set
                # The supplied path may be relative or absolute, but
                # file_to_pkg keys are absolute paths.
                fullpath = os.path.abspath(path)
                if fullpath in file_to_pkg:
                    unknown_files.remove(path)
                    pkg_to_found_files[file_to_pkg[fullpath]].append(
                        os.path.relpath(path, venv_path))

            # Some files, like venvs/dev/lib/python2.7/abc.py could be
            # symlinks populated by virtualenv itself during venv creation
            # since it relies on system wide python environment.  So we need
            # to resolve those into filenames which could be associated with
            # system wide installation of python
            for path in unknown_files.copy():
                if is_subpath(path, venv_path) and op.islink(path):
                    unknown_files.add(op.realpath(path))
                    unknown_files.remove(path)

            packages = []
            for name, details in iteritems(package_details):
                location = details["location"]
                packages.append(
                    VenvPackage(name=details["name"],
                                version=details["version"],
                                local=name in local_pkgs,
                                location=location,
                                editable=details["editable"],
                                files=pkg_to_found_files[name]))
                if location and not is_subpath(location, venv_path):
                    unknown_files.add(location)

            found_package_count += len(packages)

            venvs.append(
                VenvEnvironment(path=venv_path,
                                python_version=self._python_version(venv_path),
                                packages=packages))

        if venvs:
            yield (VenvDistribution(name="venv",
                                    venv_version=self._venv_version(),
                                    path=self._venv_exe_path(),
                                    environments=venvs), unknown_files)
示例#2
0
    def identify_distributions(self, paths):
        conda_paths = set()
        root_to_envs = defaultdict(list)
        # Start with all paths being set as unknown
        unknown_files = set(paths)
        # Track count of found packages and files
        found_package_count = 0
        total_file_count = len(unknown_files)

        # First, loop through all the files and identify conda paths
        for path in paths:
            conda_path = self._get_conda_env_path(path)
            if conda_path:
                if conda_path not in conda_paths:
                    conda_paths.add(conda_path)

        # Loop through conda_paths, find packages and create the
        # environments
        for idx, conda_path in enumerate(conda_paths):
            # Start with an empty channels list
            channels = []
            found_channel_names = set()

            # Find the root path for the environment
            # TODO: cache/memoize for those paths which have been considered
            # since will be asked again below
            conda_info = self._get_conda_info(conda_path)
            root_path = conda_info.get('root_prefix')
            if not root_path:
                lgr.warning(
                    "Could not find root path for conda environment %s" %
                    conda_path)
                continue
            # Retrieve the environment details
            env_export = self._get_conda_env_export(root_path, conda_path)
            (conda_package_details, file_to_pkg) = \
                self._get_conda_package_details(conda_path)
            (conda_pip_package_details, file_to_pip_pkg) = \
                self._get_conda_pip_package_details(env_export, conda_path)
            # Join our conda and pip packages
            conda_package_details.update(conda_pip_package_details)
            file_to_pkg.update(file_to_pip_pkg)

            # Initialize a map from packages to files that defaults to []
            pkg_to_found_files = defaultdict(list)

            # Get the conda path prefix to calculate relative paths
            path_prefix = conda_path + os.path.sep
            # Loop through unknown files, assigning them to packages if found
            for path in set(unknown_files):  # Clone the set
                if path in file_to_pkg:
                    # The file was found so remove from unknown file set
                    unknown_files.remove(path)
                    # Make relative paths if it is begins with the conda path
                    if path.startswith(path_prefix):
                        rel_path = path[len(path_prefix):]
                    else:
                        rel_path = path
                    # And add to the package
                    pkg_to_found_files[file_to_pkg[path]].append(rel_path)

            packages = []
            # Create the packages in the environment
            for package_name in conda_package_details:

                details = conda_package_details[package_name]

                # Look up or create the conda channel for the environment list
                channel_name = details.get("schannel")
                if channel_name:
                    if channel_name not in found_channel_names:
                        # New channel for our environment, so add it
                        channel_url = details.get("channel")
                        found_channel_names.add(channel_name)
                        channels.append(
                            CondaChannel(name=channel_name, url=channel_url))

                location = details.get("location")
                # Create the package
                package = CondaPackage(name=details.get("name"),
                                       installer=details.get("installer"),
                                       version=details.get("version"),
                                       build=details.get("build"),
                                       channel_name=channel_name,
                                       size=details.get("size"),
                                       md5=details.get("md5"),
                                       url=details.get("url"),
                                       location=location,
                                       editable=details.get("editable"),
                                       files=pkg_to_found_files[package_name])
                packages.append(package)

                # Make editable pip packages available to other tracers.
                if location and not is_subpath(location, conda_path):
                    unknown_files.add(location)

            # Give the distribution a name
            # Determine name from path (Alt approach: use conda-env info)
            if os.path.normpath(conda_path) == os.path.normpath(root_path):
                env_name = "root"
            else:
                env_name = os.path.basename(os.path.normpath(conda_path))

            # Keep track of found package count
            found_package_count += len(packages)

            # Create the conda environment (works with root environments too)
            conda_env = CondaEnvironment(name=env_name,
                                         path=conda_path,
                                         packages=packages,
                                         channels=channels)
            root_to_envs[root_path].append(conda_env)

        lgr.debug("%s: %d packages with %d files, and %d other files",
                  self.__class__.__name__, found_package_count,
                  total_file_count - len(unknown_files), len(unknown_files))

        # Find all the identified conda_roots
        conda_roots = root_to_envs.keys()
        # Loop through conda_roots and create the distributions
        for idx, root_path in enumerate(conda_roots):
            # Retrieve distribution details
            conda_info = self._get_conda_info(root_path)

            # Give the distribution a name
            if (len(conda_roots)) > 1:
                dist_name = 'conda-%d' % idx
            else:
                dist_name = 'conda'
            dist = CondaDistribution(
                name=dist_name,
                conda_version=conda_info.get("conda_version"),
                python_version=conda_info.get("python_version"),
                platform=conda_info.get("platform"),
                path=root_path,
                environments=root_to_envs[root_path])
            yield dist, unknown_files
示例#3
0
文件: venv.py 项目: eroesch/reproman
    def identify_distributions(self, files):
        unknown_files = set(files)
        found_package_count = 0

        venv_paths = map(self._get_venv_path, files)
        venv_paths = set(filter(None, venv_paths))

        venvs = []
        for venv_path in venv_paths:
            package_details, file_to_pkg = self._get_package_details(venv_path)
            local_pkgs = set(
                piputils.get_pip_packages(self._session,
                                          venv_path + "/bin/pip",
                                          restriction="local"))
            pkg_to_found_files = defaultdict(list)
            for path in set(unknown_files):  # Clone the set
                # The supplied path may be relative or absolute, but
                # file_to_pkg keys are absolute paths.
                fullpath = os.path.abspath(path)
                if fullpath in file_to_pkg:
                    unknown_files.remove(path)
                    pkg_to_found_files[file_to_pkg[fullpath]].append(
                        os.path.relpath(path, venv_path))

            # Some virtualenv files are links to system files. Files themselves
            # may be linked or they may be in a linked directory. We need to
            # resolve these links and pass them out as unknown files for other
            # tracers to use.
            for path in unknown_files.copy():
                if is_subpath(path, venv_path):
                    rpath = op.realpath(path)
                    # ... but the resolved link may point to another path under
                    # the environment (e.g., bin/python -> bin/python3), and we
                    # don't want to pass that back out as unknown.
                    if not is_subpath(rpath, venv_path):
                        unknown_files.add(rpath)
                    unknown_files.remove(path)

            packages = []
            for name, details in package_details.items():
                location = details["location"]
                packages.append(
                    VenvPackage(name=details["name"],
                                version=details["version"],
                                local=name in local_pkgs,
                                location=location,
                                editable=details["editable"],
                                files=pkg_to_found_files[name]))
                if location and not is_subpath(location, venv_path):
                    unknown_files.add(location)

            found_package_count += len(packages)

            venvs.append(
                VenvEnvironment(path=venv_path,
                                python_version=self._python_version(venv_path),
                                packages=packages))

        if venvs:
            yield (VenvDistribution(name="venv",
                                    venv_version=self._venv_version(),
                                    path=self._venv_exe_path(),
                                    environments=venvs), unknown_files)