Skip to content

Commit

Permalink
Enabled support for colon character in HAzureBlockBlobStore
Browse files Browse the repository at this point in the history
Issue: #119
  • Loading branch information
Timo Strunk authored and Timo Strunk committed Mar 5, 2024
1 parent b5e2d9e commit 215eb1b
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 10 deletions.
1 change: 1 addition & 0 deletions docs/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Changelog
=====
* Add `session_token` url param that can be set when creating a `[h]s3://` store
via `get_store_from_url`.
* Allow colons in filenames for `HAzureBlockBlobStore`

1.8.6
=====
Expand Down
8 changes: 8 additions & 0 deletions minimalkv/_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,11 @@
Allowed are all alphanumeric characters, as well as ``!"`#$%&'()+,-.<=>?@[]^_{}~/``. and spaces"""
VALID_KEY_RE_EXTENDED = re.compile(VALID_KEY_REGEXP_EXTENDED)
"""A compiled version of :data:`~minimalkv._constants.VALID_KEY_REGEXP_EXTENDED`."""

VALID_KEY_REGEXP_COLON_EXTENDED = "^[%s0-9a-zA-Z:]+$" % re.escape(

Check warning on line 21 in minimalkv/_constants.py

View check run for this annotation

Codecov / codecov/patch

minimalkv/_constants.py#L21

Added line #L21 was not covered by tests
VALID_NON_NUM_EXTENDED
)
"""This regular expression is the same as :data:`~minimalkv._constants.VALID_KEY_REGEXP_EXTENDED`

Check warning on line 24 in minimalkv/_constants.py

View check run for this annotation

Codecov / codecov/patch

minimalkv/_constants.py#L24

Added line #L24 was not covered by tests
but also allows a colon."""
VALID_KEY_RE_COLON_EXTENDED = re.compile(VALID_KEY_REGEXP_COLON_EXTENDED)
"""A compiled version of :data:`~minimalkv._constants.VALID_KEY_REGEXP_COLON_EXTENDED`."""

Check warning on line 27 in minimalkv/_constants.py

View check run for this annotation

Codecov / codecov/patch

minimalkv/_constants.py#L26-L27

Added lines #L26 - L27 were not covered by tests
4 changes: 2 additions & 2 deletions minimalkv/_hstores.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os

from minimalkv._mixins import ExtendedKeyspaceMixin
from minimalkv._mixins import ExtendedKeyspaceMixin, ExtendedKeyspaceMixinColon

Check warning on line 3 in minimalkv/_hstores.py

View check run for this annotation

Codecov / codecov/patch

minimalkv/_hstores.py#L3

Added line #L3 was not covered by tests
from minimalkv.fs import FilesystemStore
from minimalkv.memory import DictStore
from minimalkv.memory.redisstore import RedisStore
Expand All @@ -19,7 +19,7 @@ class HRedisStore(ExtendedKeyspaceMixin, RedisStore): # noqa D
pass


class HAzureBlockBlobStore(ExtendedKeyspaceMixin, AzureBlockBlobStore): # noqa D
class HAzureBlockBlobStore(ExtendedKeyspaceMixinColon, AzureBlockBlobStore): # noqa D

Check warning on line 22 in minimalkv/_hstores.py

View check run for this annotation

Codecov / codecov/patch

minimalkv/_hstores.py#L22

Added line #L22 was not covered by tests
pass


Expand Down
38 changes: 35 additions & 3 deletions minimalkv/_mixins.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import abc
import re

Check warning on line 2 in minimalkv/_mixins.py

View check run for this annotation

Codecov / codecov/patch

minimalkv/_mixins.py#L1-L2

Added lines #L1 - L2 were not covered by tests
from io import BytesIO
from typing import BinaryIO, Callable, Optional, Union

from minimalkv._constants import FOREVER, NOT_SET, VALID_KEY_RE_EXTENDED
from minimalkv._constants import (

Check warning on line 6 in minimalkv/_mixins.py

View check run for this annotation

Codecov / codecov/patch

minimalkv/_mixins.py#L6

Added line #L6 was not covered by tests
FOREVER,
NOT_SET,
VALID_KEY_RE_COLON_EXTENDED,
VALID_KEY_RE_EXTENDED,
)


class UrlMixin:
Expand Down Expand Up @@ -387,7 +394,7 @@ def _move(self, source: str, dest: str) -> str:
return dest


class ExtendedKeyspaceMixin:
class ExtendedKeyspaceMixinBase:

Check warning on line 397 in minimalkv/_mixins.py

View check run for this annotation

Codecov / codecov/patch

minimalkv/_mixins.py#L397

