dcor-shared 0.7.2__tar.gz → 0.7.4__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.
Files changed (30) hide show
  1. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/CHANGELOG +5 -0
  2. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/PKG-INFO +1 -1
  3. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/dcor_shared/__init__.py +1 -0
  4. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/dcor_shared/_version_save.py +1 -1
  5. dcor_shared-0.7.4/dcor_shared/dcinst.py +20 -0
  6. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/dcor_shared/s3cc.py +75 -3
  7. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/dcor_shared.egg-info/PKG-INFO +1 -1
  8. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/dcor_shared.egg-info/SOURCES.txt +1 -0
  9. dcor_shared-0.7.4/tests/test_data.py +183 -0
  10. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/tests/test_s3cc.py +51 -10
  11. dcor_shared-0.7.2/tests/test_data.py +0 -68
  12. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/LICENSE +0 -0
  13. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/MANIFEST.in +0 -0
  14. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/README.rst +0 -0
  15. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/dcor_shared/_version.py +0 -0
  16. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/dcor_shared/ckan.py +0 -0
  17. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/dcor_shared/data.py +0 -0
  18. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/dcor_shared/mime.py +0 -0
  19. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/dcor_shared/parse.py +0 -0
  20. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/dcor_shared/paths.py +0 -0
  21. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/dcor_shared/s3.py +0 -0
  22. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/dcor_shared/testing.py +0 -0
  23. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/dcor_shared.egg-info/dependency_links.txt +0 -0
  24. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/dcor_shared.egg-info/requires.txt +0 -0
  25. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/dcor_shared.egg-info/top_level.txt +0 -0
  26. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/setup.cfg +0 -0
  27. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/setup.py +0 -0
  28. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/tests/test_basic.py +0 -0
  29. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/tests/test_s3.py +0 -0
  30. {dcor_shared-0.7.2 → dcor_shared-0.7.4}/tests/test_testing.py +0 -0
@@ -1,3 +1,8 @@
1
+ 0.7.4
2
+ - fix: disable basins when loading a dataset instance
3
+ - enh: implement s3cc.upload_artifact
4
+ 0.7.3
5
+ - enh: add get_dc_instance convenience method
1
6
  0.7.2
2
7
  - tests: fix invalid make_dataset method
3
8
  0.7.1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dcor_shared
3
- Version: 0.7.2
3
+ Version: 0.7.4
4
4
  Summary: Functionalities shared by the DCOR CKAN extensions
5
5
  Home-page: https://github.com/DCOR-dev/dcor_shared
6
6
  Author: Paul Müller
@@ -1,6 +1,7 @@
1
1
  # flake8: noqa: F401
2
2
  from .ckan import get_ckan_config_option, get_resource_path
3
3
  from .data import DUMMY_BYTES, sha256sum, wait_for_resource
4
+ from .dcinst import get_dc_instance
4
5
  from .mime import DC_MIME_TYPES, VALID_FORMATS
5
6
  from . import paths
6
7
  from ._version import version as __version__
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env python
2
2
  # This file was created automatically
3
- longversion = '0.7.2'
3
+ longversion = '0.7.4'
@@ -0,0 +1,20 @@
1
+ from dclab.rtdc_dataset import RTDC_HDF5
2
+
3
+ from .ckan import get_resource_path
4
+ from . import s3cc
5
+
6
+
7
+ def get_dc_instance(rid):
8
+ """Return an instance of dclab's `RTDCBase` for a resource identifier"""
9
+ # Try local file first
10
+ path = get_resource_path(rid)
11
+ if path.is_file():
12
+ # Disable basins, because they could point to files on the local
13
+ # file system (security).
14
+ return RTDC_HDF5(path, enable_basins=False)
15
+ else:
16
+ # The resource must be on S3
17
+ if s3cc.artifact_exists(rid):
18
+ return s3cc.get_s3_dc_handle(rid)
19
+ else:
20
+ raise ValueError(f"Could not find resource {rid} anywhere")
@@ -3,16 +3,32 @@
3
3
  Contains methods to directly interact with CKAN resources that are on S3
4
4
  via just the resource ID.
