-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #35 from investigativedata/develop
v0.1.0
- Loading branch information
Showing
19 changed files
with
502 additions
and
149 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
0.0.6 | ||
0.1.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,4 +12,4 @@ | |
] | ||
|
||
|
||
__version__ = "0.0.6" | ||
__version__ = "0.1.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from functools import cache | ||
from urllib.parse import urlparse | ||
|
||
from anystore.settings import Settings | ||
from anystore.store.base import BaseStore | ||
from anystore.store.fs import Store | ||
from anystore.store.redis import RedisStore | ||
from anystore.store.sql import SqlStore | ||
from anystore.util import ensure_uri | ||
|
||
|
||
settings = Settings() | ||
|
||
|
||
@cache | ||
def get_store(**kwargs) -> BaseStore: | ||
uri = kwargs.get("uri") | ||
if uri is None: | ||
if settings.yaml_uri is not None: | ||
store = BaseStore.from_yaml_uri(settings.yaml_uri, **kwargs) | ||
return get_store(**store.model_dump()) | ||
if settings.json_uri is not None: | ||
store = BaseStore.from_json_uri(settings.json_uri, **kwargs) | ||
return get_store(**store.model_dump()) | ||
uri = ensure_uri(uri) | ||
parsed = urlparse(uri) | ||
if parsed.scheme == "redis": | ||
return RedisStore(**kwargs) | ||
if "sql" in parsed.scheme: | ||
return SqlStore(**kwargs) | ||
return Store(**kwargs) | ||
|
||
|
||
__all__ = ["get_store", "Store", "RedisStore", "SqlStore"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
""" | ||
Store backend using any file-like location usable via `fsspec` | ||
""" | ||
|
||
from typing import Generator | ||
|
||
import fsspec | ||
from banal import ensure_dict | ||
|
||
from anystore.io import smart_read, smart_write | ||
from anystore.exceptions import DoesNotExist | ||
from anystore.store.base import BaseStore | ||
from anystore.types import Uri, Value | ||
|
||
|
||
class Store(BaseStore): | ||
def _write(self, key: Uri, value: Value, **kwargs) -> None: | ||
return smart_write(key, value, **kwargs) | ||
|
||
def _read( | ||
self, key: Uri, raise_on_nonexist: bool | None = True, **kwargs | ||
) -> Value | None: | ||
try: | ||
return smart_read(str(key), **kwargs) | ||
except FileNotFoundError: | ||
if raise_on_nonexist: | ||
raise DoesNotExist(f"Key does not exist: `{key}`") | ||
return None | ||
|
||
# def _exists(self, key: Uri) -> bool: | ||
def _get_key_prefix(self) -> str: | ||
return str(self.uri).rstrip("/") | ||
|
||
def _iterate_keys(self, prefix: str | None = None) -> Generator[str, None, None]: | ||
path = self.get_key(prefix or "") | ||
mapper = fsspec.get_mapper(path, **ensure_dict(self.backend_config)) | ||
for key in mapper.keys(): | ||
if prefix: | ||
key = f"{prefix}/{key}" | ||
yield key |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
""" | ||
Store backend using redis-like stores such as Redis, Fakeredis or Apache Kvrocks | ||
""" | ||
|
||
from typing import Any, Generator | ||
import logging | ||
import os | ||
from functools import cache | ||
|
||
from banal import as_bool | ||
import redis | ||
import fakeredis | ||
|
||
from anystore.exceptions import DoesNotExist | ||
from anystore.store.base import BaseStore | ||
from anystore.types import Uri, Value | ||
|
||
|
||
log = logging.getLogger(__name__) | ||
|
||
|
||
@cache | ||
def get_redis(uri: str) -> fakeredis.FakeStrictRedis | redis.Redis: | ||
if as_bool(os.environ.get("REDIS_DEBUG")): | ||
con = fakeredis.FakeStrictRedis() | ||
con.ping() | ||
log.info("Redis connected: `fakeredis`") | ||
return con | ||
con = redis.from_url(uri) | ||
con.ping() | ||
log.info("Redis connected: `{uri}`") | ||
return con | ||
|
||
|
||
class RedisStore(BaseStore): | ||
def _write(self, key: Uri, value: Value, **kwargs) -> None: | ||
con = get_redis(self.uri) | ||
con.set(str(key), value, **kwargs) | ||
|
||
def _read(self, key: Uri, raise_on_nonexist: bool | None = True, **kwargs) -> Any: | ||
con = get_redis(self.uri) | ||
key = str(key) | ||
# `None` could be stored as an actual value, to implement `raise_on_nonexist` | ||
# we need to check this first: | ||
if raise_on_nonexist and not con.exists(key): | ||
raise DoesNotExist | ||
res = con.get(str(key)) | ||
# mimic fs read mode: | ||
if kwargs.get("mode") == "r" and isinstance(res, bytes): | ||
res = res.decode() | ||
return res | ||
|
||
def _get_key_prefix(self) -> str: | ||
if self.backend_config is not None: | ||
return self.backend_config.get("redis_prefix") or "anystore" | ||
return "anystore" | ||
|
||
def _iterate_keys(self, prefix: str | None = None) -> Generator[str, None, None]: | ||
con = get_redis(self.uri) | ||
prefix = self.get_key(prefix or "") + "*" | ||
key_prefix = self._get_key_prefix() | ||
for key in con.scan_iter(prefix): | ||
key = key.decode() | ||
yield key[len(key_prefix) + 1 :] |
Oops, something went wrong.