From 25568f30bf2544a8c7d4f757528fc0f4bb459c03 Mon Sep 17 00:00:00 2001 From: Tony Tung Date: Tue, 3 Sep 2019 14:58:13 -0700 Subject: [PATCH] Refactor file-url-to-path This is the same issue as #112, so I added a general method to do this conversion. --- slicedimage/io/_base.py | 7 +++---- slicedimage/url/path.py | 15 +++++++++++++++ slicedimage/url/resolve.py | 9 ++------- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/slicedimage/io/_base.py b/slicedimage/io/_base.py index 5a84611..b4309a6 100644 --- a/slicedimage/io/_base.py +++ b/slicedimage/io/_base.py @@ -20,6 +20,7 @@ from packaging import version +from slicedimage.url.path import get_path_from_parsed_file_url from slicedimage.url.resolve import resolve_url from slicedimage._collection import Collection from slicedimage._formats import ImageFormat @@ -283,8 +284,7 @@ def partition_url_generator(self, parent_partition_url: str, partition_name: str if self.partition_path_generator is None: return super().partition_url_generator(parent_partition_url, partition_name) parent_parsed_url = urllib.parse.urlparse(parent_partition_url) - assert parent_parsed_url.scheme == "file" - parent_path = PurePosixPath(parent_parsed_url.path) + parent_path = get_path_from_parsed_file_url(parent_parsed_url) partition_path = self.partition_path_generator(parent_path, partition_name) partition_parsed_url = parent_parsed_url._replace(path=str(partition_path)) return urllib.parse.urlunparse(partition_parsed_url) @@ -310,8 +310,7 @@ def tile_url_generator(self, tileset_url: str, tile: Tile, ext: str) -> str: if self.tile_opener is None: return super().tile_url_generator(tileset_url, tile, ext) tileset_parsed_url = urllib.parse.urlparse(tileset_url) - assert tileset_parsed_url.scheme == "file" - tileset_path = PurePosixPath(tileset_parsed_url.path) + tileset_path = get_path_from_parsed_file_url(tileset_parsed_url) with self.tile_opener(tileset_path, tile, ext) as open_fh: tile_path = open_fh.name diff --git a/slicedimage/url/path.py b/slicedimage/url/path.py index 71cb9b1..c0b5fbf 100644 --- a/slicedimage/url/path.py +++ b/slicedimage/url/path.py @@ -1,3 +1,4 @@ +import os import pathlib import posixpath import urllib.parse @@ -104,3 +105,17 @@ def calculate_relative_url(baseurl: str, name_or_url: str) -> str: result = result + "#" + absolute_url_parsed.fragment return result + + +def get_path_from_parsed_file_url(parsed_file_url: urllib.parse.ParseResult) -> pathlib.Path: + """If parsed_file_url is the result of parsing a URL using urllib.parse.unparse, and the URL is + a "file:" URL, then extract the local filesystem path. Handles idiosyncrasies such as pathlib + and Windows paths. + """ + assert parsed_file_url.scheme == "file" + if os.name == "nt": + # pathlib can parse c:/windows/xxx, but not /c:/windows/xxx. however, url paths always + # start with a / + return pathlib.Path(urllib.parse.unquote(parsed_file_url.path[1:])) + else: + return pathlib.Path(urllib.parse.unquote(parsed_file_url.path)) diff --git a/slicedimage/url/resolve.py b/slicedimage/url/resolve.py index df3677f..553fdbc 100644 --- a/slicedimage/url/resolve.py +++ b/slicedimage/url/resolve.py @@ -5,7 +5,7 @@ from slicedimage._compat import fspath from slicedimage.backends import CachingBackend, DiskBackend, HttpBackend, S3Backend, SIZE_LIMIT -from .path import get_absolute_url +from .path import get_absolute_url, get_path_from_parsed_file_url def infer_backend(baseurl, backend_config=None): @@ -26,12 +26,7 @@ def infer_backend(baseurl, backend_config=None): parsed = urllib.parse.urlparse(baseurl) if parsed.scheme == "file": - if os.name == "nt": - # pathlib can parse c:/windows/xxx, but not /c:/windows/xxx. however, url paths always - # start with a / - local_path = pathlib.Path(urllib.parse.unquote(parsed.path[1:])) - else: - local_path = pathlib.Path(urllib.parse.unquote(parsed.path)) + local_path = get_path_from_parsed_file_url(parsed) return DiskBackend(fspath(local_path)) if parsed.scheme in ("http", "https"):