5
5
  """
6
+ from __future__ import annotations
6
7
  import functools
7
-
8
+ import pathlib
8
9
  from typing import Literal
10
+ import warnings
9
11
 
10
12
  from dclab.rtdc_dataset import fmt_s3
11
13
 
12
14
  from .ckan import get_ckan_config_option
15
+ from .data import sha256sum
13
16
  from . import s3
14
17
 
15
18
 
19
+ def artifact_exists(
20
+ resource_id: str,
21
+ artifact: Literal["condensed", "preview", "resource"] = "resource"):
22
+ """Check whether an artifact is available on S3
23
+
24
+ The resource with the identifier `resource_id` must exist in the
25
+ CKAN database.
26
+ """
27
+ bucket_name, object_name = get_s3_bucket_object_for_artifact(
28
+ resource_id=resource_id, artifact=artifact)
29
+ return s3.object_exists(bucket_name=bucket_name, object_name=object_name)
30
+
31
+
16
32
  def compute_checksum(resource_id):
17
33
  """Compute the SHA256 checksum of the corresponding CKAN resource"""
18
34
  bucket_name, object_name = get_s3_bucket_object_for_artifact(
@@ -91,6 +107,9 @@ def get_s3_dc_handle(resource_id):
91
107
  "dcor_object_store.access_key_id"),
92
108
  secret_key=get_ckan_config_option(
93
109
  "dcor_object_store.secret_access_key"),
110
+ # Disable basins, because they could point to files on the
111
+ # local file system (security).
112
+ enable_basins=False,
94
113
  )
95
114
  return ds
96
115
 
@@ -130,11 +149,64 @@ def make_resource_public(resource_id: str,
130
149
  def object_exists(
131
150
  resource_id: str,
132
151
  artifact: Literal["condensed", "preview", "resource"] = "resource"):
133
- """Check whether an object is available on S3
152
+ """Check whether an artifact is available on S3
134
153
 
135
154
  The resource with the identifier `resource_id` must exist in the
136
155
  CKAN database.
137
156
  """
157
+ warnings.warn("`s3cc.object_exists` is deprecated, please use"
158
+ "`s3cc.artifact_exists` instead",
159
+ DeprecationWarning)
160
+ return artifact_exists(resource_id, artifact)
161
+
162
+
163
+ def upload_artifact(
164
+ resource_id: str,
165
+ path_artifact: str | pathlib.Path,
166
+ artifact: Literal["condensed", "preview", "resource"] = "resource",
167
+ sha256: str = None,
168
+ private: bool = None,
169
+ override: bool = False
170
+ ):
171
+ """Upload an artifact to S3
172
+
173
+ Parameters
174
+ ----------
175
+ resource_id: str
176
+ The resource identifier for the artifact
177
+ path_artifact: pathlib.Path
178
+ The path to the artifact file
179
+ artifact: str
180
+ The artifact type that the file represents
181
+ sha256: str
182
+ The SHA256 sum of `path_artifcat`, will be computed if not provided
183
+ private: bool
184
+ Whether the dataset that the resource belongs to is private.
185
+ Leave this blank if you don't know and we will do a database
186
+ look-up to determine the correct value.
187
+ override: bool
188
+ Whether to override a possibly existing object on S3.
189
+ """
138
190
  bucket_name, object_name = get_s3_bucket_object_for_artifact(
139
191
  resource_id=resource_id, artifact=artifact)
140
- return s3.object_exists(bucket_name=bucket_name, object_name=object_name)
192
+
193
+ if private is None:
194
+ # User did not say whether the resource is private. We have to
195
+ # find out ourselves.
196
+ import ckan.logic
197
+ res_dict = ckan.logic.get_action('resource_show')(
198
+ context={'ignore_auth': True, 'user': 'default'},
199
+ data_dict={"id": resource_id})
200
+ ds_dict = ckan.logic.get_action('package_show')(
201
+ context={'ignore_auth': True, 'user': 'default'},
202
+ data_dict={'id': res_dict["package_id"]})
203
+ private = ds_dict["private"]
204
+
205
+ rid = resource_id
206
+ s3.upload_file(
207
+ bucket_name=bucket_name,
208
+ object_name=f"{artifact}/{rid[:3]}/{rid[3:6]}/{rid[6:]}",
209
+ path=path_artifact,
210
+ sha256=sha256 or sha256sum(path_artifact),
211
+ private=private,
212
+ override=override)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dcor-shared
3
- Version: 0.7.2
3
+ Version: 0.7.4
4
4
  Summary: Functionalities shared by the DCOR CKAN extensions
