Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PEP 519 Support #25

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.rst
Expand Up @@ -122,7 +122,7 @@ Constructor
``Path`` (and ``AbstractPath``) objects can be created from a string path, or
from several string arguments which are joined together a la ``os.path.join``.
Each argument can be a string, an ``(Abstract)Path`` instance, an int or long,
or a list/tuple of strings to be joined::
a list/tuple of strings to be joined, or (Python 3.6+) a ``PathLike`` object::

p = Path("foo/bar.py") # A relative path
p = Path("foo", "bar.py") # Same as previous
Expand Down
26 changes: 25 additions & 1 deletion test.py
Expand Up @@ -622,5 +622,29 @@ def test_read_file(self):
# .write_file and .rmtree tested in .setUp.


try:
from os import PathLike as _
pep519_present = True
except ImportError:
pep519_present = False



@pytest.mark.skipif(not pep519_present, reason='PEP519 support not found')
class TestPEP519(FilesystemTest):
# If PEP519 support is not present then interactions with other path-like objects are left undefined (will probably fail)

def test_pathlib(self):
import pathlib
pure_path = Path('a', 'b', Path('c'), Path('d'))
mixed_path = Path('a', pathlib.Path('b'), 'c', pathlib.Path('d'))
assert pure_path == mixed_path

def test_DirEntry(self):
d = self.d
with os.scandir(self.d) as it:
for entry in it:
pure_path = Path(self.d, entry.name, '..').resolve()
mixed_path = Path(entry, '..').resolve()
assert pure_path == mixed_path
return
assert False, "scandir() yielded an empty directory"
2 changes: 1 addition & 1 deletion tox.ini
@@ -1,5 +1,5 @@
[tox]
envlist = py27, py34
envlist = py27, py34, py36

[testenv]
deps=pytest
Expand Down
31 changes: 21 additions & 10 deletions unipath/abstractpath.py
Expand Up @@ -15,6 +15,22 @@
except NameError:
pass

try:
int_types = (int, long)
except NameError: # We are in Python 3
int_types = int

try:
legal_arg_types = (basestring, list, int, long)
except NameError: # Python 3 doesn't have basestring nor long
legal_arg_types = (str, list, int)

try:
from os import PathLike
legal_arg_types += (PathLike,)
except ImportError:
pass

class AbstractPath(_base):
"""An object-oriented approach to os.path functions."""
pathlib = os.path
Expand Down Expand Up @@ -44,6 +60,9 @@ def __add__(self, more):
if resultStr is NotImplemented:
return resultStr
return self.__class__(resultStr)

def __fspath__(self):
return _base(self)

@classmethod
def _new_helper(class_, args):
Expand All @@ -55,19 +74,11 @@ def _new_helper(class_, args):
if len(args) == 1 and isinstance(args[0], class_) and \
args[0].pathlib == pathlib:
return args[0]
try:
legal_arg_types = (class_, basestring, list, int, long)
except NameError: # Python 3 doesn't have basestring nor long
legal_arg_types = (class_, str, list, int)
args = list(args)
for i, arg in enumerate(args):
if not isinstance(arg, legal_arg_types):
m = "arguments must be str, unicode, list, int, long, or %s"
if not isinstance(arg, (AbstractPath,) + legal_arg_types):
m = "arguments must be str, unicode, list, int, long, os.PathLike, or %s"
raise TypeError(m % class_.__name__)
try:
int_types = (int, long)
except NameError: # We are in Python 3
int_types = int
if isinstance(arg, int_types):
args[i] = str(arg)
elif isinstance(arg, class_) and arg.pathlib != pathlib:
Expand Down