Я начал использовать pathlib.Path
некоторое время назад, и мне нравится использовать его. Теперь, когда я привык к этому, я стал неаккуратно и забыл привести аргументы в str
.pathlib Путь и py.test LocalPath
Это часто происходит при использовании tox
+ py.test
с временными каталогами на основе tmpdir
(который является py._path.local.LocalPath
):
from pathlib import Path
import pytest
def test_tmpdir(tmpdir):
p = Path(tmpdir)/'testfile.csv'
Вместо вставки str()
каждый раз, когда я смотрел на решение этого в более общем плане, но не может ,
Сначала я пытался сделать свой собственный класс Path, который адаптированный _parse_args
:
import pytest
from py._path.local import LocalPath
from pathlib import Path, PurePath
def Path(Path):
@classmethod
def _parse_args(cls, args):
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))
elif isinstance(a, LocalPath):
parts.append(str(a))
else:
raise TypeError(
"argument should be a path or str object, not %r"
% type(a))
return cls._flavour.parse_parts(parts)
def test_subclass(tmpdir):
p = Path(tmpdir)/'testfile.csv'
Это проливает TypeError: unsupported operand type(s) for /: 'NoneType' and 'str'
(пробовал с PosixPath
, а также, такой же результат, предпочел бы не быть Linux конкретных).
Я попытался обезьяньего пластыря Path
:
import pytest
from pathlib import Path
def add_tmpdir():
from py._path.local import LocalPath
org_attr = '_parse_args'
stow_attr = '_org_parse_args'
def parse_args_localpath(cls, args):
args = list(args)
for idx, a in enumerate(args):
if isinstance(a, LocalPath):
args[idx] = str(a)
return getattr(cls, stow_attr)(args)
if hasattr(Path, stow_attr):
return # already done
setattr(Path, stow_attr, getattr(Path, org_attr))
setattr(Path, org_attr, parse_args_localpath)
add_tmpdir()
def test_monkeypatch_path(tmpdir):
p = Path(tmpdir)/'testfile.csv'
Это бросает AttributeError: type object 'Path' has no attribute '_flavour'
(также, когда обезьяна-латание PurePath).
И, наконец, я попытался просто оборачивать Path
:
import pytest
import pathlib
def Path(*args):
from py._path.local import LocalPath
args = list(args)
for idx, a in enumerate(args):
if isinstance(a, LocalPath):
args[idx] = str(a)
return pathlib.Path(*args)
def test_tmpdir_path(tmpdir):
p = Path(tmpdir)/'testfile.csv'
Который также дает AttributeError: type object 'Path' has no attribute '_flavour'
Я думал, в какой-то момент этот последний работал, но я не могу воспроизвести это.
Я делаю что-то неправильно? Почему это так сложно?
FWIW pytest планирует однажды перейти на путь: https://github.com/pytest-dev/pytest/issues/1260 –