Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
bcfb173
attachments are saved as intact files
dimitri-yatsenko Sep 13, 2019
18366e6
reform attachments and filepath
dimitri-yatsenko Sep 13, 2019
11d7d9b
complete implementation of external storage except for `clean`
dimitri-yatsenko Sep 16, 2019
22347ae
Merge branch 'dev' of https://github.com/datajoint/datajoint-python i…
dimitri-yatsenko Sep 16, 2019
7e7c183
refactor external storage
dimitri-yatsenko Sep 18, 2019
8aa1543
complete refactoring of external storage for version 0.12
dimitri-yatsenko Sep 20, 2019
a2d6f9a
rename attribute `basename` to `attachment_name` in external table
dimitri-yatsenko Sep 20, 2019
2c11a65
add __repr__ to ExternalMapping
dimitri-yatsenko Sep 20, 2019
3a1c6ab
external files are not copied if stage and store are the same
dimitri-yatsenko Sep 20, 2019
478b36a
make external tables require setting the `delete_external_files` argu…
dimitri-yatsenko Sep 20, 2019
bb1deab
update CHANGELOG
dimitri-yatsenko Sep 23, 2019
e2636ed
fix Python 3.4 compatibility
dimitri-yatsenko Sep 23, 2019
11a1f93
fix Python 3.4 and 3.5 compatibility
dimitri-yatsenko Sep 23, 2019
165f795
dropped support for Python 3.4
dimitri-yatsenko Sep 23, 2019
c18af74
Merge branch 'dev' of https://github.com/datajoint/datajoint-python i…
dimitri-yatsenko Sep 26, 2019
48147f1
minor changes in error messages
dimitri-yatsenko Oct 1, 2019
2e26c4a
Merge branch 'dev' of https://github.com/datajoint/datajoint-python i…
dimitri-yatsenko Oct 3, 2019
0c4fd1c
Update to pathlib in test init.
guzman-raphael Oct 3, 2019
6ba86e0
Update test_blob_migrate to be compatible for WIN10.
guzman-raphael Oct 3, 2019
43a5126
Fix WIN10 compatibility with KeyboardInterrupt and SystemExit excepti…
guzman-raphael Oct 3, 2019
c7ca34c
Merge pull request #4 from guzman-raphael/dimitri-attach
dimitri-yatsenko Oct 3, 2019
5c99e37
Fix WIN10 filepath to store as posix and fetch as user's platform.
guzman-raphael Oct 4, 2019
e2c3f23
Fix relpath for Python3.5.
guzman-raphael Oct 4, 2019
93aeefc
Fix copytree for Python3.5.
guzman-raphael Oct 4, 2019
20719ae
Fix typo.
guzman-raphael Oct 4, 2019
7ca0099
Fix for Python3.5.
guzman-raphael Oct 4, 2019
f3ffd63
Update coveralls.
guzman-raphael Oct 4, 2019
bb1b40f
Update coverall env vars.
guzman-raphael Oct 4, 2019
f05c50d
Merge pull request #5 from guzman-raphael/win-filepath
dimitri-yatsenko Oct 5, 2019
298efed
add environment variable DJ_SUPPORT_FILEPATH_MANAGEMENT to enable/dis…
dimitri-yatsenko Oct 7, 2019
e609fbe
Merge branch 'attach' of https://github.com/dimitri-yatsenko/datajoin…
dimitri-yatsenko Oct 7, 2019
6dda528
Update CHANGELOG.md
dimitri-yatsenko Oct 8, 2019
796dae6
Update CHANGELOG.md
dimitri-yatsenko Oct 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
make external tables require setting the delete_external_files argu…
…ment
  • Loading branch information
dimitri-yatsenko committed Sep 20, 2019
commit 478b36a651b232658a34d22e43b5601ac8a0bec1
45 changes: 27 additions & 18 deletions datajoint/external.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,29 +303,38 @@ def used(self):
return self & ["hash IN (SELECT `{column_name}` FROM {referencing_table})".format(**ref)
for ref in self.references]

