"""Filename globbing utility."""



import sys

import os

import re

import fnmatch



__all__ = ["glob", "iglob"]



def glob(pathname):

    """Return a list of paths matching a pathname pattern.



    The pattern may contain simple shell-style wildcards a la fnmatch.



    """

    return list(iglob(pathname))



def iglob(pathname):

    """Return an iterator which yields the paths matching a pathname pattern.



    The pattern may contain simple shell-style wildcards a la fnmatch.



    """

    if not has_magic(pathname):

        if os.path.lexists(pathname):

            yield pathname

        return

    dirname, basename = os.path.split(pathname)

    if not dirname:

        for name in glob1(os.curdir, basename):

            yield name

        return

    if has_magic(dirname):

        dirs = iglob(dirname)

    else:

        dirs = [dirname]

    if has_magic(basename):

        glob_in_dir = glob1

    else:

        glob_in_dir = glob0

    for dirname in dirs:

        for name in glob_in_dir(dirname, basename):

            yield os.path.join(dirname, name)



# These 2 helper functions non-recursively glob inside a literal directory.

# They return a list of basenames. `glob1` accepts a pattern while `glob0`

# takes a literal basename (so it only has to check for its existence).



def glob1(dirname, pattern):

    if not dirname:

        dirname = os.curdir

    if isinstance(pattern, unicode) and not isinstance(dirname, unicode):

        dirname = unicode(dirname, sys.getfilesystemencoding() or

                                   sys.getdefaultencoding())

    try:

        names = os.listdir(dirname)

    except os.error:

        return []

    if pattern[0] != '.':

        names = filter(lambda x: x[0] != '.', names)

    return fnmatch.filter(names, pattern)



def glob0(dirname, basename):

    if basename == '':

        # `os.path.split()` returns an empty basename for paths ending with a

        # directory separator.  'q*x/' should match only directories.

        if os.path.isdir(dirname):

            return [basename]

    else:

        if os.path.lexists(os.path.join(dirname, basename)):

            return [basename]

    return []





magic_check = re.compile('[*?[]')



def has_magic(s):

    return magic_check.search(s) is not None

