filesystem_mock.py 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. # Copyright (c) 2011 The Chromium Authors. All rights reserved.
  2. # Use of this source code is governed by a BSD-style license that can be
  3. # found in the LICENSE file.
  4. import errno
  5. import os
  6. import re
  7. import StringIO
  8. def _RaiseNotFound(path):
  9. raise IOError(errno.ENOENT, path, os.strerror(errno.ENOENT))
  10. class MockFileSystem(object):
  11. """Stripped-down version of WebKit's webkitpy.common.system.filesystem_mock
  12. Implements a filesystem-like interface on top of a dict of filenames ->
  13. file contents. A file content value of None indicates that the file should
  14. not exist (IOError will be raised if it is opened;
  15. reading from a missing key raises a KeyError, not an IOError."""
  16. def __init__(self, files=None):
  17. self.files = files or {}
  18. self.written_files = {}
  19. self._sep = '/'
  20. @property
  21. def sep(self):
  22. return self._sep
  23. def _split(self, path):
  24. return path.rsplit(self.sep, 1)
  25. def abspath(self, path):
  26. if path.endswith(self.sep):
  27. return path[:-1]
  28. return path
  29. def dirname(self, path):
  30. if self.sep not in path:
  31. return ''
  32. return self._split(path)[0] or self.sep
  33. def exists(self, path):
  34. return self.isfile(path) or self.isdir(path)
  35. def isfile(self, path):
  36. return path in self.files and self.files[path] is not None
  37. def isdir(self, path):
  38. if path in self.files:
  39. return False
  40. if not path.endswith(self.sep):
  41. path += self.sep
  42. # We need to use a copy of the keys here in order to avoid switching
  43. # to a different thread and potentially modifying the dict in
  44. # mid-iteration.
  45. files = self.files.keys()[:]
  46. return any(f.startswith(path) for f in files)
  47. def join(self, *comps):
  48. # TODO: Might want tests for this and/or a better comment about how
  49. # it works.
  50. return re.sub(re.escape(os.path.sep), self.sep, os.path.join(*comps))
  51. def open_for_reading(self, path):
  52. return StringIO.StringIO(self.read_binary_file(path))
  53. def read_binary_file(self, path):
  54. # Intentionally raises KeyError if we don't recognize the path.
  55. if self.files[path] is None:
  56. _RaiseNotFound(path)
  57. return self.files[path]