1# Copyright 2009 Google Inc. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""A fake glob module implementation that uses fake_filesystem for unit tests.
16
17Includes:
18  FakeGlob: Uses a FakeFilesystem to provide a fake replacement for the
19    glob module.
20
21Usage:
22>>> from pyfakefs import fake_filesystem
23>>> from pyfakefs import fake_filesystem_glob
24>>> filesystem = fake_filesystem.FakeFilesystem()
25>>> glob_module = fake_filesystem_glob.FakeGlobModule(filesystem)
26
27>>> file = filesystem.CreateFile('new-file')
28>>> glob_module.glob('*')
29['new-file']
30>>> glob_module.glob('???-file')
31['new-file']
32"""
33
34import fnmatch
35import glob
36import os
37
38from pyfakefs import fake_filesystem
39
40
41class FakeGlobModule(object):
42  """Uses a FakeFilesystem to provide a fake replacement for glob module."""
43
44  def __init__(self, filesystem):
45    """Construct fake glob module using the fake filesystem.
46
47    Args:
48      filesystem:  FakeFilesystem used to provide file system information
49    """
50    self._glob_module = glob
51    self._os_module = fake_filesystem.FakeOsModule(filesystem)
52    self._path_module = self._os_module.path
53
54  def glob(self, pathname):  # pylint: disable-msg=C6409
55    """Return a list of paths matching a pathname pattern.
56
57    The pattern may contain shell-style wildcards a la fnmatch.
58
59    Args:
60      pathname: the pattern with which to find a list of paths
61
62    Returns:
63      List of strings matching the glob pattern.
64    """
65    if not self.has_magic(pathname):
66      if self._path_module.exists(pathname):
67        return [pathname]
68      else:
69        return []
70
71    dirname, basename = self._path_module.split(pathname)
72
73    if not dirname:
74      return self.glob1(self._path_module.curdir, basename)
75    elif self.has_magic(dirname):
76      path_list = self.glob(dirname)
77    else:
78      path_list = [dirname]
79
80    if not self.has_magic(basename):
81      result = []
82      for dirname in path_list:
83        if basename or self._path_module.isdir(dirname):
84          name = self._path_module.join(dirname, basename)
85          if self._path_module.exists(name):
86            result.append(name)
87    else:
88      result = []
89      for dirname in path_list:
90        sublist = self.glob1(dirname, basename)
91        for name in sublist:
92          result.append(self._path_module.join(dirname, name))
93
94    return result
95
96  def glob1(self, dirname, pattern):  # pylint: disable-msg=C6409
97    if not dirname:
98      dirname = self._path_module.curdir
99    try:
100      names = self._os_module.listdir(dirname)
101    except os.error:
102      return []
103    if pattern[0] != '.':
104      names = filter(lambda x: x[0] != '.', names)
105    return fnmatch.filter(names, pattern)
106
107  def __getattr__(self, name):
108    """Forwards any non-faked calls to the standard glob module."""
109    return getattr(self._glob_module, name)
110
111
112def _RunDoctest():
113  # pylint: disable-msg=C6111,C6204,W0406
114  import doctest
115  from pyfakefs import fake_filesystem_glob
116  return doctest.testmod(fake_filesystem_glob)
117
118
119if __name__ == '__main__':
120  _RunDoctest()
121