slash3
Introduction
Slash3 is a Python package for building and navigating Amazon Web Services S3 URIs.
What's an S3 URI?
An S3 URI (Uniform Resource Identifier) is a string that identifies a bucket, and optionally a key, in Amazon Web Services S3.
The pattern for an S3 URI is s3://BUCKET/KEY.
For example:
- The bucket named "circus" can be described by the URI
s3://circus/ - The key prefix for all circus images can be described by the URI
s3://circus/images/ - The path to Steve's staff photograph can be described by the URI
s3://circus/images/steve.jpg
Installation
Slash3 requires Python 3.9 or later and can be installed from PyPI.
pip install slash3
Usage
Construct a URI from a URI
If you've already got a string URI then pass it directly to S3Uri:
from slash3 import S3Uri
uri = S3Uri("s3://circus/")
uri.bucket # circus
uri.key #
uri = S3Uri("s3://circus/images/clowns.jpg")
uri.bucket # circus
uri.key # images/clowns.jpg
Construct a URI from a bucket and key
To construct an S3 URI from a bucket name and an optional key, call
S3Uri.to_uri:
from slash3 import S3Uri
uri = S3Uri.to_uri("circus")
# s3://circus/
uri = S3Uri.to_uri("circus", "images/clowns.jpg")
# s3://circus/images/clowns.jpg
Join a key suffix with a "/" delimiter
To join a key suffix with a "/" delimiter -- for example, to join an object's
name to a key prefix -- call S3Uri.join() or use the / operator:
from slash3 import S3Uri
uri = S3Uri("s3://circus/")
images = uri / "images"
# s3://circus/images
clowns = images / "clowns.jpg"
# s3://circus/images/clowns.jpg
Slash3 will automatically normalise away any consecutive "/" delimiters.
Append a key suffix without a delimiter
To append a key suffix without a delimiter, call S3Uri.append() or use the +
operator:
from slash3 import S3Uri
staff = S3Uri("s3://circus/staff-")
steve = staff + "steve.jpg"
# s3://circus/staff-steve.jpg
penny = staff + "penny.jpg"
# s3://circus/staff-penny.jpg
Get the parent key prefix
To get a URI's parent key prefix, call S3Uri.parent:
from slash3 import S3Uri
steve = S3Uri("s3://circus/images/steve.jpg")
steve.parent
# s3://circus/images/
Get the key's leaf / file name
from slash3 import S3Uri
steve = S3Uri("s3://circus/images/steve.jpg")
steve.leaf
# steve.jpg
Get a relative key path
To discover the relative path between a specific URI and a parent URI, call
S3Uri.relative_to:
from slash3 import S3Uri
avatar = S3Uri("s3://circus/images/staff/steve.jpg")
images = "s3://circus/images/"
avatar.relative_to(images)
# staff/steve.jpg
Support
Please submit all your questions, feature requests and bug reports at github.com/cariad/slash3/issues. Thank you!
Licence
Slash3 is open-source and released under the MIT License.
You don't have to give attribution in your project, but -- as a freelance developer with rent to pay -- I appreciate it!
Author
Hello! 👋 I'm Cariad Eccleston, and I'm a freelance Amazon Web Services architect, DevOps evangelist, CI/CD pipeline engineer and backend developer.
You can find me at cariad.earth, github/cariad, linkedin/cariad and on Mastodon at @cariad@tech.lgbt.
1""" 2[](https://codecov.io/gh/cariad/slash3) 3 4# Introduction 5 6**Slash3** is a Python package for building and navigating Amazon Web Services 7S3 URIs. 8 9# What's an S3 URI? 10 11An S3 URI (Uniform Resource Identifier) is a string that identifies a bucket, 12and optionally a key, in Amazon Web Services S3. 13 14The pattern for an S3 URI is `s3://BUCKET/KEY`. 15 16For example: 17 18- The bucket named "circus" can be described by the URI `s3://circus/` 19- The key prefix for all circus images can be described by the URI 20`s3://circus/images/` 21- The path to Steve's staff photograph can be described by the URI 22`s3://circus/images/steve.jpg` 23 24# Installation 25 26Slash3 requires Python 3.9 or later and can be installed from 27[PyPI](https://pypi.org/project/slash3/). 28 29```shell 30pip install slash3 31``` 32 33# Usage 34 35## Construct a URI from a URI 36 37If you've already got a string URI then pass it directly to `S3Uri`: 38 39```python 40from slash3 import S3Uri 41 42uri = S3Uri("s3://circus/") 43 44uri.bucket # circus 45uri.key # 46 47uri = S3Uri("s3://circus/images/clowns.jpg") 48 49uri.bucket # circus 50uri.key # images/clowns.jpg 51``` 52 53## Construct a URI from a bucket and key 54 55To construct an S3 URI from a bucket name and an optional key, call 56`S3Uri.to_uri`: 57 58```python 59from slash3 import S3Uri 60 61uri = S3Uri.to_uri("circus") 62# s3://circus/ 63 64uri = S3Uri.to_uri("circus", "images/clowns.jpg") 65# s3://circus/images/clowns.jpg 66``` 67 68## Join a key suffix with a "/" delimiter 69 70To join a key suffix with a "/" delimiter -- for example, to join an object's 71name to a key prefix -- call `S3Uri.join()` or use the `/` operator: 72 73```python 74from slash3 import S3Uri 75 76uri = S3Uri("s3://circus/") 77 78images = uri / "images" 79# s3://circus/images 80 81clowns = images / "clowns.jpg" 82# s3://circus/images/clowns.jpg 83``` 84 85Slash3 will automatically normalise away any consecutive "/" delimiters. 86 87## Append a key suffix without a delimiter 88 89To append a key suffix without a delimiter, call `S3Uri.append()` or use the `+` 90operator: 91 92```python 93from slash3 import S3Uri 94 95staff = S3Uri("s3://circus/staff-") 96 97steve = staff + "steve.jpg" 98# s3://circus/staff-steve.jpg 99 100penny = staff + "penny.jpg" 101# s3://circus/staff-penny.jpg 102``` 103 104## Get the parent key prefix 105 106To get a URI's parent key prefix, call `S3Uri.parent`: 107 108```python 109from slash3 import S3Uri 110 111steve = S3Uri("s3://circus/images/steve.jpg") 112 113steve.parent 114# s3://circus/images/ 115``` 116 117## Get the key's leaf / file name 118 119```python 120from slash3 import S3Uri 121 122steve = S3Uri("s3://circus/images/steve.jpg") 123 124steve.leaf 125# steve.jpg 126``` 127 128## Get a relative key path 129 130To discover the relative path between a specific URI and a parent URI, call 131`S3Uri.relative_to`: 132 133```python 134from slash3 import S3Uri 135 136avatar = S3Uri("s3://circus/images/staff/steve.jpg") 137images = "s3://circus/images/" 138 139avatar.relative_to(images) 140# staff/steve.jpg 141``` 142 143# Support 144 145Please submit all your questions, feature requests and bug reports at 146[github.com/cariad/slash3/issues](https://github.com/cariad/slash3/issues). Thank you! 147 148# Licence 149 150Slash3 is [open-source](https://github.com/cariad/slash3) and released under the 151[MIT License](https://github.com/cariad/slash3/blob/main/LICENSE). 152 153You don't have to give attribution in your project, but -- as a freelance 154developer with rent to pay -- I appreciate it! 155 156# Author 157 158Hello! 👋 I'm **Cariad Eccleston**, and I'm a freelance Amazon Web Services 159architect, DevOps evangelist, CI/CD pipeline engineer and backend developer. 160 161You can find me at [cariad.earth](https://www.cariad.earth), 162[github/cariad](https://github.com/cariad), 163[linkedin/cariad](https://linkedin.com/in/cariad) and on Mastodon at 164[@cariad@tech.lgbt](https://tech.lgbt/@cariad). 165""" 166 167from importlib.resources import open_text 168 169from slash3.key import S3Key 170from slash3.uri import S3Uri 171 172with open_text(__package__, "VERSION") as t: 173 __version__ = t.readline().strip() 174 175__all__ = [ 176 "S3Key", 177 "S3Uri", 178]
9class S3Key: 10 """ 11 An Amazon Web Services S3 key. 12 """ 13 14 def __init__(self, key: Optional[str] = None) -> None: 15 logger.debug('Creating new S3Key from "%s"', key) 16 key = key or "" 17 18 if key.startswith("/"): 19 raise ValueError( 20 f'S3 keys cannot start with the delimiter "/" ("{key}")', 21 ) 22 23 if "//" in key: 24 raise ValueError( 25 f'S3 keys cannot contain consecutive "/" delimiters ("{key}")', 26 ) 27 28 if len(key) > MAX_LENGTH: 29 raise ValueError( 30 f"S3 keys cannot be longer than {MAX_LENGTH} characters " 31 f'("{key}" has {len(key)} characters)', 32 ) 33 34 self._key = key or "" 35 36 def __add__(self, other: str) -> "S3Key": 37 return self.append(other) 38 39 def __eq__(self, other: Any) -> bool: 40 return self._key == str(other) 41 42 def __len__(self) -> int: 43 return len(self._key) 44 45 def __repr__(self) -> str: 46 return self._key 47 48 def __truediv__(self, other: str) -> "S3Key": 49 return self.join(other) 50 51 def append(self, suffix: str) -> "S3Key": 52 """ 53 Appends a string to the key. 54 55 ```python 56 images = S3Key("images/staff-") 57 58 steve = images.append("steve.jpg") 59 # "images/staff-steve.jpg" 60 61 # Or use "+": 62 penny = images + "penny.jpg" 63 # "images/staff-penny.jpg" 64 ``` 65 66 To add a suffix with a "/" delimiter, use `join()` instead. 67 """ 68 69 logger.debug('Appending base "%s" and suffix "%s"', self._key, suffix) 70 71 if self._key.endswith("/") and suffix.startswith("/"): 72 base = self.normal_right(self._key, slash=True) 73 logger.debug('Base normalised to "%s"', base) 74 suffix = self.normal_left(suffix) 75 else: 76 base = self._key 77 78 return S3Key(base + suffix) 79 80 def join(self, suffix: str) -> "S3Key": 81 """ 82 Joins a string to the key with a "/" delimiter. 83 84 ```python 85 images = S3Key("images/staff") 86 87 steve = images.join("steve.jpg") 88 # "images/staff/steve.jpg" 89 90 # Or use "/": 91 penny = images / "penny.jpg" 92 # "images/staff/penny.jpg" 93 ``` 94 95 To append a string without a "/" delimiter, use `append()` instead. 96 """ 97 98 logger.debug('Joining base "%s" and suffix "%s"', self._key, suffix) 99 100 base = self.normal_right(self._key, slash=True) if self._key else self._key 101 logger.debug('Base normalised to "%s"', base) 102 103 suffix = self.normal_left(suffix) 104 logger.debug('Suffix normalised to "%s"', suffix) 105 106 return S3Key(base + suffix) 107 108 @property 109 def key(self) -> str: 110 """ 111 Key. 112 113 For example, "private/clowns.jpg". 114 """ 115 116 return self._key 117 118 @property 119 def leaf(self) -> str: 120 """ 121 Key leaf. 122 123 In a file system metaphor, the leaf would be the file's name. 124 125 For example, the leaf of "private/clowns.jpg" is "clowns.jpg". 126 """ 127 128 return self.relative_to(self.parent) 129 130 @staticmethod 131 def normal_left(key: str, slash: bool = False) -> str: 132 """ 133 Normalises the left of the key. 134 135 If `slash` is true then the key is returned with exactly one leading 136 slash, otherwise the key is returned with no leading slashes. 137 """ 138 139 while key.startswith("/"): 140 key = key[1:] 141 142 return "/" + key if slash else key 143 144 @staticmethod 145 def normal_right(key: str, slash: bool = False) -> str: 146 """ 147 Normalises the right of the key. 148 149 If `slash` is true then the key is returned with exactly one trailing 150 slash, otherwise the key is returned with no trailing slashes. 151 """ 152 153 while key.endswith("/"): 154 key = key[:-1] 155 156 return key + "/" if slash else key 157 158 @property 159 def parent(self) -> "S3Key": 160 """ 161 Parent key. 162 163 For example, the parent of "private/clowns.jpg" is "private/". 164 """ 165 166 logger.debug('Determining the parent of key "%s"', repr(self)) 167 168 if self._key == "": 169 logger.debug("Empty key has no parent") 170 return self 171 172 if self._key.endswith("/"): 173 key = self._key[0:-1] 174 else: 175 key = self._key 176 177 if "/" not in key: 178 logger.debug("Root key parent is the root") 179 return S3Key() 180 181 index = key.rindex("/") + 1 182 183 logger.debug('Final "/" in key "%s" is at index %s', self._key, index) 184 185 parent_key = self._key[0:index] 186 187 logger.debug('Key "%s" parent is "%s"', self._key, parent_key) 188 189 return S3Key(parent_key) 190 191 def relative_to(self, parent: Union["S3Key", str]) -> str: 192 """ 193 Gets the relative key path from this key to a `parent` key. 194 195 For example, the relative path to "private/clowns.jpg" from parent 196 "private" is "clowns.jpg". 197 """ 198 199 logger.debug( 200 'Calculating the relative key from "%s" to "%s"', 201 self, 202 parent, 203 ) 204 205 parent = str(parent) 206 normal = self.normal_right(parent, slash=True) if parent else parent 207 208 logger.debug('Normalised the parent key to "%s"', normal) 209 210 if not self._key.startswith(normal): 211 raise ValueError(f'"{parent}" is not a parent of "{self}"') 212 213 relative_key = self._key[len(normal) :] # noqa: E203 214 215 logger.debug( 216 'The relative path from "%s" to "%s" is "%s"', 217 parent, 218 self, 219 relative_key, 220 ) 221 222 return relative_key
An Amazon Web Services S3 key.
14 def __init__(self, key: Optional[str] = None) -> None: 15 logger.debug('Creating new S3Key from "%s"', key) 16 key = key or "" 17 18 if key.startswith("/"): 19 raise ValueError( 20 f'S3 keys cannot start with the delimiter "/" ("{key}")', 21 ) 22 23 if "//" in key: 24 raise ValueError( 25 f'S3 keys cannot contain consecutive "/" delimiters ("{key}")', 26 ) 27 28 if len(key) > MAX_LENGTH: 29 raise ValueError( 30 f"S3 keys cannot be longer than {MAX_LENGTH} characters " 31 f'("{key}" has {len(key)} characters)', 32 ) 33 34 self._key = key or ""
51 def append(self, suffix: str) -> "S3Key": 52 """ 53 Appends a string to the key. 54 55 ```python 56 images = S3Key("images/staff-") 57 58 steve = images.append("steve.jpg") 59 # "images/staff-steve.jpg" 60 61 # Or use "+": 62 penny = images + "penny.jpg" 63 # "images/staff-penny.jpg" 64 ``` 65 66 To add a suffix with a "/" delimiter, use `join()` instead. 67 """ 68 69 logger.debug('Appending base "%s" and suffix "%s"', self._key, suffix) 70 71 if self._key.endswith("/") and suffix.startswith("/"): 72 base = self.normal_right(self._key, slash=True) 73 logger.debug('Base normalised to "%s"', base) 74 suffix = self.normal_left(suffix) 75 else: 76 base = self._key 77 78 return S3Key(base + suffix)
Appends a string to the key.
images = S3Key("images/staff-")
steve = images.append("steve.jpg")
# "images/staff-steve.jpg"
# Or use "+":
penny = images + "penny.jpg"
# "images/staff-penny.jpg"
To add a suffix with a "/" delimiter, use join() instead.
80 def join(self, suffix: str) -> "S3Key": 81 """ 82 Joins a string to the key with a "/" delimiter. 83 84 ```python 85 images = S3Key("images/staff") 86 87 steve = images.join("steve.jpg") 88 # "images/staff/steve.jpg" 89 90 # Or use "/": 91 penny = images / "penny.jpg" 92 # "images/staff/penny.jpg" 93 ``` 94 95 To append a string without a "/" delimiter, use `append()` instead. 96 """ 97 98 logger.debug('Joining base "%s" and suffix "%s"', self._key, suffix) 99 100 base = self.normal_right(self._key, slash=True) if self._key else self._key 101 logger.debug('Base normalised to "%s"', base) 102 103 suffix = self.normal_left(suffix) 104 logger.debug('Suffix normalised to "%s"', suffix) 105 106 return S3Key(base + suffix)
Joins a string to the key with a "/" delimiter.
images = S3Key("images/staff")
steve = images.join("steve.jpg")
# "images/staff/steve.jpg"
# Or use "/":
penny = images / "penny.jpg"
# "images/staff/penny.jpg"
To append a string without a "/" delimiter, use append() instead.
Key leaf.
In a file system metaphor, the leaf would be the file's name.
For example, the leaf of "private/clowns.jpg" is "clowns.jpg".
130 @staticmethod 131 def normal_left(key: str, slash: bool = False) -> str: 132 """ 133 Normalises the left of the key. 134 135 If `slash` is true then the key is returned with exactly one leading 136 slash, otherwise the key is returned with no leading slashes. 137 """ 138 139 while key.startswith("/"): 140 key = key[1:] 141 142 return "/" + key if slash else key
Normalises the left of the key.
If slash is true then the key is returned with exactly one leading
slash, otherwise the key is returned with no leading slashes.
144 @staticmethod 145 def normal_right(key: str, slash: bool = False) -> str: 146 """ 147 Normalises the right of the key. 148 149 If `slash` is true then the key is returned with exactly one trailing 150 slash, otherwise the key is returned with no trailing slashes. 151 """ 152 153 while key.endswith("/"): 154 key = key[:-1] 155 156 return key + "/" if slash else key
Normalises the right of the key.
If slash is true then the key is returned with exactly one trailing
slash, otherwise the key is returned with no trailing slashes.
191 def relative_to(self, parent: Union["S3Key", str]) -> str: 192 """ 193 Gets the relative key path from this key to a `parent` key. 194 195 For example, the relative path to "private/clowns.jpg" from parent 196 "private" is "clowns.jpg". 197 """ 198 199 logger.debug( 200 'Calculating the relative key from "%s" to "%s"', 201 self, 202 parent, 203 ) 204 205 parent = str(parent) 206 normal = self.normal_right(parent, slash=True) if parent else parent 207 208 logger.debug('Normalised the parent key to "%s"', normal) 209 210 if not self._key.startswith(normal): 211 raise ValueError(f'"{parent}" is not a parent of "{self}"') 212 213 relative_key = self._key[len(normal) :] # noqa: E203 214 215 logger.debug( 216 'The relative path from "%s" to "%s" is "%s"', 217 parent, 218 self, 219 relative_key, 220 ) 221 222 return relative_key
Gets the relative key path from this key to a parent key.
For example, the relative path to "private/clowns.jpg" from parent "private" is "clowns.jpg".
8class S3Uri: 9 """ 10 An Amazon Web Services S3 URI. 11 12 To construct a URI from a bucket's name and optional key, use the 13 `to_uri()` class method instead. 14 """ 15 16 def __init__(self, uri: str) -> None: 17 m = match(r"[sS]3:\/\/([^/]*)(\/(.*))?", uri) 18 19 if not m: 20 raise ValueError(f'"{uri}" is not an S3 URI') 21 22 self._bucket = str(m.group(1)) 23 self._key = S3Key(m.group(3)) 24 25 def __add__(self, suffix: str) -> "S3Uri": 26 return self.append(suffix) 27 28 def __eq__(self, other: Any) -> bool: 29 return self.uri == str(other) 30 31 def __repr__(self) -> str: 32 return self.uri 33 34 def __truediv__(self, suffix: str) -> "S3Uri": 35 return self.join(suffix) 36 37 def append(self, other: str) -> "S3Uri": 38 """ 39 Appends a string to the URI. 40 41 ```python 42 images = S3Uri("s3://circus/staff-") 43 44 steve = images.append("steve.jpg") 45 # "s3://circus/staff-steve.jpg" 46 47 # Or use "+": 48 penny = images + "penny.jpg" 49 # "s3://circus/staff-penny.jpg" 50 ``` 51 52 To add a suffix with a "/" delimiter, use `join()` instead. 53 """ 54 55 return S3Uri.to_uri(self._bucket, self._key.append(other)) 56 57 @property 58 def bucket(self) -> str: 59 """ 60 Bucket. 61 """ 62 63 return self._bucket 64 65 def join(self, suffix: str) -> "S3Uri": 66 """ 67 Joins a string to the URI with a "/" delimiter. 68 69 ```python 70 images = S3Uri("s3://circus/staff") 71 72 steve = images.join("steve.jpg") 73 # "s3://circus/staff/steve.jpg" 74 75 # Or use "/": 76 penny = images / "penny.jpg" 77 # "s3://circus/staff/penny.jpg" 78 ``` 79 80 To append a string without a "/" delimiter, use `append()` instead. 81 """ 82 83 return S3Uri.to_uri(self._bucket, self._key.join(suffix)) 84 85 @property 86 def key(self) -> S3Key: 87 """ 88 Key. 89 """ 90 91 return self._key 92 93 @property 94 def leaf(self) -> str: 95 """ 96 URI leaf. 97 98 In a file system metaphor, the leaf would be the file's name. 99 100 For example, the leaf of "s3://circus/private/clowns.jpg" is 101 "clowns.jpg". 102 """ 103 104 return self.key.leaf 105 106 @property 107 def parent(self) -> "S3Uri": 108 """ 109 Parent URI. 110 111 For example, the parent of "s3://circus/private/clowns.jpg" is 112 "s3://circus/private/". 113 """ 114 115 return S3Uri.to_uri(self._bucket, self.key.parent) 116 117 def relative_to(self, parent: Union["S3Uri", str]) -> str: 118 """ 119 Gets the relative key path from this URI to a `parent` URI. 120 121 For example, the relative path to "s3://circus/private/clowns.jpg" from 122 "s3://circus/" is "private/clowns.jpg". 123 """ 124 125 parent = S3Uri(parent) if isinstance(parent, str) else parent 126 127 if parent._bucket != self._bucket: 128 raise ValueError( 129 f'There is no relative path from "{parent}" to "{self}" ' 130 "because these URIs describe different buckets" 131 ) 132 133 return self._key.relative_to(parent.key) 134 135 @staticmethod 136 def to_string(bucket: str, key: Optional[Union[S3Key, str]]) -> str: 137 """ 138 Constructs a string S3 URI from a bucket and optional key. 139 140 To construct an `S3Uri` instance, use `to_uri()` instead. 141 """ 142 143 return f"s3://{bucket}/{key or ''}" 144 145 @classmethod 146 def to_uri( 147 cls, 148 bucket: str, 149 key: Optional[Union[S3Key, str]] = None, 150 ) -> "S3Uri": 151 """ 152 Constructs an `S3Uri` from a bucket and optional key. 153 """ 154 155 return cls(cls.to_string(bucket, key=key)) 156 157 @property 158 def uri(self) -> str: 159 """ 160 URI. 161 """ 162 163 return self.to_string(self._bucket, self._key)
An Amazon Web Services S3 URI.
To construct a URI from a bucket's name and optional key, use the
to_uri() class method instead.
37 def append(self, other: str) -> "S3Uri": 38 """ 39 Appends a string to the URI. 40 41 ```python 42 images = S3Uri("s3://circus/staff-") 43 44 steve = images.append("steve.jpg") 45 # "s3://circus/staff-steve.jpg" 46 47 # Or use "+": 48 penny = images + "penny.jpg" 49 # "s3://circus/staff-penny.jpg" 50 ``` 51 52 To add a suffix with a "/" delimiter, use `join()` instead. 53 """ 54 55 return S3Uri.to_uri(self._bucket, self._key.append(other))
Appends a string to the URI.
images = S3Uri("s3://circus/staff-")
steve = images.append("steve.jpg")
# "s3://circus/staff-steve.jpg"
# Or use "+":
penny = images + "penny.jpg"
# "s3://circus/staff-penny.jpg"
To add a suffix with a "/" delimiter, use join() instead.
65 def join(self, suffix: str) -> "S3Uri": 66 """ 67 Joins a string to the URI with a "/" delimiter. 68 69 ```python 70 images = S3Uri("s3://circus/staff") 71 72 steve = images.join("steve.jpg") 73 # "s3://circus/staff/steve.jpg" 74 75 # Or use "/": 76 penny = images / "penny.jpg" 77 # "s3://circus/staff/penny.jpg" 78 ``` 79 80 To append a string without a "/" delimiter, use `append()` instead. 81 """ 82 83 return S3Uri.to_uri(self._bucket, self._key.join(suffix))
Joins a string to the URI with a "/" delimiter.
images = S3Uri("s3://circus/staff")
steve = images.join("steve.jpg")
# "s3://circus/staff/steve.jpg"
# Or use "/":
penny = images / "penny.jpg"
# "s3://circus/staff/penny.jpg"
To append a string without a "/" delimiter, use append() instead.
URI leaf.
In a file system metaphor, the leaf would be the file's name.
For example, the leaf of "s3://circus/private/clowns.jpg" is "clowns.jpg".
Parent URI.
For example, the parent of "s3://circus/private/clowns.jpg" is "s3://circus/private/".
117 def relative_to(self, parent: Union["S3Uri", str]) -> str: 118 """ 119 Gets the relative key path from this URI to a `parent` URI. 120 121 For example, the relative path to "s3://circus/private/clowns.jpg" from 122 "s3://circus/" is "private/clowns.jpg". 123 """ 124 125 parent = S3Uri(parent) if isinstance(parent, str) else parent 126 127 if parent._bucket != self._bucket: 128 raise ValueError( 129 f'There is no relative path from "{parent}" to "{self}" ' 130 "because these URIs describe different buckets" 131 ) 132 133 return self._key.relative_to(parent.key)
Gets the relative key path from this URI to a parent URI.
For example, the relative path to "s3://circus/private/clowns.jpg" from "s3://circus/" is "private/clowns.jpg".
145 @classmethod 146 def to_uri( 147 cls, 148 bucket: str, 149 key: Optional[Union[S3Key, str]] = None, 150 ) -> "S3Uri": 151 """ 152 Constructs an `S3Uri` from a bucket and optional key. 153 """ 154 155 return cls(cls.to_string(bucket, key=key))
Constructs an S3Uri from a bucket and optional key.