5
5
  Home-page: https://github.com/DCOR-dev/dcor_shared
6
6
  Author: Paul Müller
@@ -9,6 +9,7 @@ dcor_shared/_version.py
9
9
  dcor_shared/_version_save.py
10
10
  dcor_shared/ckan.py
11
11
  dcor_shared/data.py
12
+ dcor_shared/dcinst.py
12
13
  dcor_shared/mime.py
13
14
  dcor_shared/parse.py
14
15
  dcor_shared/paths.py
@@ -0,0 +1,183 @@
1
+ import atexit
2
+ import pathlib
3
+ import shutil
4
+ from unittest import mock
5
+ import uuid
6
+
7
+ from ckan import logic
8
+ import ckanext.dcor_schemas.plugin
9
+
10
+ from dcor_shared import (
11
+ get_dc_instance, get_resource_path, s3, sha256sum, wait_for_resource
12
+ )
13
+
14
+ import pytest
15
+ import ckan.tests.factories as factories
16
+ from dcor_shared.testing import make_dataset, synchronous_enqueue_job
17
+
18
+ data_path = pathlib.Path(__file__).parent / "data"
19
+
20
+
21
+ @pytest.mark.ckan_config('ckan.plugins', 'dcor_depot dcor_schemas')
22
+ @pytest.mark.usefixtures('clean_db', 'with_request_context')
23
+ @mock.patch('ckan.plugins.toolkit.enqueue_job',
24
+ side_effect=synchronous_enqueue_job)
25
+ def test_get_dc_instance_file(enqueue_job_mock, create_with_upload,
26
+ monkeypatch):
27
+ monkeypatch.setattr(
28
+ ckanext.dcor_schemas.plugin,
29
+ 'DISABLE_AFTER_DATASET_CREATE_FOR_CONCURRENT_JOB_TESTS',
30
+ True)
31
+
32
+ user = factories.User()
33
+ owner_org = factories.Organization(users=[{
34
+ 'name': user['id'],
35
+ 'capacity': 'admin'
36
+ }])
37
+ create_context = {'ignore_auth': False,
38
+ 'user': user['name'],
39
+ 'api_version': 3}
40
+ ds_dict, _ = make_dataset(
41
+ create_context, owner_org,
42
+ create_with_upload=create_with_upload,
43
+ resource_path=data_path / "calibration_beads_47.rtdc",
44
+ activate=True)
45
+ rid = ds_dict["resources"][0]["id"]
46
+ resource_path = pathlib.Path(get_resource_path(rid))
47
+ assert resource_path.exists(), "sanity check"
48
+ with get_dc_instance(rid) as ds:
49
+ assert str(ds.path) == str(resource_path)
50
+
51
+
52
+ @pytest.mark.ckan_config('ckan.storage_path',
53
+ '/tmp/test_dcor_shared/test_get_dc_instance')
54
+ def test_get_dc_instance_file_fails_without_actual_resource():
55
+ tmp_path = pathlib.Path("/tmp/test_dcor_shared/test_get_dc_instance")
56
+ atexit.register(shutil.rmtree,
57
+ tmp_path,
58
+ ignore_errors=True)
59
+ rid = str(uuid.uuid4())
60
+ resource_path = tmp_path / rid[:3] / rid[3:6] / rid[6:]
61
+ resource_path.parent.mkdir(parents=True)
62
+ shutil.copy2(data_path / "calibration_beads_47.rtdc", resource_path)
63
+ with pytest.raises(logic.NotFound):
64
+ get_dc_instance(rid)
65
+
66
+
67
+ @pytest.mark.ckan_config('ckan.plugins', 'dcor_depot dcor_schemas')
68
+ @pytest.mark.usefixtures('clean_db', 'with_request_context')
69
+ @mock.patch('ckan.plugins.toolkit.enqueue_job',
70
+ side_effect=synchronous_enqueue_job)
71
+ def test_get_dc_instance_s3(enqueue_job_mock, create_with_upload,
72
+ monkeypatch):
73
+ monkeypatch.setattr(
74
+ ckanext.dcor_schemas.plugin,
75
+ 'DISABLE_AFTER_DATASET_CREATE_FOR_CONCURRENT_JOB_TESTS',
76
+ True)
77
+
78
+ user = factories.User()
79
+ owner_org = factories.Organization(users=[{
80
+ 'name': user['id'],
81
+ 'capacity': 'admin'
82
+ }])
83
+ create_context = {'ignore_auth': False,
84
+ 'user': user['name'],
85
+ 'api_version': 3}
86
+ ds_dict, _ = make_dataset(
87
+ create_context, owner_org,
88
+ create_with_upload=create_with_upload,
89
+ resource_path=data_path / "calibration_beads_47.rtdc",
90
+ activate=True)
91
+ res_dict = ds_dict["resources"][0]
92
+ rid = res_dict["id"]
93
+ resource_path = pathlib.Path(get_resource_path(rid))
94
+ # remove the file, so DCOR falls back to the S3 resource
95
+ resource_path.unlink()
96
+ assert not resource_path.exists(), "sanity check"
97
+ with get_dc_instance(rid) as ds:
98
+ assert ds.path.startswith("http")
99
+ assert res_dict["s3_available"]
100
+ assert res_dict["s3_url"] == ds.path
101
+
102
+
103
+ @pytest.mark.ckan_config('ckan.plugins', 'dcor_depot dcor_schemas')
104
+ @pytest.mark.usefixtures('clean_db', 'with_request_context')
105
+ @mock.patch('ckan.plugins.toolkit.enqueue_job',
106
+ side_effect=synchronous_enqueue_job)
107
+ def test_get_dc_instance_s3_fails_without_actual_resource(enqueue_job_mock):
108
+ user = factories.User()
109
+ owner_org = factories.Organization(users=[{
110
+ 'name': user['id'],
111
+ 'capacity': 'admin'
112
+ }])
113
+ rid = str(uuid.uuid4())
114
+ bucket_name = f"circle-{owner_org['id']}"
115
+ object_name = f"resource/{rid[:3]}/{rid[3:6]}/{rid[6:]}"
116
+ upload_path = data_path / "calibration_beads_47.rtdc"
117
+ s3.upload_file(bucket_name=bucket_name,
118
+ object_name=object_name,
119
+ path=upload_path,
120
+ sha256=sha256sum(upload_path)
121
+ )
122
+ with pytest.raises(logic.NotFound):
123
+ get_dc_instance(rid)
124
+
125
+
126
+ def test_sha256sum(tmp_path):
127
+ p = tmp_path / "test.txt"
128
+ p.write_text("Sum this up!")
129
+ ist = sha256sum(p)
130
+ soll = "d00df55b97a60c78bbb137540e1b60647a5e6b216262a95ab96cafd4519bcf6a"
131
+ assert ist == soll
132
+
133
+
134
+ def test_wait_for_resource_s3(monkeypatch):
135
+ res_id = str(uuid.uuid4())
136
+ monkeypatch.setattr(logic, "get_action",
137
+ lambda x: lambda context, data_dict: {
138
+ "id": res_id,
139
+ "s3_available": True})
140
+ # Should not raise an exception
141
+ wait_for_resource(res_id)
142
+
143
+
144
+ @pytest.mark.ckan_config('ckan.plugins', '') # disable plugins
145
+ def test_wait_for_resource_no_s3_url_no_plugins(monkeypatch):
146
+ res_id = str(uuid.uuid4())
147
+ monkeypatch.setattr(logic, "get_action",
148
+ lambda x: lambda context, data_dict: {
149
+ "id": res_id})
150
+ # Create the actual path
151
+ rp = pathlib.Path(get_resource_path(res_id))
152
+ rp.parent.mkdir(parents=True, exist_ok=True)
153
+ rp.write_bytes(b"This is not a dummy file, but a fake DC file!")
154
+ # Should not raise an exception
155
+ wait_for_resource(res_id)
156
+
157
+
158
+ @pytest.mark.ckan_config('ckan.plugins', 'dcor_depot')
159
+ def test_wait_for_resource_no_s3_url_with_dcor_depot_plugin(monkeypatch):
160
+ res_id = str(uuid.uuid4())
161
+ monkeypatch.setattr(logic, "get_action",
162
+ lambda x: lambda context, data_dict: {
163
+ "id": res_id})
164
+ # Create the actual path
165
+ rp = pathlib.Path(get_resource_path(res_id))
166
+ rp.parent.mkdir(parents=True, exist_ok=True)
167
+ rp.write_bytes(b"This is not a dummy file, but a fake DC file!")
168
+ rp2 = rp.with_name("test.rtdc")
169
+ rp.rename(rp2)
170
+ rp.symlink_to(rp2)
171
+
172
+ # Should not raise an exception
173
+ wait_for_resource(res_id)
174
+
175
+
176
+ def test_wait_resource_not_available(monkeypatch):
177
+ res_id = str(uuid.uuid4())
178
+ monkeypatch.setattr(logic, "get_action",
179
+ lambda x: lambda context, data_dict: {
180
+ "id": res_id})
181
+ # Should raise an exception
182
+ with pytest.raises(OSError, match="Data import seems to take too long"):
183
+ wait_for_resource(res_id, timeout=1)
@@ -16,6 +16,23 @@ import requests
16
16
  data_path = pathlib.Path(__file__).parent / "data"