def delete(self, limit=None, display_progress=True):
def delete(self, *, delete_external_files=None, limit=None, display_progress=True):
"""
:param delete_external_files: True or False. If False, only the tracking info is removed from the
external store table but the external files remain intact. If True, then the external files
themselves are deleted too.
:param limit: (integer) limit the number of items to delete
:param display_progress: if True, display progress as files are cleaned up
:return: yields
"""
items = self.unused().fetch_external_paths(limit=limit)
if display_progress:
items = tqdm(items)
# delete items one by one, close to transaction-safe
error_list = []
for uuid, external_path in items:
try:
count = (self & {'hash': uuid}).delete_quick(get_count=True) # optimize
except Exception as err:
pass # if delete failed, do not remove the external file
else:
assert count in (0, 1)
if delete_external_files not in (True, False):
raise DataJointError("The delete_external_files argument must be set to either True or False in delete()")

if not delete_external_files:
self.unused.delete_quick()
else:
items = self.unused().fetch_external_paths(limit=limit)
if display_progress:
items = tqdm(items)
# delete items one by one, close to transaction-safe
error_list = []
for uuid, external_path in items:
try:
self._remove_external_file(external_path)
except Exception as error:
error_list.append((uuid, external_path, str(error)))
return error_list
count = (self & {'hash': uuid}).delete_quick(get_count=True) # optimize
except Exception as err:
pass # if delete failed, do not remove the external file
else:
assert count in (0, 1)
try:
self._remove_external_file(external_path)
except Exception as error:
error_list.append((uuid, external_path, str(error)))
return error_list


class ExternalMapping(Mapping):
Expand All @@ -341,7 +350,7 @@ def __init__(self, schema):

def __repr__(self):
return ("External file tables for schema `{schema}`:\n ".format(schema=self.schema.database)
+ "\n ".join('"{store}" {protocol}:{location}"'.format(
+ "\n ".join('"{store}" {protocol}:{location}'.format(
store=k, **v.spec) for k, v in self.items()))

def __getitem__(self, store):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_external_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def test_populate():
assert_almost_equal(img, -neg)
image.delete()
for external_table in image.external.values():
external_table.delete(display_progress=False)
external_table.delete(display_progress=False, delete_external_files=True)



6 changes: 3 additions & 3 deletions tests/test_filepath.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def test_filepath(store="repo"):
assert_equal(data, synced_data)

# cleanup
ext.delete()
ext.delete(delete_external_files=True)


def test_filepath_s3():
Copy link
Collaborator

Choose a reason for hiding this comment

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

This test failed on WIN10. For example, the result of managed_file was dj/repo/one\two\three\picture.dat.

Expand Down Expand Up @@ -116,7 +116,7 @@ def test_filepath_class(table=Filepath(), store="repo"):
assert_true(table.external[store])

# delete from external table
table.external[store].delete()
table.external[store].delete(delete_external_files=True)


def test_filepath_class_again():
Copy link
Collaborator

Choose a reason for hiding this comment

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

  • This test failed on WIN10 at test_filepath_class_again. Error details: datajoint.errors.DataJointError: A different version of 'one\two\three\attachment.dat' has already been placed
  • This test failed on WIN10 at test_filepath_class_s3. For example, the result of managed_file was dj/repo/one\two\three\attachment.dat.
  • This test failed on WIN10 at test_filepath_class_s3_again. For example, the result of managed_file was dj/repo/one\two\three\attachment.dat.

Expand Down Expand Up @@ -155,7 +155,7 @@ def test_filepath_cleanup(table=Filepath(), store="repo"):
m = n - len(table) # number deleted
assert_true(m == 6)

ext.delete() # delete unused entries
ext.delete(delete_external_files=True) # delete unused entries
assert_true(0 < len(ext) <= n - m)


Expand Down