def _build_paths(self, name, spec_path_lists, exists): """ Given an environment variable name and specified paths, return a pathsep-separated string of paths containing unique, extant, directories from those paths and from the environment variable. Raise an error if no paths are resolved. Parameters ---------- name: str Environment variable name spec_path_lists: list of str Paths exists: bool It True, only return existing paths. Return ------ str Pathsep-separated paths """ # flatten spec_path_lists spec_paths = itertools.chain.from_iterable(spec_path_lists) env_paths = environ.get(name, '').split(pathsep) paths = itertools.chain(spec_paths, env_paths) extant_paths = list(filter(isdir, paths)) if exists else paths if not extant_paths: msg = "%s environment variable is empty" % name.upper() raise distutils.errors.DistutilsPlatformError(msg) unique_paths = unique_everseen(extant_paths) return pathsep.join(unique_paths)
def find_packages( *, namespaces=True, fill_package_dir: Optional[Dict[str, str]] = None, root_dir: Optional[_Path] = None, **kwargs ) -> List[str]: """Works similarly to :func:`setuptools.find_packages`, but with all arguments given as keyword arguments. Moreover, ``where`` can be given as a list (the results will be simply concatenated). When the additional keyword argument ``namespaces`` is ``True``, it will behave like :func:`setuptools.find_namespace_packages`` (i.e. include implicit namespaces as per :pep:`420`). The ``where`` argument will be considered relative to ``root_dir`` (or the current working directory when ``root_dir`` is not given). If the ``fill_package_dir`` argument is passed, this function will consider it as a similar data structure to the ``package_dir`` configuration parameter add fill-in any missing package location. :rtype: list """ from setuptools.discovery import construct_package_dir from setuptools.extern.more_itertools import unique_everseen, always_iterable if namespaces: from setuptools.discovery import PEP420PackageFinder as PackageFinder else: from setuptools.discovery import PackageFinder # type: ignore root_dir = root_dir or os.curdir where = kwargs.pop('where', ['.']) packages: List[str] = [] fill_package_dir = {} if fill_package_dir is None else fill_package_dir search = list(unique_everseen(always_iterable(where))) if len(search) == 1 and all(not _same_path(search[0], x) for x in (".", root_dir)): fill_package_dir.setdefault("", search[0]) for path in search: package_path = _nest_path(root_dir, path) pkgs = PackageFinder.find(package_path, **kwargs) packages.extend(pkgs) if pkgs and not ( fill_package_dir.get("") == path or os.path.samefile(package_path, root_dir) ): fill_package_dir.update(construct_package_dir(pkgs, path)) return packages
def exclude_data_files(self, package, src_dir, files): """Filter filenames for package's data files in 'src_dir'""" files = list(files) patterns = self._get_platform_patterns( self.exclude_package_data, package, src_dir, ) match_groups = (fnmatch.filter(files, pattern) for pattern in patterns) # flatten the groups of matches into an iterable of matches matches = itertools.chain.from_iterable(match_groups) bad = set(matches) keepers = (fn for fn in files if fn not in bad) # ditch dupes return list(unique_everseen(keepers))
def _finalize_license_files(self): """Compute names of all license files which should be included.""" license_files: Optional[List[str]] = self.metadata.license_files patterns: List[str] = license_files if license_files else [] license_file: Optional[str] = self.metadata.license_file if license_file and license_file not in patterns: patterns.append(license_file) if license_files is None and license_file is None: # Default patterns match the ones wheel uses # See https://wheel.readthedocs.io/en/stable/user_guide.html # -> 'Including license files in the generated wheel file' patterns = ('LICEN[CS]E*', 'COPYING*', 'NOTICE*', 'AUTHORS*') self.metadata.license_files = list( unique_everseen(self._expand_patterns(patterns)))
def paths_on_pythonpath(paths): """ Add the indicated paths to the head of the PYTHONPATH environment variable so that subprocesses will also see the packages at these paths. Do this in a context that restores the value on exit. """ nothing = object() orig_pythonpath = os.environ.get('PYTHONPATH', nothing) current_pythonpath = os.environ.get('PYTHONPATH', '') try: prefix = os.pathsep.join(unique_everseen(paths)) to_join = filter(None, [prefix, current_pythonpath]) new_path = os.pathsep.join(to_join) if new_path: os.environ['PYTHONPATH'] = new_path yield finally: if orig_pythonpath is nothing: os.environ.pop('PYTHONPATH', None) else: os.environ['PYTHONPATH'] = orig_pythonpath
def wrapper(*args, **kwargs): return unique_everseen(func(*args, **kwargs))