Skip to content

Pathlib compat fails under Python 3.5 #5017

@khaeru

Description

@khaeru

pytest's compatibility code chooses to use pathlib2 except for Python 3.6. This means that pathlib2.Path objects are returned for fixtures/fixture methods like tmp_path_factory.mktemp(). When the user tests code using Python 3.5's built-in pathlib, the built-in package chokes on the objects from pathlib2.

Put the following in test_foo.py and execute using pytest under Python 3.5:

from pathlib import Path  # available in Python 3.5


def foo(p):
    p2 = p / 'foo.txt'
    print(p2.exists())


def bar(p):
    p2 = Path(p)
    print(p2.exists())


def test_foo(tmp_path_factory):
    foo(tmp_path_factory.mktemp('baz1'))


def test_bar(tmp_path_factory):
    bar(tmp_path_factory.mktemp('baz2'))

…this occurs:

$ pytest test_foo.py
============================================================================== test session starts ===============================================================================
platform linux -- Python 3.5.2, pytest-4.4.0, py-1.5.2, pluggy-0.9.0
Matplotlib: 2.1.2
Freetype: 2.6.1
rootdir: /home/gidden/work/iiasa/message/ixmp, inifile: setup.cfg
plugins: mpl-0.9, cov-2.6.0
collected 2 items
                                                                                                                                                                
test_foo.py .F                                                                                                                                                             [100%]

==================================================================================== FAILURES ====================================================================================
____________________________________________________________________________________ test_bar ____________________________________________________________________________________
tmp_path_factory = TempPathFactory(_given_basetemp=None, _trace=<pluggy._tracing.TagTracerSub object at 0x7f0779c3f1d0>, _basetemp=PosixPath('/tmp/pytest-of-gidden/pytest-22'))
    def test_bar(tmp_path_factory):
    
>       bar(tmp_path_factory.mktemp('baz2'))
test_foo.py:24: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
test_foo.py:13: in bar
    p2 = Path(p)
/usr/lib/python3.5/pathlib.py:969: in __new__
    self = cls._from_parts(args, init=False)
/usr/lib/python3.5/pathlib.py:651: in _from_parts
    drv, root, parts = self._parse_args(args)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
cls = <class 'pathlib.PosixPath'>, args = (PosixPath('/tmp/pytest-of-gidden/pytest-22/baz20'),)
    @classmethod
    def _parse_args(cls, args):
        # This is useful when you don't want to create an instance, just
        # canonicalize some constructor arguments.
        parts = []
        for a in args:
            if isinstance(a, PurePath):
                parts += a._parts
            elif isinstance(a, str):
                # Force-cast str subclasses to str (issue #21127)
                parts.append(str(a))
            else:
                raise TypeError(
                    "argument should be a path or str object, not %r"
>                   % type(a))
E               TypeError: argument should be a path or str object, not <class 'pathlib2.PosixPath'>
/usr/lib/python3.5/pathlib.py:643: TypeError
======================================================================= 1 failed, 1 passed in 0.13 seconds =======================================================================

The same command succeeds under Python 3.6.

Discovered by @gidden

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: proposalproposal for a new feature, often to gather opinions or design the API around the new feature

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions