diff --git a/sphinx/util/osutil.py b/sphinx/util/osutil.py index 2b3fe51b0..3751fcc08 100644 --- a/sphinx/util/osutil.py +++ b/sphinx/util/osutil.py @@ -19,14 +19,11 @@ import time import warnings from io import StringIO from os import path +from typing import Any, Generator, Iterator, List, Tuple, Type from sphinx.deprecation import RemovedInSphinx30Warning, RemovedInSphinx40Warning from sphinx.testing.path import path as Path -if False: - # For type annotation - from typing import Any, Iterator, List, Tuple # NOQA - # Errnos that we need. EEXIST = getattr(errno, 'EEXIST', 0) # RemovedInSphinx40Warning ENOENT = getattr(errno, 'ENOENT', 0) # RemovedInSphinx40Warning @@ -41,19 +38,16 @@ EINVAL = getattr(errno, 'EINVAL', 0) # RemovedInSphinx40Warning SEP = "/" -def os_path(canonicalpath): - # type: (str) -> str +def os_path(canonicalpath: str) -> str: return canonicalpath.replace(SEP, path.sep) -def canon_path(nativepath): - # type: (str) -> str +def canon_path(nativepath: str) -> str: """Return path in OS-independent form""" return nativepath.replace(path.sep, SEP) -def relative_uri(base, to): - # type: (str, str) -> str +def relative_uri(base: str, to: str) -> str: """Return a relative URL from ``base`` to ``to``.""" if to.startswith(SEP): return to @@ -76,22 +70,19 @@ def relative_uri(base, to): return ('..' + SEP) * (len(b2) - 1) + SEP.join(t2) -def ensuredir(path): - # type: (str) -> None +def ensuredir(path: str) -> None: """Ensure that a path exists.""" os.makedirs(path, exist_ok=True) -def walk(top, topdown=True, followlinks=False): - # type: (str, bool, bool) -> Iterator[Tuple[str, List[str], List[str]]] +def walk(top: str, topdown: bool = True, followlinks: bool = False) -> Iterator[Tuple[str, List[str], List[str]]]: # NOQA warnings.warn('sphinx.util.osutil.walk() is deprecated for removal. ' 'Please use os.walk() instead.', RemovedInSphinx40Warning) return os.walk(top, topdown=topdown, followlinks=followlinks) -def mtimes_of_files(dirnames, suffix): - # type: (List[str], str) -> Iterator[float] +def mtimes_of_files(dirnames: List[str], suffix: str) -> Iterator[float]: for dirname in dirnames: for root, dirs, files in os.walk(dirname): for sfile in files: @@ -102,8 +93,7 @@ def mtimes_of_files(dirnames, suffix): pass -def movefile(source, dest): - # type: (str, str) -> None +def movefile(source: str, dest: str) -> None: """Move a file, removing the destination if it exists.""" if os.path.exists(dest): try: @@ -113,16 +103,14 @@ def movefile(source, dest): os.rename(source, dest) -def copytimes(source, dest): - # type: (str, str) -> None +def copytimes(source: str, dest: str) -> None: """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): - # type: (str, str) -> None +def copyfile(source: str, dest: str) -> None: """Copy a file and its modification times, if possible. Note: ``copyfile`` skips copying if the file has not been changed""" @@ -139,18 +127,15 @@ no_fn_re = re.compile(r'[^a-zA-Z0-9_-]') project_suffix_re = re.compile(' Documentation$') -def make_filename(string): - # type: (str) -> str +def make_filename(string: str) -> str: return no_fn_re.sub('', string) or 'sphinx' -def make_filename_from_project(project): - # type: (str) -> str +def make_filename_from_project(project: str) -> str: return make_filename(project_suffix_re.sub('', project)).lower() -def ustrftime(format, *args): - # type: (str, Any) -> str +def ustrftime(format: str, *args) -> str: """[DEPRECATED] strftime for unicode strings.""" warnings.warn('sphinx.util.osutil.ustrtime is deprecated for removal', RemovedInSphinx30Warning, stacklevel=2) @@ -171,8 +156,7 @@ def ustrftime(format, *args): return r.encode().decode('unicode-escape') -def relpath(path, start=os.curdir): - # type: (str, str) -> str +def relpath(path: str, start: str = os.curdir) -> str: """Return a relative filepath to *path* either from the current directory or from an optional *start* directory. @@ -189,8 +173,7 @@ safe_relpath = relpath # for compatibility fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() -def abspath(pathdir): - # type: (str) -> str +def abspath(pathdir: str) -> str: if isinstance(pathdir, Path): return pathdir.abspath() else: @@ -205,8 +188,7 @@ def abspath(pathdir): return pathdir -def getcwd(): - # type: () -> str +def getcwd() -> str: warnings.warn('sphinx.util.osutil.getcwd() is deprecated. ' 'Please use os.getcwd() instead.', RemovedInSphinx40Warning) @@ -214,8 +196,7 @@ def getcwd(): @contextlib.contextmanager -def cd(target_dir): - # type: (str) -> Iterator[None] +def cd(target_dir: str) -> Generator[None, None, None]: cwd = os.getcwd() try: os.chdir(target_dir) @@ -236,19 +217,16 @@ class FileAvoidWrite: Objects can be used as context managers. """ - def __init__(self, path): - # type: (str) -> None + def __init__(self, path: str) -> None: self._path = path self._io = None # type: StringIO - def write(self, data): - # type: (str) -> None + def write(self, data: str) -> None: if not self._io: self._io = StringIO() self._io.write(data) - def close(self): - # type: () -> None + def close(self) -> None: """Stop accepting writes and write file, if needed.""" if not self._io: raise Exception('FileAvoidWrite does not support empty files.') @@ -267,16 +245,14 @@ class FileAvoidWrite: with open(self._path, 'w') as f: f.write(buf) - def __enter__(self): - # type: () -> FileAvoidWrite + def __enter__(self) -> "FileAvoidWrite": return self - def __exit__(self, type, value, traceback): - # type: (str, str, str) -> None + def __exit__(self, exc_type: Type[Exception], exc_value: Exception, traceback: Any) -> bool: # NOQA self.close() + return True - def __getattr__(self, name): - # type: (str) -> Any + def __getattr__(self, name: str) -> Any: # Proxy to _io instance. if not self._io: raise Exception('Must write to FileAvoidWrite before other ' @@ -285,8 +261,7 @@ class FileAvoidWrite: return getattr(self._io, name) -def rmtree(path): - # type: (str) -> None +def rmtree(path: str) -> None: if os.path.isdir(path): shutil.rmtree(path) else: