From 9a8ae56427ffeb78157d2723b1297cf38d2e0d79 Mon Sep 17 00:00:00 2001 From: joncrall Date: Thu, 6 Jan 2022 12:08:59 -0500 Subject: [PATCH] Fix internal _fspath --- ubelt/_win32_links.py | 1 + ubelt/util_path.py | 38 ++++++++++++++++++++++++++++++++++++++ ubelt/util_zip.py | 33 +++++++-------------------------- 3 files changed, 46 insertions(+), 26 deletions(-) diff --git a/ubelt/_win32_links.py b/ubelt/_win32_links.py index d321c8e07..6bae3856e 100644 --- a/ubelt/_win32_links.py +++ b/ubelt/_win32_links.py @@ -22,6 +22,7 @@ from os.path import join from ubelt import util_io from ubelt import util_path +from ubelt.util_path import _fspath import sys if sys.platform.startswith('win32'): diff --git a/ubelt/util_path.py b/ubelt/util_path.py index 57b7939d0..70a7d1398 100644 --- a/ubelt/util_path.py +++ b/ubelt/util_path.py @@ -582,3 +582,41 @@ def delete(self): else: util_io.delete(self) return self + + +if PY_LE_35: # nocover + def _fspath(path): + """ + Return the file system path representation of the object. + + If the object is str or bytes, then allow it to pass through as-is. If + the object defines __fspath__(), then return the result of that method. + All other types raise a TypeError. + + Internal helper for cases where os.fspath does not exist on older Python + """ + import six + string_types = six.string_types + + if isinstance(path, string_types): + 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, string_types): + return path_repr + else: + raise TypeError("expected {}.__fspath__() to return str or bytes, " + "not {}".format(path_type.__name__, + type(path_repr).__name__)) +else: + _fspath = os.fspath diff --git a/ubelt/util_zip.py b/ubelt/util_zip.py index 1ca760fbf..8cb97401e 100644 --- a/ubelt/util_zip.py +++ b/ubelt/util_zip.py @@ -15,40 +15,23 @@ a temporary directory first. """ from __future__ import absolute_import, division, print_function, unicode_literals -import os -import sys import io +import os import re +import sys import tempfile import zipfile from os.path import exists, join from ubelt.util_mixins import NiceRepr +from ubelt.util_path import _fspath __all__ = ['zopen', 'split_archive'] PY2 = (sys.version_info[0] == 2) + if PY2: OSError = IOError - def _fspath(p): - import pathlib - if isinstance(p, (str, unicode)): # NOQA - return p - elif isinstance(p, pathlib.Path): - return str(p) - else: - raise TypeError -elif sys.version_info[0:2] >= (3, 6): # nocover - _fspath = os.fspath -else: # nocover - def _fspath(p): - import pathlib - if isinstance(p, (str, bytes)): # NOQA - return p - elif isinstance(p, pathlib.Path): - return str(p) - else: - raise TypeError def split_archive(fpath, ext='.zip'): @@ -61,9 +44,8 @@ def split_archive(fpath, ext='.zip'): >>> split_archive('/a/b/foo.zip/bar.txt') >>> split_archive('/a/b/foo.zip/baz/biz.zip/bar.py') >>> split_archive('archive.zip') - >>> # xdoctest: +REQUIRES(module:pathlib) - >>> import pathlib - >>> split_archive(pathlib.Path('/a/b/foo.zip/baz/biz.zip/bar.py')) + >>> import ubelt as ub + >>> split_archive(ub.Path('/a/b/foo.zip/baz/biz.zip/bar.py')) >>> split_archive('/a/b/foo.zip/baz.pt/bar.zip/bar.zip', '.pt') TODO: @@ -140,11 +122,10 @@ class zopen(NiceRepr): Example: >>> from ubelt.util_zip import * # NOQA - >>> import pathlib >>> import pickle >>> import ubelt as ub >>> dpath = ub.ensure_app_cache_dir('ubelt/tests/util_zip') - >>> dpath = pathlib.Path(dpath) + >>> dpath = ub.Path(dpath) >>> data_fpath = dpath / 'test.pkl' >>> data = {'demo': 'data'} >>> with open(str(data_fpath), 'wb') as file: