Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
5918b2c
move dj.config into settings.py
dimitri-yatsenko Dec 2, 2018
bc85f21
Merge branch 'dev' into attachments
dimitri-yatsenko Dec 2, 2018
92553b0
Merge branch 'master' of https://github.com/datajoint/datajoint-pytho…
dimitri-yatsenko Dec 2, 2018
c127693
Merge branch 'dev' into attachments
dimitri-yatsenko Dec 3, 2018
1b188da
Merge branch 'dev' into attachments
dimitri-yatsenko Dec 3, 2018
13573c5
Merge branch 'dev' into attachments
dimitri-yatsenko Dec 3, 2018
f3dd5b3
add properties for heading attributes for supporting configurable blo…
dimitri-yatsenko Dec 3, 2018
046291a
rename property is_supported to unsupported for heading attributes
dimitri-yatsenko Dec 3, 2018
1f5fe9d
load configurable fields
dimitri-yatsenko Dec 3, 2018
3350516
implement declaration of configurable attributes: blob- and attach.
dimitri-yatsenko Dec 3, 2018
acc07fb
prepare for saving attachments
dimitri-yatsenko Dec 3, 2018
c11bbbf
add attach.py for saving and loading attachments
dimitri-yatsenko Dec 3, 2018
390b0b7
implement inserting attachments
dimitri-yatsenko Dec 3, 2018
2c04d74
implement fetch of attachments and configurable blobs
dimitri-yatsenko Dec 3, 2018
43e9c76
fix issue #467
dimitri-yatsenko Dec 3, 2018
51336ff
further cleanup of __init__.py
dimitri-yatsenko Dec 3, 2018
cee588e
Use DEFAULT instead of NULL when the insert value is None.
dimitri-yatsenko Dec 3, 2018
c04f974
slight refactor of Table.insert
dimitri-yatsenko Dec 3, 2018
9de4782
fix for error introduced in previous commit
dimitri-yatsenko Dec 3, 2018
0c35af1
Merge branch 'master' of https://github.com/datajoint/datajoint-pytho…
dimitri-yatsenko Dec 3, 2018
1588303
Merge branch 'master' of https://github.com/datajoint/datajoint-pytho…
dimitri-yatsenko Dec 4, 2018
f265674
implement external file folding
dimitri-yatsenko Dec 7, 2018
bcebce5
Merge branch 'master' into attachments
dimitri-yatsenko Dec 11, 2018
50f17ce
remote the `keys` property from `fetch` (a warning was displayed in s…
dimitri-yatsenko Dec 11, 2018
f141aa7
add `dj.get_schema_names()`
dimitri-yatsenko Dec 11, 2018
6310c7d
stylistic improvements
dimitri-yatsenko Dec 13, 2018
7cb1d3f
Merge branch 'master' of https://github.com/datajoint/datajoint-pytho…
dimitri-yatsenko Dec 13, 2018
aa72832
Merge branch 'master' into attachments
dimitri-yatsenko Dec 13, 2018
4818bbb
Merge branch 'master' into attachments
dimitri-yatsenko Dec 19, 2018
3aa936e
complete implementation of attachments and configurable blobs with pa…
dimitri-yatsenko Jan 14, 2019
bdf8195
Merge branch 'master' of https://github.com/datajoint/datajoint-pytho…
dimitri-yatsenko Jan 14, 2019
173bf1d
add test for configurable blobs
dimitri-yatsenko Jan 14, 2019
61c2ce7
drop support of Python 3.4
dimitri-yatsenko Jan 14, 2019
aa6a2ce
add test for attachment methods
dimitri-yatsenko Jan 14, 2019
f49cf22
fix test_attach
dimitri-yatsenko Jan 15, 2019
eea3e20
fix 3.4 compatibility
dimitri-yatsenko Jan 15, 2019
7ee6134
Python 3.4 compatibility
dimitri-yatsenko Jan 15, 2019
6701abb
fix Python 3.4 compatibility
dimitri-yatsenko Jan 15, 2019
346f47f
fix Python 3.4 compatibility
dimitri-yatsenko Jan 15, 2019
b2087aa
fix Python 3.4 compatibility
dimitri-yatsenko Jan 15, 2019
332cfd6
Merge branch 'master' of https://github.com/datajoint/datajoint-pytho…
dimitri-yatsenko Jan 15, 2019
0c491e2
improve error message
dimitri-yatsenko Jan 15, 2019
7e51e4f
improve error message
dimitri-yatsenko Jan 15, 2019
0434fc8
Merge branch 'attachments' of https://github.com/dimitri-yatsenko/dat…
dimitri-yatsenko Jan 16, 2019
484e926
bugfix in S3 store
dimitri-yatsenko Jan 16, 2019
1a83fe6
bugfix in S3 store
dimitri-yatsenko Jan 16, 2019
4c8b6eb
Merge branch 'attachments' of https://github.com/dimitri-yatsenko/dat…
dimitri-yatsenko Jan 16, 2019
bf66d64
Merge branch 'master' of https://github.com/datajoint/datajoint-pytho…
dimitri-yatsenko Jan 22, 2019
8f4e8f9
Merge branch 'master' into attachments
dimitri-yatsenko Feb 4, 2019
0826d94
implement external storage cleanup with subfolding
dimitri-yatsenko Feb 6, 2019
fb14029
fix error message and release date
dimitri-yatsenko Feb 7, 2019
90cf697
improve warning messages
dimitri-yatsenko Feb 8, 2019
afeadb1
change version to 0.12.dev
dimitri-yatsenko Feb 8, 2019
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
Prev Previous commit
Next Next commit
add test for configurable blobs
  • Loading branch information
dimitri-yatsenko committed Jan 14, 2019
commit 173bf1dfb9f1d80a7dd4600426fde463327e6bfd
2 changes: 1 addition & 1 deletion datajoint/heading.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ def init_from_database(self, conn, database, table_name):

# recognize configurable fields
configurable_field = re.match(
r'^:(?P<type>(blob|external|attach)(-\w+)?):(?P<comment>.*)$', attr['comment'])
r'^:(?P<type>(blob|external|attach)(-\w*)?):(?P<comment>.*)$', attr['comment'])
if configurable_field is None:
attr['is_external'] = False
attr['is_attachment'] = False
Expand Down
19 changes: 11 additions & 8 deletions tests/schema_external.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,22 @@
schema = dj.schema(PREFIX + '_extern', connection=dj.conn(**CONN_INFO))


dj.config['external'] = {
dj.config['stores'] = {
'-': {
'protocol': 'file',
'location': 'dj-store/external'}
'location': 'dj-store/external'
},

dj.config['external-raw'] = {
'-raw': {
'protocol': 'file',
'location': 'dj-store/raw'}
'location': 'dj-store/raw'},

dj.config['external-compute'] = {
'-compute': {
'protocol': 's3',
'location': '/datajoint-projects/test',
'user': 'djtest',
'token': '2e05709792545ce'}
}

dj.config['cache'] = tempfile.mkdtemp('dj-cache')

Expand All @@ -33,7 +36,7 @@ class Simple(dj.Manual):
definition = """
simple : int
---
item : external-raw
item : blob-
"""


Expand Down Expand Up @@ -64,8 +67,8 @@ class Image(dj.Computed):
-> Seed
-> Dimension
----
img : external-raw # objects are stored as specified by dj.config['external-raw']
neg : external # objects are stored as specified by dj.config['external']
img : blob-raw # objects are stored as specified by dj.config['stores'][-raw']
neg : blob- # objects are stored as specified by dj.config['stores']['-']
"""

def make(self, key):
Expand Down
74 changes: 74 additions & 0 deletions tests/schema_legacy_external.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""
a schema for testing external attributes using legacy syntax pre-version 0.12.0
"""

import tempfile
import datajoint as dj

from . import PREFIX, CONN_INFO
import numpy as np

schema = dj.schema(PREFIX + '_legacy_extern', connection=dj.conn(**CONN_INFO))


dj.config['external'] = {
'protocol': 'file',
'location': 'dj-legacy/external'}

dj.config['external-raw'] = {
'protocol': 'file',
'location': 'dj-legacy/raw'}

dj.config['external-compute'] = {
'protocol': 's3',
'location': '/datajoint-legacy/test',
'user': 'djtest',
'token': '2e05709792545ce'}

dj.config['cache'] = tempfile.mkdtemp('dj-legacy-cache')


@schema
class Simple(dj.Manual):
definition = """
simple : int
---
item : external-raw
"""


@schema
class Seed(dj.Lookup):
definition = """
seed : int
"""
contents = zip(range(4))


@schema
class Dimension(dj.Lookup):
definition = """
dim : int
---
dimensions : blob
"""
contents = (
[0, [100, 50]],
[1, [3, 4, 8, 6]])


@schema
class Image(dj.Computed):
definition = """
# table for storing
-> Seed
-> Dimension
----
img : external-raw # objects are stored as specified by dj.config['external-raw']
neg : external # objects are stored as specified by dj.config['external']
"""

def make(self, key):
np.random.seed(key['seed'])
img = np.random.rand(*(Dimension() & key).fetch1('dimensions'))
self.insert1(dict(key, img=img, neg=-img.astype(np.float32)))
2 changes: 1 addition & 1 deletion tests/test_external_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


def test_heading():
heading = modu.Simple().heading
heading = modu.Simple.heading
assert_true('item' in heading)
assert_true(heading['item'].is_external)

Expand Down
28 changes: 28 additions & 0 deletions tests/test_legacy_external.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import numpy as np
from numpy.testing import assert_array_equal
from nose.tools import assert_true, assert_equal
from datajoint.external import ExternalTable
from datajoint.blob import pack, unpack

from . schema_legacy_external import schema


def test_external_put():
"""
external storage put and get and remove
"""
ext = ExternalTable(schema.connection, schema.database)
input_ = np.random.randn(3, 7, 8)
count = 7
extra = 3
for i in range(count):
hash1 = ext.put('external-raw', pack(input_))
for i in range(extra):
hash2 = ext.put('external-raw', pack(np.random.randn(4, 3, 2)))

fetched_hashes = ext.fetch('hash')
assert_true(all(hash in fetched_hashes for hash in (hash1, hash2)))
assert_equal(len(ext), 1 + extra)

output_ = unpack(ext.get(hash1))
assert_array_equal(input_, output_)
63 changes: 63 additions & 0 deletions tests/test_legacy_external_class.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from nose.tools import assert_true, assert_list_equal, raises
from numpy.testing import assert_almost_equal
import datajoint as dj
from . import schema_legacy_external as modu


def test_heading():
heading = modu.Simple().heading
Copy link
Contributor

Choose a reason for hiding this comment

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

You removed the () in line 8 of test_external_class.py above. Should you do so here as well?

Copy link
Member Author

Choose a reason for hiding this comment

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

This does not really matter. Accessing attributes of classes directly still triggers instantiation of an object, so a more efficient way is to instantiate. The omission of parentheses was provided for user convenience.

assert_true('item' in heading)
assert_true(heading['item'].is_external)


def test_insert_and_fetch():
original_list = [1, 3, 8]
modu.Simple().insert1(dict(simple=1, item=original_list))
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above; should the () be removed throughout this method?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is inside legacy tests. We support both syntaxes.

# test fetch
q = (modu.Simple() & {'simple': 1}).fetch('item')[0]
assert_list_equal(list(q), original_list)
# test fetch1 as a tuple
q = (modu.Simple() & {'simple': 1}).fetch1('item')
assert_list_equal(list(q), original_list)
# test fetch1 as a dict
q = (modu.Simple() & {'simple': 1}).fetch1()
assert_list_equal(list(q['item']), original_list)
# test without cache
previous_cache = dj.config['cache']
dj.config['cache'] = None
q = (modu.Simple() & {'simple': 1}).fetch1()
assert_list_equal(list(q['item']), original_list)
# test with cache
dj.config['cache'] = previous_cache
q = (modu.Simple() & {'simple': 1}).fetch1()
assert_list_equal(list(q['item']), original_list)


def test_populate():
image = modu.Image()
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we remove these () throughout this and the next two methods?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, we could but, when using the same table multiple times, it's more efficient to instantiate once.

Copy link
Member Author

Choose a reason for hiding this comment

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

This particular snippet is inside test_legacy_external_class, which tests old functionality, so it's a good place to test whether the old syntax still works.

image.populate()
remaining, total = image.progress()
image.external_table.clean_store('raw')
assert_true(total == len(modu.Dimension() * modu.Seed()) and remaining == 0)
for img, neg, dimensions in zip(*(image * modu.Dimension()).fetch('img', 'neg', 'dimensions')):
assert_list_equal(list(img.shape), list(dimensions))
assert_almost_equal(img, -neg)
image.delete()
image.external_table.delete_garbage()
image.external_table.clean_store('raw')


@raises(dj.DataJointError)
def test_drop():
image = modu.Image()
image.populate()
image.external_table.drop()


@raises(dj.DataJointError)
def test_delete():
image = modu.Image()
image.external_table.delete()