17
17
 
18
18
 
19
+ @pytest.mark.ckan_config('ckan.plugins', 'dcor_schemas')
20
+ @pytest.mark.usefixtures('clean_db', 'with_request_context')
21
+ @mock.patch('ckan.plugins.toolkit.enqueue_job',
22
+ side_effect=synchronous_enqueue_job)
23
+ def test_artifact_exists(enqueue_job_mock):
24
+ rid, s3_url, _, org_dict = setup_s3_resource_on_ckan(private=True)
25
+ assert s3cc.artifact_exists(rid)
26
+ # Delete the object
27
+ s3_client, _, _ = s3.get_s3()
28
+ bucket_name, object_name = s3cc.get_s3_bucket_object_for_artifact(rid)
29
+ s3_client.delete_object(
30
+ Bucket=bucket_name,
31
+ Key=object_name
32
+ )
33
+ assert not s3cc.artifact_exists(rid)
34
+
35
+
19
36
  def setup_s3_resource_on_ckan(private=False):
20
37
  """Create an S3 resource in CKAN"""
21
38
  user = factories.User()
@@ -151,14 +168,38 @@ def test_make_resource_public(enqueue_job_mock):
151
168
  @pytest.mark.usefixtures('clean_db', 'with_request_context')
152
169
  @mock.patch('ckan.plugins.toolkit.enqueue_job',
153
170
  side_effect=synchronous_enqueue_job)
