Skip to content

Commit baf833e

Browse files
committed
url escape : on win and cache
1 parent 8daee30 commit baf833e

2 files changed

Lines changed: 24 additions & 0 deletions

File tree

cloudpathlib/s3/s3path.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
22
import re
3+
import sys
34
from pathlib import Path
45
from tempfile import TemporaryDirectory
56
from typing import Any, Optional, TYPE_CHECKING
@@ -32,6 +33,7 @@ class S3Path(CloudPath):
3233
cloud_prefix: str = "s3://"
3334
client: "S3Client"
3435
_bucket: str
36+
_local_path: Path
3537

3638
@property
3739
def drive(self) -> str:
@@ -106,3 +108,14 @@ def key(self) -> str:
106108
@property
107109
def etag(self):
108110
return self.client._get_metadata(self).get("etag")
111+
112+
@property
113+
def _local(self) -> Path:
114+
if hasattr(self, "_local_path"):
115+
return self._local_path
116+
no_prefix = self._no_prefix
117+
# `:` is invalid in Windows paths; percent-encode it for MRAP ARNs
118+
if sys.platform == "win32":
119+
no_prefix = no_prefix.replace(":", "%3A")
120+
self._local_path = self.client._local_cache_dir / no_prefix
121+
return self._local_path

tests/test_s3_specific.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,3 +394,14 @@ def test_mrap_file_operations(s3_rig):
394394
assert new_file.bucket == _MRAP_ARN
395395
new_file.unlink()
396396
assert not new_file.exists()
397+
398+
399+
def test_mrap_local_path_windows_encoding(monkeypatch, s3_rig):
400+
"""On Windows, colons in MRAP ARNs must be percent-encoded in the local cache path."""
401+
import cloudpathlib.s3.s3path as s3path_module
402+
403+
monkeypatch.setattr(s3path_module.sys, "platform", "win32")
404+
client = s3_rig.client_class()
405+
p = client.CloudPath(f"s3://{_MRAP_ARN}/some/key.txt")
406+
assert ":" not in str(p._local), f"Colon found in local path on simulated Windows: {p._local}"
407+
assert "%3A" in str(p._local)

0 commit comments

Comments
 (0)