diff --git a/Lib/_dummy_os.py b/Lib/_dummy_os.py new file mode 100644 index 000000000..910f469c6 --- /dev/null +++ b/Lib/_dummy_os.py @@ -0,0 +1,61 @@ +""" +A shim of the os module containing only simple path-related utilities +""" + +try: + from os import * +except ImportError: + import abc + + # this will throw an appropriate error if os isn't available and a module + # tries to use an os function. If os has become available, then this will + # just work. + def __getattr__(name): + import os + return getattr(os, name) + + + sep = '/' + + + def fspath(path): + """Return the path representation of a path-like object. + + If str or bytes is passed in, it is returned unchanged. Otherwise the + os.PathLike interface is used to get the path representation. If the + path representation is not str or bytes, TypeError is raised. If the + provided path is not str, bytes, or os.PathLike, TypeError is raised. + """ + if isinstance(path, (str, bytes)): + return path + + # Work from the object's type to match method resolution of other magic + # methods. + path_type = type(path) + try: + path_repr = path_type.__fspath__(path) + except AttributeError: + if hasattr(path_type, '__fspath__'): + raise + else: + raise TypeError("expected str, bytes or os.PathLike object, " + "not " + path_type.__name__) + if isinstance(path_repr, (str, bytes)): + return path_repr + else: + raise TypeError("expected {}.__fspath__() to return str or bytes, " + "not {}".format(path_type.__name__, + type(path_repr).__name__)) + + class PathLike(abc.ABC): + + """Abstract base class for implementing the file system path protocol.""" + + @abc.abstractmethod + def __fspath__(self): + """Return the file system path representation of the object.""" + raise NotImplementedError + + @classmethod + def __subclasshook__(cls, subclass): + return hasattr(subclass, '__fspath__') diff --git a/Lib/genericpath.py b/Lib/genericpath.py index 5dd703d73..e790d7468 100644 --- a/Lib/genericpath.py +++ b/Lib/genericpath.py @@ -3,7 +3,10 @@ Path operations common to more than one OS Do not use directly. The OS specific modules import the appropriate functions from this module themselves. """ -import os +try: + import os +except ImportError: + import _dummy_os as os import stat __all__ = ['commonprefix', 'exists', 'getatime', 'getctime', 'getmtime', diff --git a/Lib/io.py b/Lib/io.py index ee701d2c2..3f497b311 100644 --- a/Lib/io.py +++ b/Lib/io.py @@ -52,12 +52,17 @@ import _io import abc from _io import (DEFAULT_BUFFER_SIZE, BlockingIOError, UnsupportedOperation, - open, open_code, FileIO, BytesIO, StringIO, BufferedReader, + open, open_code, BytesIO, StringIO, BufferedReader, BufferedWriter, BufferedRWPair, BufferedRandom, # XXX RUSTPYTHON TODO: IncrementalNewlineDecoder # IncrementalNewlineDecoder, TextIOWrapper) TextIOWrapper) +try: + from _io import FileIO +except ImportError: + pass + OpenWrapper = _io.open # for compatibility with _pyio # Pretend this exception was created here. diff --git a/Lib/posixpath.py b/Lib/posixpath.py index ecb4e5a8f..8bd078c2b 100644 --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -22,7 +22,10 @@ defpath = '/bin:/usr/bin' altsep = None devnull = '/dev/null' -import os +try: + import os +except ImportError: + import _dummy_os as os import sys import stat import genericpath diff --git a/Lib/zipfile.py b/Lib/zipfile.py index 5dc6516cc..cd309da01 100644 --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -8,13 +8,22 @@ import functools import importlib.util import io import itertools -import os +try: + import os +except ImportError: + import _dummy_os as os import posixpath -import shutil +try: + import shutil +except ImportError: + pass import stat import struct import sys -import threading +try: + import threading +except ImportError: + import _dummy_thread as threading import time import contextlib from collections import OrderedDict