summaryrefslogtreecommitdiff
path: root/sphinx/util/osutil.py
diff options
context:
space:
mode:
Diffstat (limited to 'sphinx/util/osutil.py')
-rw-r--r--sphinx/util/osutil.py130
1 files changed, 130 insertions, 0 deletions
diff --git a/sphinx/util/osutil.py b/sphinx/util/osutil.py
new file mode 100644
index 000000000..beab38cbd
--- /dev/null
+++ b/sphinx/util/osutil.py
@@ -0,0 +1,130 @@
+# -*- coding: utf-8 -*-
+"""
+ sphinx.util.osutil
+ ~~~~~~~~~~~~~~~~~~
+
+ Operating system-related utility functions for Sphinx.
+
+ :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
+ :license: BSD, see LICENSE for details.
+"""
+
+import os
+import re
+import time
+import errno
+import shutil
+from os import path
+
+# Errnos that we need.
+EEXIST = getattr(errno, 'EEXIST', 0)
+ENOENT = getattr(errno, 'ENOENT', 0)
+EPIPE = getattr(errno, 'EPIPE', 0)
+
+# SEP separates path elements in the canonical file names
+#
+# Define SEP as a manifest constant, not so much because we expect it to change
+# in the future as to avoid the suspicion that a stray "/" in the code is a
+# hangover from more *nix-oriented origins.
+SEP = "/"
+
+def os_path(canonicalpath):
+ return canonicalpath.replace(SEP, path.sep)
+
+
+def relative_uri(base, to):
+ """Return a relative URL from ``base`` to ``to``."""
+ if to.startswith(SEP):
+ return to
+ b2 = base.split(SEP)
+ t2 = to.split(SEP)
+ # remove common segments
+ for x, y in zip(b2, t2):
+ if x != y:
+ break
+ b2.pop(0)
+ t2.pop(0)
+ return ('..' + SEP) * (len(b2)-1) + SEP.join(t2)
+
+
+def ensuredir(path):
+ """Ensure that a path exists."""
+ try:
+ os.makedirs(path)
+ except OSError, err:
+ # 0 for Jython/Win32
+ if err.errno not in [0, EEXIST]:
+ raise
+
+
+def walk(top, topdown=True, followlinks=False):
+ """
+ Backport of os.walk from 2.6, where the followlinks argument was added.
+ """
+ names = os.listdir(top)
+
+ dirs, nondirs = [], []
+ for name in names:
+ if path.isdir(path.join(top, name)):
+ dirs.append(name)
+ else:
+ nondirs.append(name)
+
+ if topdown:
+ yield top, dirs, nondirs
+ for name in dirs:
+ fullpath = path.join(top, name)
+ if followlinks or not path.islink(fullpath):
+ for x in walk(fullpath, topdown, followlinks):
+ yield x
+ if not topdown:
+ yield top, dirs, nondirs
+
+
+def mtimes_of_files(dirnames, suffix):
+ for dirname in dirnames:
+ for root, dirs, files in os.walk(dirname):
+ for sfile in files:
+ if sfile.endswith(suffix):
+ try:
+ yield path.getmtime(path.join(root, sfile))
+ except EnvironmentError:
+ pass
+
+
+def movefile(source, dest):
+ """Move a file, removing the destination if it exists."""
+ if os.path.exists(dest):
+ try:
+ os.unlink(dest)
+ except OSError:
+ pass
+ os.rename(source, dest)
+
+
+def copytimes(source, dest):
+ """Copy a file's modification times."""
+ st = os.stat(source)
+ if hasattr(os, 'utime'):
+ os.utime(dest, (st.st_atime, st.st_mtime))
+
+
+def copyfile(source, dest):
+ """Copy a file and its modification times, if possible."""
+ shutil.copyfile(source, dest)
+ try:
+ # don't do full copystat because the source may be read-only
+ copytimes(source, dest)
+ except OSError:
+ pass
+
+
+no_fn_re = re.compile(r'[^a-zA-Z0-9_-]')
+
+def make_filename(string):
+ return no_fn_re.sub('', string)
+
+
+def ustrftime(format, *args):
+ # strftime for unicode strings
+ return time.strftime(unicode(format).encode('utf-8'), *args).decode('utf-8')