1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
From 8a4d651610abb71da66cef58f350788eab6b0bd1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= <alex.gronholm@nextday.fi>
Date: Tue, 28 May 2024 01:00:49 +0300
Subject: [PATCH 1/3] Added missing Path properties from Python 3.13
Fixes #737.
---
src/anyio/_core/_fileio.py | 24 ++++++++++++++++++++++--
tests/test_fileio.py | 18 ++++++++++++++++++
4 files changed, 47 insertions(+), 4 deletions(-)
diff --git a/src/anyio/_core/_fileio.py b/src/anyio/_core/_fileio.py
index df2057fe..8053dce5 100644
--- a/src/anyio/_core/_fileio.py
+++ b/src/anyio/_core/_fileio.py
@@ -358,8 +358,28 @@ def as_posix(self) -> str:
def as_uri(self) -> str:
return self._path.as_uri()
- def match(self, path_pattern: str) -> bool:
- return self._path.match(path_pattern)
+ if sys.version_info >= (3, 13):
+ parser = pathlib.Path.parser # type: ignore[attr-defined]
+
+ @classmethod
+ def from_uri(cls, uri: str) -> Path:
+ return Path(pathlib.Path.from_uri(uri)) # type: ignore[attr-defined]
+
+ def full_match(
+ self, path_pattern: str, *, case_sensitive: bool | None = None
+ ) -> bool:
+ return self._path.full_match( # type: ignore[attr-defined]
+ path_pattern, case_sensitive=case_sensitive
+ )
+
+ def match(
+ self, path_pattern: str, *, case_sensitive: bool | None = None
+ ) -> bool:
+ return self._path.match(path_pattern, case_sensitive=case_sensitive)
+ else:
+
+ def match(self, path_pattern: str) -> bool:
+ return self._path.match(path_pattern)
def is_relative_to(self, other: str | PathLike[str]) -> bool:
try:
diff --git a/tests/test_fileio.py b/tests/test_fileio.py
index bcd7fe1d..ff9178e0 100644
--- a/tests/test_fileio.py
+++ b/tests/test_fileio.py
@@ -186,6 +186,15 @@ def test_as_uri(self) -> None:
else:
assert Path("/foo/bar").as_uri() == "file:///foo/bar"
+ @pytest.mark.skipif(
+ sys.version_info < (3, 13),
+ reason="Path.from_uri() is only available on Python 3.13+",
+ )
+ def test_from_uri(self) -> None:
+ path = Path.from_uri("file:///foo/bar")
+ assert isinstance(path, Path)
+ assert path.as_uri() == "file:///foo/bar"
+
async def test_cwd(self) -> None:
result = await Path.cwd()
assert isinstance(result, Path)
@@ -269,6 +278,7 @@ async def test_is_mount(self) -> None:
assert not await Path("/gfobj4ewiotj").is_mount()
assert await Path("/").is_mount()
+ @pytest.mark.filterwarnings("ignore::DeprecationWarning")
def test_is_reserved(self) -> None:
expected_result = platform.system() == "Windows"
assert Path("nul").is_reserved() == expected_result
@@ -339,6 +349,14 @@ def test_joinpath(self) -> None:
path = Path("/foo").joinpath("bar")
assert path == Path("/foo/bar")
+ @pytest.mark.skipif(
+ sys.version_info < (3, 13),
+ reason="Path.full_match() is only available on Python 3.13+",
+ )
+ def test_fullmatch(self) -> None:
+ assert Path("/foo/bar").full_match("/foo/*")
+ assert not Path("/foo/bar").full_match("/baz/*")
+
def test_match(self) -> None:
assert Path("/foo/bar").match("/foo/*")
assert not Path("/foo/bar").match("/baz/*")
|