Added line #L397 was not covered by tests
"""A mixin to extend the keyspace to allow slashes and spaces in keynames.
Attention: A single / is NOT allowed.
Expand All @@ -397,6 +404,18 @@ class ExtendedKeyspaceMixin:
"""

@property
@abc.abstractmethod
def VALID_KEY_RE(self) -> re.Pattern:

Check warning on line 409 in minimalkv/_mixins.py

View check run for this annotation

Codecov / codecov/patch

minimalkv/_mixins.py#L407-L409

Added lines #L407 - L409 were not covered by tests
"""Method returning a compiled regular expression to validate the key.
Returns
-------
re.Pattern:
Expression to validate against
"""
raise NotImplementedError("Implement this property in child classes")

Check warning on line 417 in minimalkv/_mixins.py

View check run for this annotation

Codecov / codecov/patch

minimalkv/_mixins.py#L417

Added line #L417 was not covered by tests

def _check_valid_key(self, key: Optional[str]) -> None:
"""Check if a key is valid and raises a ValueError if its not.
Expand All @@ -412,5 +431,18 @@ def _check_valid_key(self, key: Optional[str]) -> None:
if key is not None:
if not isinstance(key, str):
raise ValueError("%r is not a valid key type" % key)
elif not VALID_KEY_RE_EXTENDED.match(key) or key == "/":
elif not self.VALID_KEY_RE.match(key) or key == "/":
breakpoint()

Check warning on line 435 in minimalkv/_mixins.py

View check run for this annotation

Codecov / codecov/patch

minimalkv/_mixins.py#L434-L435

Added lines #L434 - L435 were not covered by tests
raise ValueError("%r contains illegal characters" % key)


class ExtendedKeyspaceMixin(ExtendedKeyspaceMixinBase):
@property
def VALID_KEY_RE(self) -> re.Pattern:
return VALID_KEY_RE_EXTENDED

Check warning on line 442 in minimalkv/_mixins.py

View check run for this annotation

Codecov / codecov/patch

minimalkv/_mixins.py#L439-L442

Added lines #L439 - L442 were not covered by tests


class ExtendedKeyspaceMixinColon(ExtendedKeyspaceMixinBase):
@property
def VALID_KEY_RE(self) -> re.Pattern:
return VALID_KEY_RE_COLON_EXTENDED

Check warning on line 448 in minimalkv/_mixins.py

View check run for this annotation

Codecov / codecov/patch

minimalkv/_mixins.py#L445-L448

Added lines #L445 - L448 were not covered by tests
2 changes: 2 additions & 0 deletions minimalkv/contrib/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from minimalkv._constants import (
VALID_KEY_RE_COLON_EXTENDED,
VALID_KEY_RE_EXTENDED,
VALID_KEY_REGEXP_EXTENDED,
VALID_NON_NUM_EXTENDED,
Expand All @@ -9,5 +10,6 @@
"VALID_NON_NUM_EXTENDED",
"VALID_KEY_REGEXP_EXTENDED",
"VALID_KEY_RE_EXTENDED",
"VALID_KEY_RE_COLON_EXTENDED",
"ExtendedKeyspaceMixin",
]
19 changes: 14 additions & 5 deletions tests/test_azure_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from basic_store import BasicStore, OpenSeekTellStore
from conftest import ExtendedKeyspaceTests

from minimalkv._mixins import ExtendedKeyspaceMixin
from minimalkv._hstores import HAzureBlockBlobStore
from minimalkv.net.azurestore import AzureBlockBlobStore

asb = pytest.importorskip("azure.storage.blob")
Expand Down Expand Up @@ -86,10 +86,7 @@ def store(self):
pytest.skip("Compatibility issues with azurite and azure-storage-blob<12")
container = str(uuid())

class ExtendedKeysStore(ExtendedKeyspaceMixin, AzureBlockBlobStore):
pass

with ExtendedKeysStore(
with HAzureBlockBlobStore(
conn_string=conn_string, container=container, public=False
) as store:
yield store
Expand Down Expand Up @@ -139,6 +136,18 @@ def test_azure_dangling_port_explicit_close_multi():
store.close()


@pytest.mark.filterwarnings("error")
def test_azure_colon_compatibility():
container = str(uuid())
conn_string = get_azure_conn_string()
with HAzureBlockBlobStore(conn_string=conn_string, container=container) as store:
if not hasattr(store, "blob_container_client"):
# This test only runs for azurestore_new
return
store.put("Test:file", b"Test data")
assert store.get("Test:file") == b"Test data"


def test_azure_setgetstate():
container = str(uuid())
conn_string = get_azure_conn_string()
Expand Down

0 comments on commit 215eb1b

Please sign in to comment.