dcor-shared 0.8.0__tar.gz → 0.9.0__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.8.0 → dcor_shared-0.9.0}/CHANGELOG +4 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/PKG-INFO +1 -1
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/dcor_shared/_version_save.py +1 -1
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/dcor_shared/s3.py +22 -9
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/dcor_shared/s3cc.py +2 -2
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/dcor_shared/testing.py +127 -4
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/dcor_shared.egg-info/PKG-INFO +1 -1
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/dcor_shared.egg-info/requires.txt +1 -1
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/setup.py +1 -1
- dcor_shared-0.9.0/tests/test_testing.py +85 -0
- dcor_shared-0.8.0/tests/test_testing.py +0 -44
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/LICENSE +0 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/MANIFEST.in +0 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/README.rst +0 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/dcor_shared/__init__.py +0 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/dcor_shared/_version.py +0 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/dcor_shared/ckan.py +0 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/dcor_shared/data.py +0 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/dcor_shared/dcinst.py +0 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/dcor_shared/mime.py +0 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/dcor_shared/parse.py +0 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/dcor_shared/paths.py +0 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/dcor_shared.egg-info/SOURCES.txt +0 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/dcor_shared.egg-info/dependency_links.txt +0 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/dcor_shared.egg-info/top_level.txt +0 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/setup.cfg +0 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/tests/test_basic.py +0 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/tests/test_ckan.py +0 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/tests/test_data.py +0 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/tests/test_s3.py +0 -0
- {dcor_shared-0.8.0 → dcor_shared-0.9.0}/tests/test_s3cc.py +0 -0
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
0.9.0
|
|
2
|
+
- feat: introduce `testing.make_dataset_via_s3` and
|
|
3
|
+
`testing.make_resource_via_s3` which uploads resources via S3
|
|
4
|
+
- enh: make sha256 optional in `s3.upload_file`
|
|
1
5
|
0.8.0
|
|
2
6
|
- feat: introduce `get_resource_dc_config`, `get_resource_info`, and
|
|
3
7
|
`s3cc.get_s3_dc_handle_basin_based`
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
"""Basic S3 utility functions"""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
2
4
|
import functools
|
|
3
5
|
import hashlib
|
|
4
6
|
import json
|
|
@@ -10,6 +12,7 @@ import boto3
|
|
|
10
12
|
import botocore.exceptions
|
|
11
13
|
|
|
12
14
|
from .ckan import get_ckan_config_option
|
|
15
|
+
from .data import sha256sum
|
|
13
16
|
|
|
14
17
|
|
|
15
18
|
def compute_checksum(bucket_name, object_name, max_size=None):
|
|
@@ -124,8 +127,11 @@ def create_presigned_upload_url(bucket_name, object_name,
|
|
|
124
127
|
return response["url"], response["fields"]
|
|
125
128
|
|
|
126
129
|
|
|
127
|
-
def create_presigned_url(
|
|
128
|
-
|
|
130
|
+
def create_presigned_url(
|
|
131
|
+
bucket_name: str,
|
|
132
|
+
object_name: str,
|
|
133
|
+
expiration: int = 3600,
|
|
134
|
+
filename: str | None = None):
|
|
129
135
|
"""Generate a presigned URL to share an S3 object
|
|
130
136
|
|
|
131
137
|
Parameters
|
|
@@ -164,8 +170,11 @@ def create_presigned_url(bucket_name, object_name, expiration=3600,
|
|
|
164
170
|
|
|
165
171
|
|
|
166
172
|
@functools.lru_cache()
|
|
167
|
-
def create_presigned_url_until(
|
|
168
|
-
|
|
173
|
+
def create_presigned_url_until(
|
|
174
|
+
bucket_name: str,
|
|
175
|
+
object_name: str,
|
|
176
|
+
expires_at: int,
|
|
177
|
+
filename: str | None = None) -> str:
|
|
169
178
|
"""Cached `create_presigned_url` with expiry time point
|
|
170
179
|
|
|
171
180
|
Parameters
|
|
@@ -182,7 +191,7 @@ def create_presigned_url_until(bucket_name, object_name, expires_at,
|
|
|
182
191
|
|
|
183
192
|
Returns
|
|
184
193
|
-------
|
|
185
|
-
|
|
194
|
+
ps_url: str
|
|
186
195
|
Presigned URL as string.
|
|
187
196
|
"""
|
|
188
197
|
# Generate a presigned URL for the S3 object
|
|
@@ -192,12 +201,12 @@ def create_presigned_url_until(bucket_name, object_name, expires_at,
|
|
|
192
201
|
if filename is not None:
|
|
193
202
|
params["ResponseContentDisposition"] = \
|
|
194
203
|
f"attachment; filename = {filename}"
|
|
195
|
-
|
|
204
|
+
ps_url = s3_client.generate_presigned_url(
|
|
196
205
|
'get_object',
|
|
197
206
|
Params=params,
|
|
198
207
|
ExpiresIn=expires_at - create_time())
|
|
199
208
|
# The response contains the presigned URL
|
|
200
|
-
return
|
|
209
|
+
return ps_url
|
|
201
210
|
|
|
202
211
|
|
|
203
212
|
def create_time():
|
|
@@ -367,7 +376,7 @@ def require_bucket(bucket_name):
|
|
|
367
376
|
return s3_bucket
|
|
368
377
|
|
|
369
378
|
|
|
370
|
-
def upload_file(bucket_name, object_name, path, sha256, private=True,
|
|
379
|
+
def upload_file(bucket_name, object_name, path, sha256=None, private=True,
|
|
371
380
|
override=False):
|
|
372
381
|
"""Upload a file to a bucket
|
|
373
382
|
|
|
@@ -380,7 +389,8 @@ def upload_file(bucket_name, object_name, path, sha256, private=True,
|
|
|
380
389
|
path: str or pathlib.Path
|
|
381
390
|
Local path of the file to be uploaded
|
|
382
391
|
sha256: str
|
|
383
|
-
SHA256 checksum of the file to be uploaded
|
|
392
|
+
SHA256 checksum of the file to be uploaded, will be computed
|
|
393
|
+
if not provided
|
|
384
394
|
private: bool
|
|
385
395
|
Whether the object should remain private. If set to False,
|
|
386
396
|
a tag "public:true" is added to the object which is picket up
|
|
@@ -393,6 +403,9 @@ def upload_file(bucket_name, object_name, path, sha256, private=True,
|
|
|
393
403
|
s3_url: str
|
|
394
404
|
URL to the S3 object
|
|
395
405
|
"""
|
|
406
|
+
if not sha256:
|
|
407
|
+
sha256 = sha256sum(path)
|
|
408
|
+
|
|
396
409
|
path_size = pathlib.Path(path).stat().st_size
|
|
397
410
|
s3_client, _, _ = get_s3()
|
|
398
411
|
s3_bucket = require_bucket(bucket_name)
|
|
@@ -18,7 +18,7 @@ import h5py
|
|
|
18
18
|
from .ckan import (
|
|
19
19
|
get_ckan_config_option, get_resource_dc_config, get_resource_info
|
|
20
20
|
)
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
from . import s3
|
|
23
23
|
|
|
24
24
|
|
|
@@ -246,7 +246,7 @@ def upload_artifact(
|
|
|
246
246
|
bucket_name=bucket_name,
|
|
247
247
|
object_name=f"{artifact}/{rid[:3]}/{rid[3:6]}/{rid[6:]}",
|
|
248
248
|
path=path_artifact,
|
|
249
|
-
sha256=sha256
|
|
249
|
+
sha256=sha256,
|
|
250
250
|
private=private,
|
|
251
251
|
override=override)
|
|
252
252
|
return s3_url
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from io import BytesIO
|
|
4
|
+
import numbers
|
|
5
|
+
import pathlib
|
|
6
|
+
from typing import Dict
|
|
7
|
+
import uuid
|
|
2
8
|
|
|
3
9
|
import ckan.authz
|
|
4
10
|
import ckan.tests.factories as factories
|
|
@@ -9,6 +15,9 @@ from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor
|
|
|
9
15
|
|
|
10
16
|
import pytest
|
|
11
17
|
|
|
18
|
+
from .ckan import get_ckan_config_option
|
|
19
|
+
from . import s3
|
|
20
|
+
|
|
12
21
|
|
|
13
22
|
@pytest.fixture
|
|
14
23
|
def create_with_upload_no_temp(clean_db, ckan_config, monkeypatch):
|
|
@@ -47,7 +56,8 @@ def make_dataset(create_context=None, owner_org=None, create_with_upload=None,
|
|
|
47
56
|
user_id = user["id"]
|
|
48
57
|
else:
|
|
49
58
|
# get user ID from create_context
|
|
50
|
-
user_id = ckan.authz.get_user_id_for_username(
|
|
59
|
+
user_id = ckan.authz.get_user_id_for_username(
|
|
60
|
+
create_context["user"], allow_none=True)
|
|
51
61
|
|
|
52
62
|
if owner_org is None:
|
|
53
63
|
owner_org = factories.Organization(users=[{
|
|
@@ -77,9 +87,11 @@ def make_dataset(create_context=None, owner_org=None, create_with_upload=None,
|
|
|
77
87
|
dataset_id=ds["id"])
|
|
78
88
|
|
|
79
89
|
if activate:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
90
|
+
revise_dict = {
|
|
91
|
+
"match": {"id": ds["id"]},
|
|
92
|
+
"update": {"state": "active"}
|
|
93
|
+
}
|
|
94
|
+
helpers.call_action("package_revise", create_context, **revise_dict)
|
|
83
95
|
|
|
84
96
|
ds_dict = helpers.call_action("package_show", id=ds["id"])
|
|
85
97
|
|
|
@@ -91,6 +103,90 @@ def make_dataset(create_context=None, owner_org=None, create_with_upload=None,
|
|
|
91
103
|
return ds_dict
|
|
92
104
|
|
|
93
105
|
|
|
106
|
+
def make_dataset_via_s3(
|
|
107
|
+
create_context: Dict | None = None,
|
|
108
|
+
owner_org: Dict | None = None,
|
|
109
|
+
resource_path: str | pathlib.Path | None = None,
|
|
110
|
+
activate: bool = False,
|
|
111
|
+
**kwargs: str | numbers.Number):
|
|
112
|
+
"""Create a dataset and upload the given resource directly via S3
|
|
113
|
+
|
|
114
|
+
For this action to work, the "ckanext-dcor_schemas" extension
|
|
115
|
+
must be loaded.
|
|
116
|
+
|
|
117
|
+
Parameters
|
|
118
|
+
----------
|
|
119
|
+
create_context: dict
|
|
120
|
+
CKAN context for creating the dataset
|
|
121
|
+
owner_org: dict
|
|
122
|
+
CKAN dictionary of the owner organization
|
|
123
|
+
resource_path: str or pathlib.Path
|
|
124
|
+
path to the resource file to upload. If not specified, then
|
|
125
|
+
not resource is created for the dataset
|
|
126
|
+
activate: bool
|
|
127
|
+
whether to activate the dataset
|
|
128
|
+
kwargs: dict
|
|
129
|
+
keyword arguments passed to `package_create`
|
|
130
|
+
"""
|
|
131
|
+
if create_context is None:
|
|
132
|
+
user = factories.User()
|
|
133
|
+
create_context = {'ignore_auth': False,
|
|
134
|
+
'user': user['name'],
|
|
135
|
+
'api_version': 3}
|
|
136
|
+
user_id = user["id"]
|
|
137
|
+
else:
|
|
138
|
+
# get user ID from create_context
|
|
139
|
+
user_id = ckan.authz.get_user_id_for_username(
|
|
140
|
+
create_context["user"], allow_none=True)
|
|
141
|
+
|
|
142
|
+
if owner_org is None:
|
|
143
|
+
owner_org = factories.Organization(users=[{
|
|
144
|
+
'name': user_id,
|
|
145
|
+
'capacity': 'admin'
|
|
146
|
+
}])
|
|
147
|
+
|
|
148
|
+
if "title" not in kwargs:
|
|
149
|
+
kwargs["title"] = "test-dataset-S3"
|
|
150
|
+
if "authors" not in kwargs:
|
|
151
|
+
kwargs["authors"] = "Peter Fly Pan"
|
|
152
|
+
if "license_id" not in kwargs:
|
|
153
|
+
kwargs["license_id"] = "CC-BY-4.0"
|
|
154
|
+
assert "state" not in kwargs, "must not be set"
|
|
155
|
+
assert "owner_org" not in kwargs, "must not be set"
|
|
156
|
+
# create a dataset
|
|
157
|
+
ds_dict = helpers.call_action("package_create", create_context,
|
|
158
|
+
owner_org=owner_org["name"],
|
|
159
|
+
state="draft",
|
|
160
|
+
**kwargs
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
if resource_path is not None:
|
|
164
|
+
rid = make_resource_via_s3(resource_path=resource_path,
|
|
165
|
+
organization_id=owner_org["id"],
|
|
166
|
+
dataset_id=ds_dict["id"],
|
|
167
|
+
create_context=create_context,
|
|
168
|
+
private=ds_dict.get("private", False)
|
|
169
|
+
)
|
|
170
|
+
else:
|
|
171
|
+
rid = None
|
|
172
|
+
|
|
173
|
+
if activate:
|
|
174
|
+
revise_dict = {
|
|
175
|
+
"match": {"id": ds_dict["id"]},
|
|
176
|
+
"update": {"state": "active"}
|
|
177
|
+
}
|
|
178
|
+
helpers.call_action("package_revise", create_context, **revise_dict)
|
|
179
|
+
|
|
180
|
+
ds_dict = helpers.call_action("package_show", id=ds_dict["id"])
|
|
181
|
+
|
|
182
|
+
if rid is not None:
|
|
183
|
+
# fetch resource dictionary
|
|
184
|
+
rs_dict = helpers.call_action("resource_show", id=rid)
|
|
185
|
+
return ds_dict, rs_dict
|
|
186
|
+
else:
|
|
187
|
+
return ds_dict
|
|
188
|
+
|
|
189
|
+
|
|
94
190
|
def make_resource(resource_path, create_with_upload, create_context,
|
|
95
191
|
dataset_id):
|
|
96
192
|
content = resource_path.read_bytes()
|
|
@@ -105,6 +201,33 @@ def make_resource(resource_path, create_with_upload, create_context,
|
|
|
105
201
|
return resource
|
|
106
202
|
|
|
107
203
|
|
|
204
|
+
def make_resource_via_s3(resource_path, organization_id, dataset_id,
|
|
205
|
+
create_context, private=False):
|
|
206
|
+
"""Upload a resource to S3 and register it with CKAN"""
|
|
207
|
+
bucket_name = get_ckan_config_option(
|
|
208
|
+
"dcor_object_store.bucket_name").format(
|
|
209
|
+
organization_id=organization_id)
|
|
210
|
+
rid = str(uuid.uuid4())
|
|
211
|
+
object_name = f"resource/{rid[:3]}/{rid[3:6]}/{rid[6:]}"
|
|
212
|
+
|
|
213
|
+
s3.upload_file(bucket_name=bucket_name,
|
|
214
|
+
object_name=object_name,
|
|
215
|
+
path=resource_path,
|
|
216
|
+
private=private)
|
|
217
|
+
|
|
218
|
+
revise_dict = {
|
|
219
|
+
"match": {"id": dataset_id},
|
|
220
|
+
"update": {"resources": [{"id": rid,
|
|
221
|
+
"name": resource_path.name,
|
|
222
|
+
"s3_available": True,
|
|
223
|
+
}
|
|
224
|
+
]
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
helpers.call_action("package_revise", create_context, **revise_dict)
|
|
228
|
+
return rid
|
|
229
|
+
|
|
230
|
+
|
|
108
231
|
def synchronous_enqueue_job(job_func, args=None, kwargs=None, title=None,
|
|
109
232
|
queue=None, rq_kwargs=None):
|
|
110
233
|
"""
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import pathlib
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
import ckan.tests.factories as factories
|
|
5
|
+
import requests
|
|
6
|
+
|
|
7
|
+
from dcor_shared.testing import make_dataset, make_dataset_via_s3
|
|
8
|
+
from dcor_shared import s3cc, sha256sum
|
|
9
|
+
|
|
10
|
+
data_path = pathlib.Path(__file__).parent / "data"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.mark.ckan_config('ckan.plugins', 'dcor_schemas')
|
|
14
|
+
@pytest.mark.usefixtures('clean_db', 'with_request_context')
|
|
15
|
+
def test_make_dataset():
|
|
16
|
+
user = factories.User()
|
|
17
|
+
owner_org = factories.Organization(users=[{
|
|
18
|
+
'name': user['id'],
|
|
19
|
+
'capacity': 'admin'
|
|
20
|
+
}])
|
|
21
|
+
# Note: `call_action` bypasses authorization!
|
|
22
|
+
create_context = {'ignore_auth': False,
|
|
23
|
+
'user': user['name'], 'api_version': 3}
|
|
24
|
+
ds_dict = make_dataset(create_context, owner_org,
|
|
25
|
+
activate=False)
|
|
26
|
+
assert ds_dict["state"] == "draft"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@pytest.mark.ckan_config('ckan.plugins', 'dcor_schemas')
|
|
30
|
+
@pytest.mark.usefixtures('clean_db', 'with_request_context')
|
|
31
|
+
def test_make_dataset_no_user_specified():
|
|
32
|
+
ds_dict = make_dataset(activate=False)
|
|
33
|
+
assert ds_dict["state"] == "draft"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@pytest.mark.ckan_config('ckan.plugins', 'dcor_schemas')
|
|
37
|
+
@pytest.mark.usefixtures('clean_db', 'with_request_context')
|
|
38
|
+
def test_make_dataset_with_resource(create_with_upload):
|
|
39
|
+
# upload a *valid* [sic] .rtdc File (this is the control)
|
|
40
|
+
ds_dict, res_dict = make_dataset(
|
|
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"]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@pytest.mark.ckan_config('ckan.plugins', 'dcor_schemas')
|
|
50
|
+
@pytest.mark.usefixtures('clean_db', 'with_request_context')
|
|
51
|
+
def test_make_dataset_via_s3():
|
|
52
|
+
user = factories.User()
|
|
53
|
+
owner_org = factories.Organization(users=[{
|
|
54
|
+
'name': user['id'],
|
|
55
|
+
'capacity': 'admin'
|
|
56
|
+
}])
|
|
57
|
+
# Note: `call_action` bypasses authorization!
|
|
58
|
+
create_context = {'ignore_auth': False,
|
|
59
|
+
'user': user['name'], 'api_version': 3}
|
|
60
|
+
ds_dict = make_dataset_via_s3(create_context, owner_org, activate=False)
|
|
61
|
+
assert ds_dict["state"] == "draft"
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@pytest.mark.ckan_config('ckan.plugins', 'dcor_schemas')
|
|
65
|
+
@pytest.mark.usefixtures('clean_db', 'with_request_context')
|
|
66
|
+
def test_make_dataset_with_resource_via_s3(tmp_path):
|
|
67
|
+
# upload a *valid* [sic] .rtdc File (this is the control)
|
|
68
|
+
ds_dict, res_dict = make_dataset_via_s3(
|
|
69
|
+
resource_path=data_path / "calibration_beads_47.rtdc",
|
|
70
|
+
activate=True,
|
|
71
|
+
private=False,
|
|
72
|
+
)
|
|
73
|
+
assert len(ds_dict["resources"]) == 1
|
|
74
|
+
assert "id" in res_dict
|
|
75
|
+
assert res_dict["package_id"] == ds_dict["id"]
|
|
76
|
+
|
|
77
|
+
# verify SHA256 sum of the resource
|
|
78
|
+
ps_url = s3cc.get_s3_url_for_artifact(res_dict["id"], artifact="resource")
|
|
79
|
+
response = requests.get(ps_url)
|
|
80
|
+
dl_path = tmp_path / "calbeads.rtdc"
|
|
81
|
+
with dl_path.open("wb") as fd:
|
|
82
|
+
fd.write(response.content)
|
|
83
|
+
|
|
84
|
+
assert sha256sum(dl_path) == \
|
|
85
|
+
"490efdf5d9bb4cd4b2a6bcf2fe54d4dc201c38530140bcb168980bf8bf846c73"
|
|
@@ -1,44 +0,0 @@
|
|
|
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_no_user_specified():
|
|
30
|
-
ds_dict = make_dataset(activate=False)
|
|
31
|
-
assert ds_dict["state"] == "draft"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
@pytest.mark.ckan_config('ckan.plugins', 'dcor_schemas')
|
|
35
|
-
@pytest.mark.usefixtures('clean_db', 'with_request_context')
|
|
36
|
-
def test_make_dataset_with_resource(create_with_upload):
|
|
37
|
-
# upload a *valid* [sic] .rtdc File (this is the control)
|
|
38
|
-
ds_dict, res_dict = make_dataset(
|
|
39
|
-
create_with_upload=create_with_upload,
|
|
40
|
-
resource_path=data_path / "calibration_beads_47.rtdc",
|
|
41
|
-
activate=True)
|
|
42
|
-
assert len(ds_dict["resources"]) == 1
|
|
43
|
-
assert "id" in res_dict
|
|
44
|
-
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
|
|
File without changes
|