Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update filesystem datastore to async/await #13

Merged
merged 4 commits into from
Jan 28, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 43 additions & 5 deletions datastore/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,46 @@
__version__ = '0.3.6'
__author__ = 'Juan Batiz-Benet'
__email__ = 'juan@benet.ai'
"""
Datastore is a generic layer of abstraction for data store and database access.
It is a **simple** API with the aim to enable application development in a
datastore-agnostic way, allowing datastores to be swapped seamlessly without
changing application code. Thus, one can leverage different datastores with
different strengths without committing the application to one datastore
throughout its lifetime.
"""

from .core import *
from .filesystem import *
__version__ = "0.3.6"
__author__ = "Juan Batiz-Benet, Alexander Schlarb"
__email__ = "juan@benet.ai, alexander@ninetailed.ninja"
__all__ = (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work exposing those Classes directly.

"Key", "Namespace",
"BinaryNullDatastore", "BinaryDictDatastore",
"ObjectNullDatastore", "ObjectDictDatastore",
"Query", "Cursor",
"SerializerAdapter",

"abc", "typing", "util"
)


# import core.key
from .core.key import Key
from .core.key import Namespace

# import core.binarystore, core.objectstore
from .core.binarystore import NullDatastore as BinaryNullDatastore
from .core.binarystore import DictDatastore as BinaryDictDatastore

from .core.objectstore import NullDatastore as ObjectNullDatastore
from .core.objectstore import DictDatastore as ObjectDictDatastore

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will also have to expose FileSystemDatastore and FileReader

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thought was that the filesystem datastore has to be explicitly imported using datastore.filesystem as it is not needed if another datastore (like leveldb or the in-memory dict one) is used.

FileReader is just an implementation detail of how the datastore manages to return its datastore.abc.ReceiveStream. Its not really meant to be used directly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay 👍

# import core.query
from .core.query import Query
from .core.query import Cursor

# import core.serialize
from .core.serialize import SerializerAdapter


### Exposed submodules ###
from . import abc
from . import typing
from . import util
6 changes: 3 additions & 3 deletions datastore/adapter/directory.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ async def directory(self, dir_key: datastore.Key, exist_ok: bool = False) -> boo
try:
await (await super().get(dir_key)).aclose()
except KeyError:
await super()._put(dir_key, datastore.receive_channel_from([]))
await super()._put(dir_key, datastore.util.receive_channel_from([]))
return True
else:
if not exist_ok:
Expand Down Expand Up @@ -86,7 +86,7 @@ async def directory_add(self, dir_key: datastore.Key, key: datastore.Key,

if key_str not in dir_items:
dir_items.append(key_str)
await super()._put(dir_key, datastore.receive_channel_from(dir_items))
await super()._put(dir_key, datastore.util.receive_channel_from(dir_items))


@typing.no_type_check
Expand All @@ -112,7 +112,7 @@ async def directory_remove(self, dir_key: datastore.Key, key: datastore.Key,
if not missing_ok:
raise KeyError(f"{key} in {dir_key}") from None
else:
await super()._put(dir_key, datastore.receive_channel_from(dir_items))
await super()._put(dir_key, datastore.util.receive_channel_from(dir_items))



Expand Down
34 changes: 0 additions & 34 deletions datastore/core/__init__.py

This file was deleted.

23 changes: 13 additions & 10 deletions datastore/core/test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ def encode(self, value):


def check_length(self, length: int) -> None:
try:
for sn in self.stores:
assert len(sn) == length
except TypeError:
pass
for sn in self.stores:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

try:
assert len(sn) == length # type: ignore[arg-type]
except TypeError:
pass


async def subtest_remove_nonexistent(self) -> None:
Expand All @@ -60,11 +60,12 @@ async def subtest_remove_nonexistent(self) -> None:

async def subtest_insert_elems(self) -> None:
sn: DS
key: datastore.Key
value: int

# insert numelems elems
for value in range(0, self.numelems):
key: datastore.Key = self.pkey.child(value)
key = self.pkey.child(value)
for sn in self.stores:
assert not await sn.contains(key)
await sn.put(key, self.encode(value))
Expand All @@ -75,19 +76,20 @@ async def subtest_insert_elems(self) -> None:
self.check_length(self.numelems)

for value in range(0, self.numelems):
key: datastore.Key = self.pkey.child(value)
key = self.pkey.child(value)
for sn in self.stores:
assert await sn.contains(key)
assert await sn.get_all(key) == self.encode(value)

self.check_length(self.numelems)


@typing.no_type_check #FIXME: This method is broken
async def check_query(self, query, total, slice) -> datastore.Cursor:
assert not self.is_binary # Queries are only supported for object stores

allitems: List[int] = list(range(0, total))
sn: datastore.ObjectDatastore
allitems: typing.List[int] = list(range(0, total))
sn: datastore.abc.ObjectDatastore
resultset: datastore.Cursor

for sn in self.stores:
Expand All @@ -110,11 +112,12 @@ async def check_query(self, query, total, slice) -> datastore.Cursor:
return resultset


@typing.no_type_check #FIXME: This method is broken
async def subtest_queries(self) -> None:
if self.is_binary:
return # Not supported on binary datastores

sn: datastore.ObjectDatastore
sn: datastore.abc.ObjectDatastore
value: int

for value in range(0, self.numelems):
Expand Down
9 changes: 4 additions & 5 deletions datastore/core/test/test_store.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import importlib
import logging
import unittest
from typing import Callable, List, Tuple, Type, TypeVar, Union, TYPE_CHECKING

import pytest
import trio.testing

from datastore.core import BinaryDictDatastore, ObjectDictDatastore
from datastore.core import BinaryNullDatastore, ObjectNullDatastore
from datastore.core.key import Key
from datastore.core.query import Query
from datastore import BinaryDictDatastore, ObjectDictDatastore
from datastore import BinaryNullDatastore, ObjectNullDatastore
from datastore import Key
from datastore import Query

import datastore.adapter.logging

Expand Down
5 changes: 3 additions & 2 deletions datastore/filesystem/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
__version__ = '1.2'
__author__ = 'Juan Batiz-Benet <juan@benet.ai>'
__version__ = "2.0"
__author__ = "Juan Batiz-Benet, Alexander Schlarb"
__email__ = "juan@benet.ai, alexander@ninetailed.ninja"
__doc__ = """
Filesystem datastore implementation
"""
Expand Down
Loading