Skip to content

Commit b15fe43

Browse files
committed
Merging changes from master
2 parents 957c563 + 61dab59 commit b15fe43

File tree

9 files changed

+104
-10
lines changed

9 files changed

+104
-10
lines changed

.github/workflows/development.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ jobs:
4040
PY_VER: ${{matrix.py_ver}}
4141
MYSQL_VER: ${{matrix.mysql_ver}}
4242
ALPINE_VER: "3.10"
43-
MINIO_VER: RELEASE.2019-09-26T19-42-35Z
43+
MINIO_VER: RELEASE.2021-09-03T03-56-13Z
4444
COMPOSE_HTTP_TIMEOUT: "120"
4545
COVERALLS_SERVICE_NAME: travis-ci
4646
COVERALLS_REPO_TOKEN: fd0BoXG46TPReEem0uMy7BJO5j0w1MQiY

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* Bugfix - Dependencies not properly loaded on populate. (#902) PR #919
55
* Bugfix - Replace use of numpy aliases of built-in types with built-in type. (#938) PR #939
66
* Bugfix - `ExternalTable.delete` should not remove row on error (#953) PR #956
7+
* Bugfix - Fix error handling of remove_object function in `s3.py` (#952) PR #955
78

89
### 0.13.2 -- May 7, 2021
910
* Update `setuptools_certificate` dependency to new name `otumat`

LNX-docker-compose.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ services:
7777
- -c
7878
- |
7979
set -e
80+
wget -P /home/dja/.local/bin/ https://dl.min.io/client/mc/release/linux-amd64/mc
81+
chmod +x /home/dja/.local/bin/mc
82+
mc alias set myminio/ http://minio:9000 datajoint datajoint
8083
pip install --user -r test_requirements.txt
8184
pip install -e .
8285
pip freeze | grep datajoint

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ A number of labs are currently adopting DataJoint and we are quickly getting the
108108
PY_VER=3.7
109109
ALPINE_VER=3.10
110110
MYSQL_VER=5.7
111-
MINIO_VER=RELEASE.2019-09-26T19-42-35Z
111+
MINIO_VER=RELEASE.2021-09-03T03-56-13Z
112112
UID=1000
113113
GID=1000
114114
```

datajoint/external.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,11 +317,12 @@ def used(self):
317317
return self & [FreeTable(self.connection, ref['referencing_table']).proj(hash=ref['column_name'])
318318
for ref in self.references]
319319

320-
def delete(self, *, delete_external_files=None, limit=None, display_progress=True):
320+
def delete(self, *, delete_external_files=None, limit=None, display_progress=True, errors_as_string=True):
321321
"""
322322
:param delete_external_files: True or False. If False, only the tracking info is removed from the
323323
external store table but the external files remain intact. If True, then the external files
324324
themselves are deleted too.
325+
:param errors_as_string: If True any errors returned when deleting from external files will be strings
325326
:param limit: (integer) limit the number of items to delete
326327
:param display_progress: if True, display progress as files are cleaned up
327328
:return: if deleting external files, returns errors
@@ -352,7 +353,7 @@ def delete(self, *, delete_external_files=None, limit=None, display_progress=Tru
352353
except Exception as error:
353354
# adding row back into table after failed delete
354355
self.insert1(row[0])
355-
error_list.append((uuid, external_path, str(error)))
356+
error_list.append((uuid, external_path, str(error) if errors_as_string else error))))
356357
return error_list
357358

358359

datajoint/s3.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,11 @@ def get_size(self, name):
7676
except minio.error.S3Error as e:
7777
if e.code == 'NoSuchKey':
7878
raise errors.MissingExternalFile
79-
else:
80-
raise e
79+
raise e
8180

8281
def remove_object(self, name):
8382
logger.debug('remove_object: {}:{}'.format(self.bucket, name))
8483
try:
8584
self.client.remove_object(self.bucket, str(name))
86-
except minio.ResponseError:
87-
return errors.DataJointError('Failed to delete %s from s3 storage' % name)
85+
except minio.error.MinioException:
86+
raise errors.DataJointError('Failed to delete %s from s3 storage' % name)

docs-parts/intro/Releases_lang1.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Bugfix - Dependencies not properly loaded on populate. (#902) PR #919
44
* Bugfix - Replace use of numpy aliases of built-in types with built-in type. (#938) PR #939
55
* Bugfix - `ExternalTable.delete` should not remove row on error (#953) PR #956
6+
* Bugfix - Fix error handling of remove_object function in `s3.py` (#952) PR #955
67

78
0.13.2 -- May 7, 2021
89
----------------------

local-docker-compose.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ services:
8282
- -c
8383
- |
8484
set -e
85+
wget -P /home/dja/.local/bin/ https://dl.min.io/client/mc/release/linux-amd64/mc
86+
chmod +x /home/dja/.local/bin/mc
87+
mc alias set myminio/ http://minio:9000 datajoint datajoint
8588
pip install --user nose nose-cov coveralls flake8 ptvsd
8689
pip install -e .
8790
pip freeze | grep datajoint

tests/test_s3.py

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
from . import S3_CONN_INFO
2-
32
from minio import Minio
3+
import json
44
import urllib3
55
import certifi
6-
from nose.tools import assert_true
6+
from nose.tools import assert_true, raises
7+
from .schema_external import schema, SimpleRemote
8+
from datajoint.errors import DataJointError
9+
import os
10+
from datajoint.hash import uuid_from_buffer
11+
from datajoint.blob import pack
712

813

914
class TestS3:
@@ -51,3 +56,84 @@ def test_connection_secure():
5156
http_client=http_client)
5257

5358
assert_true(minio_client.bucket_exists(S3_CONN_INFO['bucket']))
59+
60+
@staticmethod
61+
@raises(DataJointError)
62+
def test_remove_object_exception():
63+
# https://github.com/datajoint/datajoint-python/issues/952
64+
65+
# Initialize minioClient with an endpoint and access/secret keys.
66+
minio_client = Minio(
67+
'minio:9000',
68+
access_key='jeffjeff',
69+
secret_key='jeffjeff',
70+
secure=False)
71+
72+
# Create new user
73+
os.system('mc admin user add myminio jeffjeff jeffjeff')
74+
# json for test policy for permissionless user
75+
testpolicy = {
76+
"Version": "2012-10-17",
77+
"Statement": [
78+
{
79+
"Action": [
80+
"s3:GetBucketLocation",
81+
"s3:ListBucket",
82+
"s3:ListBucketMultipartUploads",
83+
"s3:ListAllMyBuckets"
84+
],
85+
"Effect": "Allow",
86+
"Resource": [
87+
"arn:aws:s3:::datajoint.test",
88+
"arn:aws:s3:::datajoint.migrate"
89+
],
90+
"Sid": ""
91+
},
92+
{
93+
"Action": [
94+
"s3:GetObject",
95+
"s3:ListMultipartUploadParts"
96+
],
97+
"Effect": "Allow",
98+
"Resource": [
99+
"arn:aws:s3:::datajoint.test/*",
100+
"arn:aws:s3:::datajoint.migrate/*"
101+
],
102+
"Sid": ""
103+
}
104+
]
105+
}
106+
107+
# Write test json to tmp directory so we can use it to create a new user policy
108+
with open('/tmp/policy.json', 'w') as f:
109+
f.write(json.dumps(testpolicy))
110+
111+
# Add the policy and apply it to the user
112+
os.system('mc admin policy add myminio test /tmp/policy.json')
113+
os.system('mc admin policy set myminio test user=jeffjeff')
114+
115+
# Insert some test data and remove it so that the external table is populated
116+
test = [1, [1, 2, 3]]
117+
SimpleRemote.insert1(test)
118+
SimpleRemote.delete()
119+
120+
# Save the old external table minio client
121+
old_client = schema.external['share'].s3.client
122+
123+
# Apply our new minio client to the external table that has permissions restrictions
124+
schema.external['share'].s3.client = minio_client
125+
126+
# This method returns a list of errors
127+
error_list = schema.external['share'].delete(delete_external_files=True,
128+
errors_as_string=False)
129+
130+
# Teardown
131+
os.system('mc admin policy remove myminio test')
132+
os.system('mc admin user remove myminio jeffjeff')
133+
schema.external['share'].s3.client = old_client
134+
schema.external['share'].delete(delete_external_files=True)
135+
os.remove("/tmp/policy.json")
136+
137+
# Raise the error we want if the error matches the expected uuid
138+
if str(error_list[0][0]) == str(uuid_from_buffer(pack(test[1]))):
139+
raise error_list[0][2]

0 commit comments

Comments
 (0)