154
- def test_object_exists(enqueue_job_mock):
171
+ def test_upload_artifact(enqueue_job_mock, tmp_path):
155
172
  rid, s3_url, _, org_dict = setup_s3_resource_on_ckan(private=True)
156
- assert s3cc.object_exists(rid)
157
- # Delete the object
158
- s3_client, _, _ = s3.get_s3()
159
- bucket_name, object_name = s3cc.get_s3_bucket_object_for_artifact(rid)
160
- s3_client.delete_object(
161
- Bucket=bucket_name,
162
- Key=object_name
163
- )
164
- assert not s3cc.object_exists(rid)
173
+ path_fake_preview = tmp_path / "test_preview.jpg"
174
+ path_fake_preview.write_text("This is not a real image!")
175
+ # upload the preview
176
+ s3cc.upload_artifact(rid,
177
+ path_artifact=path_fake_preview,
178
+ artifact="preview")
179
+ # make sure that worked
180
+ assert s3cc.artifact_exists(rid, "preview")
181
+ # attempt to download the private artifact
182
+ resp1 = requests.get(s3_url.replace("resource", "preview"))
183
+ assert not resp1.ok, "sanity check"
184
+
185
+
186
+ @pytest.mark.ckan_config('ckan.plugins', 'dcor_schemas')
187
+ @pytest.mark.usefixtures('clean_db', 'with_request_context')
188
+ @mock.patch('ckan.plugins.toolkit.enqueue_job',
189
+ side_effect=synchronous_enqueue_job)
190
+ def test_upload_artifact_public(enqueue_job_mock, tmp_path):
191
+ rid, s3_url, _, org_dict = setup_s3_resource_on_ckan(private=True)
192
+ path_fake_preview = tmp_path / "test_preview.jpg"
193
+ path_fake_preview.write_text("This is not a real image!")
194
+ # upload the preview
195
+ s3cc.upload_artifact(rid,
196
+ path_artifact=path_fake_preview,
197
+ artifact="preview",
198
+ # force public resource even though dataset is not
199
+ # (this has no real-life use case)
200
+ private=False)
201
+ # make sure that worked
202
+ assert s3cc.artifact_exists(rid, "preview")
203
+ # attempt to download the private artifact
204
+ resp1 = requests.get(s3_url.replace("resource", "preview"))
205
+ assert resp1.ok, "preview should be public"
@@ -1,68 +0,0 @@
1
- import pathlib
2
- import uuid
3
-
4
- from ckan import logic
5
-
6
- import pytest
7
-
8
- from dcor_shared import get_resource_path, sha256sum, wait_for_resource
9
-
10
-
11
- def test_sha256sum(tmp_path):
12
- p = tmp_path / "test.txt"
13
- p.write_text("Sum this up!")
14
- ist = sha256sum(p)
15
- soll = "d00df55b97a60c78bbb137540e1b60647a5e6b216262a95ab96cafd4519bcf6a"
16
- assert ist == soll
17
-
18
-
19
- def test_wait_for_resource_s3(monkeypatch):
20
- res_id = str(uuid.uuid4())
21
- monkeypatch.setattr(logic, "get_action",
22
- lambda x: lambda context, data_dict: {
23
- "id": res_id,
24
- "s3_available": True})
25
- # Should not raise an exception
26
- wait_for_resource(res_id)
27
-
28
-
29
- @pytest.mark.ckan_config('ckan.plugins', '') # disable plugins
30
- def test_wait_for_resource_no_s3_url_no_plugins(monkeypatch):
31
- res_id = str(uuid.uuid4())
32
- monkeypatch.setattr(logic, "get_action",
33
- lambda x: lambda context, data_dict: {
34
- "id": res_id})
35
- # Create the actual path
36
- rp = pathlib.Path(get_resource_path(res_id))
37
- rp.parent.mkdir(parents=True, exist_ok=True)
38
- rp.write_bytes(b"This is not a dummy file, but a fake DC file!")
39
- # Should not raise an exception
40
- wait_for_resource(res_id)
41
-
42
-
43
- @pytest.mark.ckan_config('ckan.plugins', 'dcor_depot')
44
- def test_wait_for_resource_no_s3_url_with_dcor_depot_plugin(monkeypatch):
45
- res_id = str(uuid.uuid4())
46
- monkeypatch.setattr(logic, "get_action",
47
- lambda x: lambda context, data_dict: {
48
- "id": res_id})
49
- # Create the actual path
50
- rp = pathlib.Path(get_resource_path(res_id))
51
- rp.parent.mkdir(parents=True, exist_ok=True)
52
- rp.write_bytes(b"This is not a dummy file, but a fake DC file!")
53
- rp2 = rp.with_name("test.rtdc")
54
- rp.rename(rp2)
55
- rp.symlink_to(rp2)
56
-
57
- # Should not raise an exception
58
- wait_for_resource(res_id)
59
-
60
-
61
- def test_wait_resource_not_available(monkeypatch):
62
- res_id = str(uuid.uuid4())
63
- monkeypatch.setattr(logic, "get_action",
64
- lambda x: lambda context, data_dict: {
65
- "id": res_id})
66
- # Should raise an exception
67
- with pytest.raises(OSError, match="Data import seems to take too long"):
68
- wait_for_resource(res_id, timeout=1)
File without changes
File without changes
File without changes
File without changes
File without changes