# Path: gears/exceptions.py
# class ImproperlyConfigured(Exception):
#     pass
# 
# class FileNotFound(Exception):
#     pass
# 
# Path: gears/utils.py
# def safe_join(base, *paths):
#     if not os.path.isabs(base):
#         raise ValueError("%r is not an absolute path." % base)
#     base = os.path.normpath(base)
#     path = os.path.normpath(os.path.join(base, *paths))
#     if not path.startswith(base):
#         raise ValueError("Path %r is outside of %r" % (path, base))
#     return path


import os
import glob2
from .exceptions import ImproperlyConfigured, FileNotFound
from .utils import safe_join
        if not isinstance(directories, (list, tuple)):
            raise ImproperlyConfigured(
                "FileSystemFinder's 'directories' parameter is not a "
                "tuple or list; perhaps you forgot a trailing comma?")
        for directory in directories:
            if directory not in self.locations:
                self.locations.append(directory)

    @property
    def paths(self):
        return self.locations

    def find(self, path):
        for matched_path in self.find_all(path):
            return matched_path
        raise FileNotFound(path)

    def find_all(self, path):
        for root in self.locations:
            matched_path = self.find_location(root, path)
            if matched_path:
                yield matched_path

    def find_location(self, root, path):
        path = safe_join(root, path)
        if os.path.exists(path):
            return path

    def list(self, path):
        for root in self.locations:

# Path: gears/exceptions.py
# class ImproperlyConfigured(Exception):
#     pass
# 
# class FileNotFound(Exception):
#     pass
# 
# Path: gears/utils.py
# def safe_join(base, *paths):
#     if not os.path.isabs(base):
#         raise ValueError("%r is not an absolute path." % base)
#     base = os.path.normpath(base)
#     path = os.path.normpath(os.path.join(base, *paths))
#     if not path.startswith(base):
#         raise ValueError("Path %r is outside of %r" % (path, base))
#     return path


# Path: gears/finders.py
import os
import glob2
from .exceptions import ImproperlyConfigured, FileNotFound
from .utils import safe_join

        if not isinstance(directories, (list, tuple)):
            raise ImproperlyConfigured(
                "FileSystemFinder's 'directories' parameter is not a "
                "tuple or list; perhaps you forgot a trailing comma?")
        for directory in directories:
            if directory not in self.locations:
                self.locations.append(directory)

    @property
    def paths(self):
        return self.locations

    def find(self, path):
        for matched_path in self.find_all(path):
            return matched_path
        raise FileNotFound(path)

    def find_all(self, path):
        for root in self.locations:
            matched_path = self.find_location(root, path)
            if matched_path:
                yield matched_path

    def find_location(self, root, path):
        path = safe_join(root, path)
        if os.path.exists(path):
            return path

    def list(self, path):
        for root in self.locations:

            for absolute_path in glob2.iglob(safe_join(root, path)):