View on GitHub


1 hr
Test Coverage
from __future__ import (absolute_import, division, print_function,

import fnmatch
from glob import glob
import os
import logging

import plpacker.utils

LOGGER = logging.getLogger(__name__)

class FileSet(object):
    # pylint: disable=too-few-public-methods
    def __init__(self, directory, includes, excludes=(), followlinks=False):
        # Validate
        if directory is None:
            raise ValueError('"None" is not an acceptable "directory" value.')
        if not includes:
            raise ValueError('"includes" must be provided.')

        # Scalars to tuples
        if not isinstance(includes, (list, tuple)):
            includes = (includes,)
        if excludes and not isinstance(excludes, (list, tuple)):
            excludes = (excludes,)

        # Save = plpacker.utils.expand_path(directory, True)
        self.includes = (includes
                         if isinstance(includes, tuple) else tuple(includes))
        self.excludes = (excludes
                         if isinstance(excludes, tuple) else tuple(excludes))
        self.followlinks = followlinks
        self.fileset = self._expand_fileset()

    def __len__(self):
        return len(self.fileset)

    def __getitem__(self, index):
        return self.fileset[index]

    def __iter__(self):
        return iter(self.fileset)

    def pairs(self):
        return ((os.path.join(, item),
                 item) for item in self.fileset)

    def _expand_fileset(self):
        files = set()
        for include in self.includes:
            files.update(self._expand_glob(include, self.followlinks))

        for exclude in self.excludes:
            files = files.difference(
                self._expand_glob(exclude, self.followlinks))

        return tuple(sorted(item for item in files))

    def _expand_glob(self, expression, followlinks=False):
        if os.path.isabs(expression):
            raise ValueError('Absolute paths in globs are not supported: {}'

        if expression:
            full_glob = os.path.join(, expression)
            full_glob =

        if full_glob != os.path.normpath(full_glob):
            raise ValueError('Dots (".." or ".") are not permitted: {}'

        if '**' in expression:
            result = _find_files_recursively(full_glob, followlinks)
            result = _find_files(full_glob)
        directory_len = len( + 1
        return tuple(sorted(item[directory_len:] for item in result))

def _find_files_recursively(expression, followlinks=False):
    if '**' not in expression:
        raise ValueError('Glob is missing "**": {}'.format(expression))
    (directories, glob_part) = expression.rsplit('**', 1)
    if not glob_part:
        glob_part = '*'
    elif glob_part.startswith(os.path.sep):
        glob_part = glob_part[len(os.path.sep):]

    result = []
    for directory in glob(directories):
        for (dirpath, _, filenames) in os.walk(
                directory, followlinks=followlinks):
            for filename in fnmatch.filter(filenames, glob_part):
                result.append(os.path.join(dirpath, filename))
    return result

def _find_files(expression):
    items = []
    for item in glob(expression):
        if os.path.isfile(item):
    return items