dcor-shared 0.7.0__tar.gz → 0.7.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/CHANGELOG +5 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/PKG-INFO +1 -1
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/dcor_shared/_version_save.py +1 -1
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/dcor_shared/s3.py +2 -1
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/dcor_shared/s3cc.py +29 -3
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/dcor_shared/testing.py +5 -2
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/dcor_shared.egg-info/PKG-INFO +1 -1
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/dcor_shared.egg-info/SOURCES.txt +2 -1
- dcor_shared-0.7.2/tests/test_testing.py +46 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/LICENSE +0 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/MANIFEST.in +0 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/README.rst +0 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/dcor_shared/__init__.py +0 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/dcor_shared/_version.py +0 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/dcor_shared/ckan.py +0 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/dcor_shared/data.py +0 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/dcor_shared/mime.py +0 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/dcor_shared/parse.py +0 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/dcor_shared/paths.py +0 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/dcor_shared.egg-info/dependency_links.txt +0 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/dcor_shared.egg-info/requires.txt +0 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/dcor_shared.egg-info/top_level.txt +0 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/setup.cfg +0 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/setup.py +0 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/tests/test_basic.py +0 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/tests/test_data.py +0 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/tests/test_s3.py +0 -0
- {dcor_shared-0.7.0 → dcor_shared-0.7.2}/tests/test_s3cc.py +0 -0
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
0.7.2
|
|
2
|
+
- tests: fix invalid make_dataset method
|
|
3
|
+
0.7.1
|
|
4
|
+
- fix: handle non-existent bucket when S3 object is missing
|
|
5
|
+
- docs: be more verbose in s3cc docstrings
|
|
1
6
|
0.7.0
|
|
2
7
|
- feat: implement `s3.create_presigned_upload_url` for creating presigned
|
|
3
8
|
upload URLs that DCOR-Aid can use to upload resources directly to S3
|
|
@@ -256,7 +256,8 @@ def make_object_public(bucket_name, object_name, missing_ok=False):
|
|
|
256
256
|
response = s3_client.get_object_tagging(
|
|
257
257
|
Bucket=bucket_name,
|
|
258
258
|
Key=object_name)
|
|
259
|
-
except s3_client.exceptions.
|
|
259
|
+
except (s3_client.exceptions.NoSuchBucket,
|
|
260
|
+
s3_client.exceptions.NoSuchKey):
|
|
260
261
|
if not missing_ok:
|
|
261
262
|
raise
|
|
262
263
|
else:
|
|
@@ -26,7 +26,11 @@ def create_presigned_url(
|
|
|
26
26
|
artifact: Literal["condensed", "preview", "resource"] = "resource",
|
|
27
27
|
expiration: int = 3600,
|
|
28
28
|
filename: str = None):
|
|
29
|
-
"""Create a presigned URL for a given artifact of a CKAN resource
|
|
29
|
+
"""Create a presigned URL for a given artifact of a CKAN resource
|
|
30
|
+
|
|
31
|
+
The resource with the identifier `resource_id` must exist in the
|
|
32
|
+
CKAN database.
|
|
33
|
+
"""
|
|
30
34
|
bucket_name, object_name = get_s3_bucket_object_for_artifact(
|
|
31
35
|
resource_id=resource_id, artifact=artifact)
|
|
32
36
|
return s3.create_presigned_url(bucket_name=bucket_name,
|
|
@@ -42,6 +46,9 @@ def get_s3_bucket_object_for_artifact(
|
|
|
42
46
|
|
|
43
47
|
The value of artifact can be either "condensed", "preview", or "resource"
|
|
44
48
|
(those are the keys under which the individual objects are stored in S3).
|
|
49
|
+
|
|
50
|
+
The resource with the identifier `resource_id` must exist in the
|
|
51
|
+
CKAN database.
|
|
45
52
|
"""
|
|
46
53
|
bucket_name = get_s3_bucket_name_for_resource(resource_id=resource_id)
|
|
47
54
|
rid = resource_id
|
|
@@ -54,6 +61,9 @@ def get_s3_bucket_name_for_resource(resource_id):
|
|
|
54
61
|
|
|
55
62
|
The bucket name is determined by the ID of the organization
|
|
56
63
|
which the dataset containing the resource belongs to.
|
|
64
|
+
|
|
65
|
+
The resource with the identifier `resource_id` must exist in the
|
|
66
|
+
CKAN database.
|
|
57
67
|
"""
|
|
58
68
|
import ckan.logic
|
|
59
69
|
res_dict = ckan.logic.get_action('resource_show')(
|
|
@@ -69,7 +79,11 @@ def get_s3_bucket_name_for_resource(resource_id):
|
|
|
69
79
|
|
|
70
80
|
|
|
71
81
|
def get_s3_dc_handle(resource_id):
|
|
72
|
-
"""Return an instance of :class:`RTDC_S3`
|
|
82
|
+
"""Return an instance of :class:`RTDC_S3`
|
|
83
|
+
|
|
84
|
+
The resource with the identifier `resource_id` must exist in the
|
|
85
|
+
CKAN database.
|
|
86
|
+
"""
|
|
73
87
|
s3_url = get_s3_url_for_artifact(resource_id)
|
|
74
88
|
ds = fmt_s3.RTDC_S3(
|
|
75
89
|
url=s3_url,
|
|
@@ -88,6 +102,9 @@ def get_s3_url_for_artifact(
|
|
|
88
102
|
|
|
89
103
|
The value of artifact can be either "condensed", "preview", or "resource"
|
|
90
104
|
(those are the keys under which the individual objects are stored in S3).
|
|
105
|
+
|
|
106
|
+
The resource with the identifier `resource_id` must exist in the
|
|
107
|
+
CKAN database.
|
|
91
108
|
"""
|
|
92
109
|
s3_endpoint = get_ckan_config_option("dcor_object_store.endpoint_url")
|
|
93
110
|
bucket_name, object_name = get_s3_bucket_object_for_artifact(
|
|
@@ -97,7 +114,11 @@ def get_s3_url_for_artifact(
|
|
|
97
114
|
|
|
98
115
|
def make_resource_public(resource_id: str,
|
|
99
116
|
missing_ok: bool = True):
|
|
100
|
-
"""Make a resource, including all its artifacts, public
|
|
117
|
+
"""Make a resource, including all its artifacts, public
|
|
118
|
+
|
|
119
|
+
The resource with the identifier `resource_id` must exist in the
|
|
120
|
+
CKAN database.
|
|
121
|
+
"""
|
|
101
122
|
for artifact in ["condensed", "preview", "resource"]:
|
|
102
123
|
bucket_name, object_name = get_s3_bucket_object_for_artifact(
|
|
103
124
|
resource_id=resource_id, artifact=artifact)
|
|
@@ -109,6 +130,11 @@ def make_resource_public(resource_id: str,
|
|
|
109
130
|
def object_exists(
|
|
110
131
|
resource_id: str,
|
|
111
132
|
artifact: Literal["condensed", "preview", "resource"] = "resource"):
|
|
133
|
+
"""Check whether an object is available on S3
|
|
134
|
+
|
|
135
|
+
The resource with the identifier `resource_id` must exist in the
|
|
136
|
+
CKAN database.
|
|
137
|
+
"""
|
|
112
138
|
bucket_name, object_name = get_s3_bucket_object_for_artifact(
|
|
113
139
|
resource_id=resource_id, artifact=artifact)
|
|
114
140
|
return s3.object_exists(bucket_name=bucket_name, object_name=object_name)
|
|
@@ -35,7 +35,7 @@ def create_with_upload_no_temp(clean_db, ckan_config, monkeypatch):
|
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
def make_dataset(create_context, owner_org, create_with_upload=None,
|
|
38
|
-
activate=False, **kwargs):
|
|
38
|
+
resource_path=None, activate=False, **kwargs):
|
|
39
39
|
if "title" not in kwargs:
|
|
40
40
|
kwargs["title"] = "test-dataset"
|
|
41
41
|
if "authors" not in kwargs:
|
|
@@ -52,7 +52,10 @@ def make_dataset(create_context, owner_org, create_with_upload=None,
|
|
|
52
52
|
)
|
|
53
53
|
|
|
54
54
|
if create_with_upload is not None:
|
|
55
|
-
rs = make_resource(
|
|
55
|
+
rs = make_resource(resource_path=resource_path,
|
|
56
|
+
create_with_upload=create_with_upload,
|
|
57
|
+
create_context=create_context,
|
|
58
|
+
dataset_id=ds["id"])
|
|
56
59
|
|
|
57
60
|
if activate:
|
|
58
61
|
helpers.call_action("package_patch", create_context,
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import pathlib
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
import ckan.tests.factories as factories
|
|
5
|
+
|
|
6
|
+
from dcor_shared.testing import make_dataset
|
|
7
|
+
|
|
8
|
+
data_path = pathlib.Path(__file__).parent / "data"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.mark.ckan_config('ckan.plugins', 'dcor_schemas')
|
|
12
|
+
@pytest.mark.usefixtures('clean_db', 'with_request_context')
|
|
13
|
+
def test_make_dataset():
|
|
14
|
+
user = factories.User()
|
|
15
|
+
owner_org = factories.Organization(users=[{
|
|
16
|
+
'name': user['id'],
|
|
17
|
+
'capacity': 'admin'
|
|
18
|
+
}])
|
|
19
|
+
# Note: `call_action` bypasses authorization!
|
|
20
|
+
create_context = {'ignore_auth': False,
|
|
21
|
+
'user': user['name'], 'api_version': 3}
|
|
22
|
+
ds_dict = make_dataset(create_context, owner_org,
|
|
23
|
+
activate=False)
|
|
24
|
+
assert ds_dict["state"] == "draft"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@pytest.mark.ckan_config('ckan.plugins', 'dcor_schemas')
|
|
28
|
+
@pytest.mark.usefixtures('clean_db', 'with_request_context')
|
|
29
|
+
def test_make_dataset_with_resource(create_with_upload):
|
|
30
|
+
user = factories.User()
|
|
31
|
+
owner_org = factories.Organization(users=[{
|
|
32
|
+
'name': user['id'],
|
|
33
|
+
'capacity': 'admin'
|
|
34
|
+
}])
|
|
35
|
+
# Note: `call_action` bypasses authorization!
|
|
36
|
+
create_context = {'ignore_auth': False,
|
|
37
|
+
'user': user['name'], 'api_version': 3}
|
|
38
|
+
# upload a *valid* [sic] .rtdc File (this is the control)
|
|
39
|
+
ds_dict, res_dict = make_dataset(
|
|
40
|
+
create_context, owner_org,
|
|
41
|
+
create_with_upload=create_with_upload,
|
|
42
|
+
resource_path=data_path / "calibration_beads_47.rtdc",
|
|
43
|
+
activate=True)
|
|
44
|
+
assert len(ds_dict["resources"]) == 1
|
|
45
|
+
assert "id" in res_dict
|
|
46
|
+
assert res_dict["package_id"] == ds_dict["id"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|