Skip to content

Commit f0e5d6b

Browse files
committed
Add new function to create a PathPlus object from a file URI
1 parent 47bd3fc commit f0e5d6b

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

domdf_python_tools/paths.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import stat
5353
import sys
5454
import tempfile
55+
import urllib.parse
5556
from collections import defaultdict, deque
5657
from operator import methodcaller
5758
from typing import (
@@ -65,6 +66,7 @@
6566
List,
6667
Optional,
6768
Sequence,
69+
Type,
6870
TypeVar,
6971
Union
7072
)
@@ -832,6 +834,25 @@ def iterchildren(
832834
if file.is_dir():
833835
yield from file.iterchildren(exclude_dirs, match)
834836

837+
@classmethod
838+
def from_uri(cls: Type[_PP], uri: str) -> _PP:
839+
"""
840+
Construct a :class:`~.PathPlus` from a ``file`` URI returned by :meth:`pathlib.PurePath.as_uri`.
841+
842+
.. versionadded:: 2.9.0
843+
844+
:param uri:
845+
"""
846+
847+
parseresult = urllib.parse.urlparse(uri)
848+
849+
if parseresult.scheme != "file":
850+
raise ValueError(f"Unsupported URI scheme {parseresult.scheme!r}")
851+
if parseresult.netloc or parseresult.params or parseresult.query or parseresult.fragment:
852+
raise ValueError("Malformed file URI")
853+
854+
return cls(urllib.parse.unquote_to_bytes(parseresult.path).decode("UTF-8"))
855+
835856

836857
class PosixPathPlus(PathPlus, pathlib.PurePosixPath):
837858
"""

tests/test_paths.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import sys
1616
from tempfile import TemporaryDirectory
1717
from textwrap import dedent
18+
from typing import Type
1819

1920
# 3rd party
2021
import pytest
@@ -880,3 +881,24 @@ def test_sort_paths():
880881
PathPlus("foo.txt"),
881882
]
882883
assert sort_paths(*paths) == expected
884+
885+
886+
if platform.system() == "Windows":
887+
_from_uri_paths = [
888+
"c:/",
889+
"c:/users/domdf/☃.txt",
890+
"c:/a/b.c",
891+
"c:/a/b%#c",
892+
"c:/a/bé",
893+
"//some/share/",
894+
"//some/share/a/b.c",
895+
"//some/share/a/b%#cé"
896+
]
897+
else:
898+
_from_uri_paths = ['/', "/home/domdf/☃.txt", "/a/b.c", "/a/b%#c"]
899+
900+
901+
@pytest.mark.parametrize("path", _from_uri_paths)
902+
@pytest.mark.parametrize("left_type", [pathlib.PurePath, pathlib.Path, PathPlus])
903+
def test_pathplus_from_uri(path: str, left_type: Type):
904+
assert PathPlus.from_uri(left_type(path).as_uri()).as_posix() == path

0 commit comments

Comments
 (0)