pyicat-plus 2.2.0__tar.gz → 2.3.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.
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/PKG-INFO +6 -10
- pyicat_plus-2.3.0/README.md +10 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/pyproject.toml +29 -14
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/_icat_messaging/deserializers/xml.py +1 -1
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/apps/store_processed.py +3 -2
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/apps/store_raw.py +6 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/client/defaults.py +1 -1
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/client/icatplus_restricted.py +40 -12
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/client/interface.py +34 -5
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/client/main.py +16 -2
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/client/messaging.py +2 -2
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/client/null.py +3 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/client/types.py +10 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/metadata/definitions.py +2 -3
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/conftest.py +0 -1
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/test_icat_investigations.py +1 -1
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/test_icat_restricted.py +45 -3
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/utils/compare.py +2 -2
- pyicat_plus-2.3.0/src/pyicat_plus/tests/utils/generate.py +5 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus.egg-info/PKG-INFO +6 -10
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus.egg-info/SOURCES.txt +17 -25
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus.egg-info/entry_points.txt +3 -1
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus.egg-info/requires.txt +1 -9
- pyicat_plus-2.3.0/src/pyicat_plus.egg-info/top_level.txt +2 -0
- {pyicat_plus-2.2.0/src/pyicat_plus/tests/fixtures → pyicat_plus-2.3.0/src/pyicat_plus_pytest_plugin}/proc.py +6 -2
- pyicat_plus-2.2.0/src/pyicat_plus/tests/fixtures/icat.py → pyicat_plus-2.3.0/src/pyicat_plus_pytest_plugin/pytest_plugin.py +20 -19
- {pyicat_plus-2.2.0/src/pyicat_plus/tests → pyicat_plus-2.3.0/src/pyicat_plus_pytest_plugin}/servers/activemq_rest_server.py +6 -3
- {pyicat_plus-2.2.0/src/pyicat_plus/tests → pyicat_plus-2.3.0/src/pyicat_plus_pytest_plugin}/servers/coilmq/pkg_resources.py +4 -1
- {pyicat_plus-2.2.0/src/pyicat_plus/tests → pyicat_plus-2.3.0/src/pyicat_plus_pytest_plugin}/servers/icat_db.py +1 -1
- {pyicat_plus-2.2.0/src/pyicat_plus/tests → pyicat_plus-2.3.0/src/pyicat_plus_pytest_plugin}/servers/icat_session.py +1 -1
- {pyicat_plus-2.2.0/src/pyicat_plus/tests → pyicat_plus-2.3.0/src/pyicat_plus_pytest_plugin}/servers/icatplus_server.py +17 -2
- {pyicat_plus-2.2.0/src/pyicat_plus/tests → pyicat_plus-2.3.0/src/pyicat_plus_pytest_plugin}/servers/stomp_publisher.py +1 -1
- {pyicat_plus-2.2.0/src/pyicat_plus/tests → pyicat_plus-2.3.0/src/pyicat_plus_pytest_plugin}/servers/stomp_subscriber.py +3 -2
- {pyicat_plus-2.2.0/src/pyicat_plus/tests/fixtures → pyicat_plus-2.3.0/src/pyicat_plus_pytest_plugin}/tcp.py +5 -4
- pyicat_plus-2.2.0/README.md +0 -7
- pyicat_plus-2.2.0/src/pyicat_plus/apps/sync_raw.py +0 -584
- pyicat_plus-2.2.0/src/pyicat_plus/client/bliss.py +0 -38
- pyicat_plus-2.2.0/src/pyicat_plus/tests/test_icat_sync.py +0 -747
- pyicat_plus-2.2.0/src/pyicat_plus/tests/test_raw_data.py +0 -57
- pyicat_plus-2.2.0/src/pyicat_plus/tests/utils/generate.py +0 -5
- pyicat_plus-2.2.0/src/pyicat_plus/utils/path_utils.py +0 -25
- pyicat_plus-2.2.0/src/pyicat_plus/utils/raw_data.py +0 -238
- pyicat_plus-2.2.0/src/pyicat_plus/utils/sync_store.py +0 -381
- pyicat_plus-2.2.0/src/pyicat_plus/utils/sync_types.py +0 -394
- pyicat_plus-2.2.0/src/pyicat_plus.egg-info/top_level.txt +0 -1
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/LICENSE.md +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/setup.cfg +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/__init__.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/_icat_messaging/__init__.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/_icat_messaging/deserializers/__init__.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/_icat_messaging/models/__init__.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/_icat_messaging/models/xsd/__init__.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/_icat_messaging/models/xsd/dataset.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/_icat_messaging/models/xsd/investigation.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/_icat_messaging/serializers/__init__.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/_icat_messaging/serializers/dataset.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/_icat_messaging/serializers/dataset_parameters/__init__.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/_icat_messaging/serializers/dataset_parameters/fallback.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/_icat_messaging/serializers/dataset_parameters/main.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/_icat_messaging/serializers/dataset_parameters/pydantic.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/_icat_messaging/serializers/investigation.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/_icat_messaging/serializers/xml.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/_icat_messaging/utils/__init__.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/_icat_messaging/utils/constants.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/_icat_messaging/utils/datetime_utils.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/apps/__init__.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/apps/icat_as_nexus.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/apps/store_from_file.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/client/__init__.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/client/add_files.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/client/archive.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/client/deprecation_utils.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/client/elogbook.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/client/investigation.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/client/metadata.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/client/models/__init__.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/client/models/session.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/client/update_metadata.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/concurrency.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/errors.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/metadata/__init__.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/metadata/drac_report_builder.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/metadata/hdf5_cfg.xml +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/metadata/namespace_wrapper.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/metadata/nexus.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/__init__.py +0 -0
- {pyicat_plus-2.2.0/src/pyicat_plus/tests/fixtures → pyicat_plus-2.3.0/src/pyicat_plus/tests/icat_messaging}/__init__.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/icat_messaging/test_dataset.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/icat_messaging/test_fallback.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/icat_messaging/test_investigation.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/test_cli.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/test_drac_report_builder.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/test_elogbook.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/test_icat_add_files.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/test_icat_archive.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/test_icat_datasets.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/test_icat_definitions.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/test_icat_mockup.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/test_icat_nexus.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/test_icat_update_metadata.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/test_maxsizedict.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/test_namespace.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/tests/test_url_utils.py +0 -0
- {pyicat_plus-2.2.0/src/pyicat_plus/tests/icat_messaging → pyicat_plus-2.3.0/src/pyicat_plus/tests/utils}/__init__.py +0 -0
- {pyicat_plus-2.2.0/src/pyicat_plus/tests/servers → pyicat_plus-2.3.0/src/pyicat_plus/utils}/__init__.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/utils/html_utils.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/utils/log_utils.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/utils/maxsizedict.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/utils/url.py +0 -0
- {pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus.egg-info/dependency_links.txt +0 -0
- {pyicat_plus-2.2.0/src/pyicat_plus/tests/servers/coilmq → pyicat_plus-2.3.0/src/pyicat_plus_pytest_plugin}/__init__.py +0 -0
- {pyicat_plus-2.2.0/src/pyicat_plus/tests/fixtures → pyicat_plus-2.3.0/src/pyicat_plus_pytest_plugin}/misc.py +0 -0
- {pyicat_plus-2.2.0/src/pyicat_plus/tests/utils → pyicat_plus-2.3.0/src/pyicat_plus_pytest_plugin/servers}/__init__.py +0 -0
- {pyicat_plus-2.2.0/src/pyicat_plus/utils → pyicat_plus-2.3.0/src/pyicat_plus_pytest_plugin/servers/coilmq}/__init__.py +0 -0
- {pyicat_plus-2.2.0/src/pyicat_plus/tests → pyicat_plus-2.3.0/src/pyicat_plus_pytest_plugin}/servers/coilmq/__main__.py +0 -0
- {pyicat_plus-2.2.0/src/pyicat_plus/tests → pyicat_plus-2.3.0/src/pyicat_plus_pytest_plugin}/servers/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyicat-plus
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
4
4
|
Summary: Python client to ICAT+
|
|
5
5
|
Author-email: ESRF <dau-pydev@esrf.fr>
|
|
6
6
|
License: GNU Lesser General Public License
|
|
@@ -186,14 +186,10 @@ Requires-Dist: numpy
|
|
|
186
186
|
Requires-Dist: querypool
|
|
187
187
|
Requires-Dist: requests
|
|
188
188
|
Requires-Dist: stompest
|
|
189
|
-
Requires-Dist: tqdm
|
|
190
189
|
Requires-Dist: pillow
|
|
191
190
|
Requires-Dist: xsdata==24.9; python_version == "3.8"
|
|
192
191
|
Requires-Dist: xsdata; python_version >= "3.9"
|
|
193
|
-
Provides-Extra: bliss
|
|
194
|
-
Requires-Dist: blissdata[beacon]; extra == "bliss"
|
|
195
192
|
Provides-Extra: test
|
|
196
|
-
Requires-Dist: pyicat-plus[bliss]; extra == "test"
|
|
197
193
|
Requires-Dist: pytest>=7; extra == "test"
|
|
198
194
|
Requires-Dist: pytest-timeout>=2.1; extra == "test"
|
|
199
195
|
Requires-Dist: numpy>=1.15; extra == "test"
|
|
@@ -203,10 +199,7 @@ Requires-Dist: stomp.py>=7; extra == "test"
|
|
|
203
199
|
Requires-Dist: h5py>=3.5; extra == "test"
|
|
204
200
|
Provides-Extra: dev
|
|
205
201
|
Requires-Dist: pyicat-plus[test]; extra == "dev"
|
|
206
|
-
Requires-Dist:
|
|
207
|
-
Requires-Dist: flake8>=4; extra == "dev"
|
|
208
|
-
Requires-Dist: pep8-naming; extra == "dev"
|
|
209
|
-
Requires-Dist: isort; extra == "dev"
|
|
202
|
+
Requires-Dist: ruff; extra == "dev"
|
|
210
203
|
Requires-Dist: xsdata[cli]; extra == "dev"
|
|
211
204
|
Requires-Dist: pre-commit; extra == "dev"
|
|
212
205
|
Provides-Extra: doc
|
|
@@ -217,7 +210,10 @@ Requires-Dist: pydata-sphinx-theme; extra == "doc"
|
|
|
217
210
|
Requires-Dist: sphinx-copybutton; extra == "doc"
|
|
218
211
|
Dynamic: license-file
|
|
219
212
|
|
|
220
|
-
|
|
213
|
+
<h1>
|
|
214
|
+
<img src="doc/_static/images/pyicatplus-logo.svg" alt="PyIcat-Plus logo" height="52">
|
|
215
|
+
PyIcat-Plus
|
|
216
|
+
</h1>
|
|
221
217
|
|
|
222
218
|
A python client for ICAT+.
|
|
223
219
|
|
|
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "pyicat-plus"
|
|
9
|
-
version = "2.
|
|
9
|
+
version = "2.3.0"
|
|
10
10
|
authors = [{name = "ESRF", email = "dau-pydev@esrf.fr"}]
|
|
11
11
|
description = "Python client to ICAT+"
|
|
12
12
|
readme = {file = "README.md", content-type = "text/markdown"}
|
|
@@ -26,7 +26,6 @@ dependencies = [
|
|
|
26
26
|
"querypool",
|
|
27
27
|
"requests",
|
|
28
28
|
"stompest",
|
|
29
|
-
"tqdm",
|
|
30
29
|
"pillow",
|
|
31
30
|
"xsdata==24.9; python_version == '3.8'", # latest version that supports Python 3.8
|
|
32
31
|
"xsdata; python_version >= '3.9'",
|
|
@@ -40,11 +39,7 @@ Issues = "https://gitlab.esrf.fr/icat/pyicat-plus/issues"
|
|
|
40
39
|
Changelog = "https://gitlab.esrf.fr/icat/pyicat-plus/-/blob/main/CHANGELOG.md"
|
|
41
40
|
|
|
42
41
|
[project.optional-dependencies]
|
|
43
|
-
bliss = [
|
|
44
|
-
"blissdata[beacon]",
|
|
45
|
-
]
|
|
46
42
|
test = [
|
|
47
|
-
"pyicat-plus[bliss]",
|
|
48
43
|
"pytest >=7",
|
|
49
44
|
"pytest-timeout >=2.1",
|
|
50
45
|
"numpy >=1.15",
|
|
@@ -55,10 +50,7 @@ test = [
|
|
|
55
50
|
]
|
|
56
51
|
dev = [
|
|
57
52
|
"pyicat-plus[test]",
|
|
58
|
-
"
|
|
59
|
-
"flake8 >=4",
|
|
60
|
-
"pep8-naming",
|
|
61
|
-
"isort",
|
|
53
|
+
"ruff",
|
|
62
54
|
"xsdata[cli]",
|
|
63
55
|
"pre-commit",
|
|
64
56
|
]
|
|
@@ -83,13 +75,36 @@ where = ["src"]
|
|
|
83
75
|
[tool.coverage.run]
|
|
84
76
|
omit = ['*/tests/*']
|
|
85
77
|
|
|
86
|
-
[tool.
|
|
87
|
-
|
|
88
|
-
|
|
78
|
+
[tool.ruff]
|
|
79
|
+
line-length = 88
|
|
80
|
+
|
|
81
|
+
[tool.ruff.lint]
|
|
82
|
+
select = [
|
|
83
|
+
"E", # pycodestyle errors
|
|
84
|
+
"F", # pyflakes
|
|
85
|
+
"I", # isort
|
|
86
|
+
"N", # pep8-naming
|
|
87
|
+
"S", # flake8-bandit
|
|
88
|
+
]
|
|
89
|
+
ignore = ["E501"]
|
|
90
|
+
|
|
91
|
+
[tool.ruff.lint.per-file-ignores]
|
|
92
|
+
"**/tests/**" = [
|
|
93
|
+
"S101", # allow asserts
|
|
94
|
+
]
|
|
95
|
+
"src/pyicat_plus_pytest_plugin/**" = [
|
|
96
|
+
"S101", # allow asserts
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
[tool.ruff.lint.isort]
|
|
100
|
+
force-single-line = true
|
|
101
|
+
known-first-party = ["pyicat_plus", "pyicat_plus_pytest_plugin"]
|
|
102
|
+
|
|
103
|
+
[project.entry-points."pytest11"]
|
|
104
|
+
"pyicat_plus" = "pyicat_plus_pytest_plugin.pytest_plugin"
|
|
89
105
|
|
|
90
106
|
[project.scripts]
|
|
91
107
|
icat-store-raw = "pyicat_plus.apps.store_raw:main"
|
|
92
|
-
icat-sync-raw = "pyicat_plus.apps.sync_raw:main"
|
|
93
108
|
icat-store-processed = "pyicat_plus.apps.store_processed:main"
|
|
94
109
|
icat-store-from-file = "pyicat_plus.apps.store_from_file:main"
|
|
95
110
|
icat-nexus-definitions = "pyicat_plus.apps.icat_as_nexus:main"
|
{pyicat_plus-2.2.0 → pyicat_plus-2.3.0}/src/pyicat_plus/_icat_messaging/deserializers/xml.py
RENAMED
|
@@ -16,7 +16,7 @@ def deserialize_message(data: bytes) -> Tuple[str, Dict[str, Any]]:
|
|
|
16
16
|
"""
|
|
17
17
|
:raises xml.etree.ElementTree.ParseError:
|
|
18
18
|
"""
|
|
19
|
-
root = ElementTree.fromstring(data)
|
|
19
|
+
root = ElementTree.fromstring(data) # noqa: S314 -- trusted internal ICAT messaging broker
|
|
20
20
|
root_tag = root.tag.split("}", 1)[-1]
|
|
21
21
|
|
|
22
22
|
if root_tag == "dataset":
|
|
@@ -9,7 +9,7 @@ def main(argv=None):
|
|
|
9
9
|
if argv is None:
|
|
10
10
|
argv = sys.argv
|
|
11
11
|
|
|
12
|
-
parser = argparse.ArgumentParser(description="Register
|
|
12
|
+
parser = argparse.ArgumentParser(description="Register processed data with ICAT")
|
|
13
13
|
|
|
14
14
|
store_raw.add_store_parameters(parser)
|
|
15
15
|
add_process_parameters(parser)
|
|
@@ -27,6 +27,7 @@ def main(argv=None):
|
|
|
27
27
|
path=args.path,
|
|
28
28
|
metadata=args.metadata,
|
|
29
29
|
raw=args.raw,
|
|
30
|
+
store_filename=args.store_filename,
|
|
30
31
|
)
|
|
31
32
|
|
|
32
33
|
client.disconnect()
|
|
@@ -37,7 +38,7 @@ def add_process_parameters(parser):
|
|
|
37
38
|
"--raw",
|
|
38
39
|
action="append",
|
|
39
40
|
required=True,
|
|
40
|
-
help="
|
|
41
|
+
help="Input dataset directories, raw or processed",
|
|
41
42
|
)
|
|
42
43
|
|
|
43
44
|
|
|
@@ -25,6 +25,7 @@ def main(argv=None):
|
|
|
25
25
|
dataset=args.dataset,
|
|
26
26
|
path=args.path,
|
|
27
27
|
metadata=args.metadata,
|
|
28
|
+
store_filename=args.store_filename,
|
|
28
29
|
)
|
|
29
30
|
client.disconnect()
|
|
30
31
|
|
|
@@ -64,6 +65,11 @@ def add_store_parameters(parser):
|
|
|
64
65
|
default=[],
|
|
65
66
|
)
|
|
66
67
|
|
|
68
|
+
parser.add_argument(
|
|
69
|
+
"--store-filename",
|
|
70
|
+
help="Store in an XML file instead of sending to ActiveMQ",
|
|
71
|
+
)
|
|
72
|
+
|
|
67
73
|
|
|
68
74
|
def apply_store_parameters(args):
|
|
69
75
|
if args.metadatafile:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import List
|
|
2
2
|
|
|
3
|
-
ELOGBOOK_TOKEN: str = "elogbook-00000000-0000-0000-0000-000000000000"
|
|
3
|
+
ELOGBOOK_TOKEN: str = "elogbook-00000000-0000-0000-0000-000000000000" # noqa: S105 -- placeholder default, not a secret
|
|
4
4
|
|
|
5
5
|
METADATA_QUEUE: str = "icatIngest"
|
|
6
6
|
METADATA_BROKERS: List[str] = ["bcu-mq-01.esrf.fr:61613", "bcu-mq-02.esrf.fr:61613"]
|
|
@@ -8,6 +8,8 @@ import requests
|
|
|
8
8
|
|
|
9
9
|
from ..utils.url import normalize_url
|
|
10
10
|
from .deprecation_utils import deprecated_argument
|
|
11
|
+
from .deprecation_utils import deprecated_method
|
|
12
|
+
from .types import InvestigationType
|
|
11
13
|
from .types import InvestigationUser
|
|
12
14
|
from .types import SampleMetadata
|
|
13
15
|
|
|
@@ -41,6 +43,7 @@ class IcatPlusRestrictedClient:
|
|
|
41
43
|
|
|
42
44
|
def _init_urls(self, url: str):
|
|
43
45
|
self._investigation_url = urljoin(url, "catalogue/{session_id}/investigation")
|
|
46
|
+
self._investigation_types_url = urljoin(url, "catalogue/investigationtypes")
|
|
44
47
|
self._sample_url = urljoin(url, "catalogue/{session_id}/samples")
|
|
45
48
|
self._dataset_url = urljoin(url, "catalogue/datasets")
|
|
46
49
|
self._parcel_url = urljoin(url, "tracking/{session_id}/parcel")
|
|
@@ -65,7 +68,7 @@ class IcatPlusRestrictedClient:
|
|
|
65
68
|
}
|
|
66
69
|
if username is not None:
|
|
67
70
|
credentials["username"] = username
|
|
68
|
-
response = requests.post(self._authentication_url, json=credentials)
|
|
71
|
+
response = requests.post(self._authentication_url, json=credentials) # noqa: S113 -- trusted internal ICAT+ service
|
|
69
72
|
response.raise_for_status()
|
|
70
73
|
authentication_response = response.json()
|
|
71
74
|
self._session_id = authentication_response["sessionId"]
|
|
@@ -115,7 +118,12 @@ class IcatPlusRestrictedClient:
|
|
|
115
118
|
params = {k: v for k, v in params.items() if v is not None}
|
|
116
119
|
|
|
117
120
|
url = self._investigation_url.format(session_id=self.session_id)
|
|
118
|
-
response = requests.get(url, params=params)
|
|
121
|
+
response = requests.get(url, params=params) # noqa: S113 -- trusted internal ICAT+ service
|
|
122
|
+
response.raise_for_status()
|
|
123
|
+
return response.json()
|
|
124
|
+
|
|
125
|
+
def get_investigation_types(self) -> List[InvestigationType]:
|
|
126
|
+
response = requests.get(self._investigation_types_url) # noqa: S113 -- trusted internal ICAT+ service
|
|
119
127
|
response.raise_for_status()
|
|
120
128
|
return response.json()
|
|
121
129
|
|
|
@@ -127,7 +135,7 @@ class IcatPlusRestrictedClient:
|
|
|
127
135
|
params = {"investigationId": investigation_id}
|
|
128
136
|
|
|
129
137
|
url = self._parcel_url.format(session_id=self.session_id)
|
|
130
|
-
response = requests.get(url, params=params)
|
|
138
|
+
response = requests.get(url, params=params) # noqa: S113 -- trusted internal ICAT+ service
|
|
131
139
|
response.raise_for_status()
|
|
132
140
|
return response.json()
|
|
133
141
|
|
|
@@ -161,7 +169,7 @@ class IcatPlusRestrictedClient:
|
|
|
161
169
|
"Authorization": f"Bearer {self.session_id}",
|
|
162
170
|
}
|
|
163
171
|
url = self._dataset_url
|
|
164
|
-
response = requests.get(url, params=params, headers=headers)
|
|
172
|
+
response = requests.get(url, params=params, headers=headers) # noqa: S113 -- trusted internal ICAT+ service
|
|
165
173
|
response.raise_for_status()
|
|
166
174
|
return response.json()
|
|
167
175
|
|
|
@@ -173,7 +181,7 @@ class IcatPlusRestrictedClient:
|
|
|
173
181
|
:raises RuntimeError: No session ID is available.
|
|
174
182
|
"""
|
|
175
183
|
url = self._session_info_url.format(session_id=self.session_id)
|
|
176
|
-
response = requests.get(url)
|
|
184
|
+
response = requests.get(url) # noqa: S113 -- trusted internal ICAT+ service
|
|
177
185
|
response.raise_for_status()
|
|
178
186
|
return response.json()
|
|
179
187
|
|
|
@@ -209,7 +217,7 @@ class IcatPlusRestrictedClient:
|
|
|
209
217
|
params = {k: v for k, v in params.items() if v is not None}
|
|
210
218
|
|
|
211
219
|
url = self._sample_url.format(session_id=self.session_id)
|
|
212
|
-
response = requests.get(url, params=params)
|
|
220
|
+
response = requests.get(url, params=params) # noqa: S113 -- trusted internal ICAT+ service
|
|
213
221
|
response.raise_for_status()
|
|
214
222
|
return response.json()
|
|
215
223
|
|
|
@@ -227,15 +235,35 @@ class IcatPlusRestrictedClient:
|
|
|
227
235
|
params["parameters"] = filter
|
|
228
236
|
|
|
229
237
|
url = self._sample_metadata_url.format(session_id=self.session_id)
|
|
230
|
-
response = requests.get(url, params=params)
|
|
238
|
+
response = requests.get(url, params=params) # noqa: S113 -- trusted internal ICAT+ service
|
|
231
239
|
response.raise_for_status()
|
|
232
240
|
return response.json()
|
|
233
241
|
|
|
242
|
+
@deprecated_method
|
|
234
243
|
def get_sample_files_information_by(self, sample_id: str) -> dict:
|
|
235
|
-
|
|
244
|
+
"""DEPRECATED: This method is deprecated and may be removed in future versions.
|
|
245
|
+
Use `get_sample_information_list_by` instead.
|
|
246
|
+
|
|
247
|
+
Returns a single sample's file information, or an empty dict when not found.
|
|
248
|
+
"""
|
|
249
|
+
results = self.get_sample_information_list_by(sample_id=sample_id)
|
|
250
|
+
return results[0] if results else {}
|
|
251
|
+
|
|
252
|
+
def get_sample_information_list_by(
|
|
253
|
+
self,
|
|
254
|
+
sample_id: Optional[str] = None,
|
|
255
|
+
investigation_id: Optional[str] = None,
|
|
256
|
+
) -> List[dict]:
|
|
257
|
+
if sample_id is None and investigation_id is None:
|
|
258
|
+
raise ValueError(
|
|
259
|
+
"Either 'sample_id' or 'investigation_id' must be provided."
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
params = {"sampleId": sample_id, "investigationId": investigation_id}
|
|
263
|
+
params = {k: v for k, v in params.items() if v is not None}
|
|
236
264
|
|
|
237
265
|
url = self._sample_files_url.format(session_id=self.session_id)
|
|
238
|
-
response = requests.get(url, params=params)
|
|
266
|
+
response = requests.get(url, params=params) # noqa: S113 -- trusted internal ICAT+ service
|
|
239
267
|
response.raise_for_status()
|
|
240
268
|
return response.json()
|
|
241
269
|
|
|
@@ -250,7 +278,7 @@ class IcatPlusRestrictedClient:
|
|
|
250
278
|
|
|
251
279
|
url = self._download_file_url.format(session_id=self.session_id)
|
|
252
280
|
if use_chunks:
|
|
253
|
-
with requests.get(url, params=params, stream=True) as response:
|
|
281
|
+
with requests.get(url, params=params, stream=True) as response: # noqa: S113 -- trusted internal ICAT+ service
|
|
254
282
|
response.raise_for_status()
|
|
255
283
|
return b"".join(
|
|
256
284
|
chunk
|
|
@@ -258,7 +286,7 @@ class IcatPlusRestrictedClient:
|
|
|
258
286
|
if chunk
|
|
259
287
|
)
|
|
260
288
|
else:
|
|
261
|
-
response = requests.get(url, params=params)
|
|
289
|
+
response = requests.get(url, params=params) # noqa: S113 -- trusted internal ICAT+ service
|
|
262
290
|
response.raise_for_status()
|
|
263
291
|
return response.content
|
|
264
292
|
|
|
@@ -269,7 +297,7 @@ class IcatPlusRestrictedClient:
|
|
|
269
297
|
url = self._investigation_users_url.format(
|
|
270
298
|
session_id=self.session_id, investigation_id=investigation_id
|
|
271
299
|
)
|
|
272
|
-
response = requests.get(url)
|
|
300
|
+
response = requests.get(url) # noqa: S113 -- trusted internal ICAT+ service
|
|
273
301
|
response.raise_for_status()
|
|
274
302
|
return response.json()
|
|
275
303
|
|
|
@@ -14,6 +14,7 @@ from .types import ArchiveStatusType as StatusType # noqa F401 deprecated
|
|
|
14
14
|
from .types import Dataset
|
|
15
15
|
from .types import DatasetId
|
|
16
16
|
from .types import DatasetMetadata # noqa F401
|
|
17
|
+
from .types import InvestigationType
|
|
17
18
|
from .types import InvestigationUser
|
|
18
19
|
from .types import SampleMetadata
|
|
19
20
|
|
|
@@ -143,7 +144,7 @@ class IcatClientInterface:
|
|
|
143
144
|
store_filename: Optional[str] = None,
|
|
144
145
|
):
|
|
145
146
|
"""
|
|
146
|
-
Request icat to store raw dataset.
|
|
147
|
+
Request icat to store a raw dataset, i.e. a dataset without other datasets as input.
|
|
147
148
|
|
|
148
149
|
:param beamline str: beamline name like id01, id15a, bm18...
|
|
149
150
|
:param proposal str: proposal name like in1169, blc14795, ihma429...
|
|
@@ -166,14 +167,14 @@ class IcatClientInterface:
|
|
|
166
167
|
store_filename: Optional[str] = None,
|
|
167
168
|
):
|
|
168
169
|
"""
|
|
169
|
-
Request icat to store a processed dataset.
|
|
170
|
+
Request icat to store a processed dataset, i.e. a dataset with other datasets as input.
|
|
170
171
|
|
|
171
172
|
:param beamline str: beamline name like id01, id15a, bm18...
|
|
172
173
|
:param proposal str: proposal name like in1169, blc14795, ihma429...
|
|
173
174
|
:param str dataset: dataset name like sample_XYZ.
|
|
174
175
|
:param str path: path to the processed dataset to store. Can be a file or a folder.
|
|
175
176
|
:param dict metadata: metadata to associate with the dataset. Must contain keys defined by the appropriate application definition, available at https://icat-esrf-definitions.readthedocs.io.
|
|
176
|
-
:param tuple raw: Path(s) to the
|
|
177
|
+
:param tuple raw: Path(s) to the input dataset(s), raw or processed. Should point to the dataset folder(s).
|
|
177
178
|
If processing relies on multiple datasets, all corresponding folders must be provided.
|
|
178
179
|
:param str store_filename: xml file with metadata to be stored.
|
|
179
180
|
"""
|
|
@@ -413,6 +414,15 @@ class IcatClientInterface:
|
|
|
413
414
|
"""
|
|
414
415
|
raise NotImplementedError
|
|
415
416
|
|
|
417
|
+
def get_investigation_types(self) -> List[InvestigationType]:
|
|
418
|
+
"""
|
|
419
|
+
Returns a list of investigation types. Does not require authentication.
|
|
420
|
+
API Reference: https://icatplus.esrf.fr/api-docs/#/Catalogue/get_catalogue_investigationtypes
|
|
421
|
+
|
|
422
|
+
:returns: list of investigation types.
|
|
423
|
+
"""
|
|
424
|
+
raise NotImplementedError
|
|
425
|
+
|
|
416
426
|
def get_parcels_by(self, investigation_id: str) -> List[dict]:
|
|
417
427
|
"""
|
|
418
428
|
Returns the list of parcels associated to an investigation.
|
|
@@ -448,12 +458,31 @@ class IcatClientInterface:
|
|
|
448
458
|
"""
|
|
449
459
|
raise NotImplementedError
|
|
450
460
|
|
|
461
|
+
@deprecated_method
|
|
451
462
|
def get_sample_files_information_by(self, sample_id: str) -> dict:
|
|
452
|
-
"""
|
|
463
|
+
"""DEPRECATED: This method is deprecated and may be removed in future versions.
|
|
464
|
+
Use `get_sample_information_list_by` instead.
|
|
465
|
+
|
|
453
466
|
Returns the sample file information for a given sample.
|
|
454
467
|
|
|
455
468
|
:param sample_id: Sample identifier.
|
|
456
|
-
:returns: Sample file information as dict.
|
|
469
|
+
:returns: Sample file information as dict, or an empty dict when no match is found.
|
|
470
|
+
"""
|
|
471
|
+
raise NotImplementedError
|
|
472
|
+
|
|
473
|
+
def get_sample_information_list_by(
|
|
474
|
+
self,
|
|
475
|
+
sample_id: Optional[str] = None,
|
|
476
|
+
investigation_id: Optional[str] = None,
|
|
477
|
+
) -> List[dict]:
|
|
478
|
+
"""
|
|
479
|
+
Returns the list of sample file information for a given sample and/or
|
|
480
|
+
investigation.
|
|
481
|
+
|
|
482
|
+
:param sample_id: Sample identifier.
|
|
483
|
+
:param investigation_id: Investigation identifier.
|
|
484
|
+
:returns: List of sample file information.
|
|
485
|
+
:raises ValueError: Neither `sample_id` nor `investigation_id` is provided.
|
|
457
486
|
"""
|
|
458
487
|
raise NotImplementedError
|
|
459
488
|
|
|
@@ -23,6 +23,7 @@ from .types import ArchiveStatusType
|
|
|
23
23
|
from .types import ArchiveStatusType as StatusType # noqa F401 deprecated
|
|
24
24
|
from .types import Dataset
|
|
25
25
|
from .types import DatasetId
|
|
26
|
+
from .types import InvestigationType
|
|
26
27
|
from .types import InvestigationUser
|
|
27
28
|
from .types import SampleMetadata
|
|
28
29
|
from .update_metadata import IcatUpdateMetadataClient
|
|
@@ -666,7 +667,8 @@ class IcatClient(IcatClientInterface):
|
|
|
666
667
|
:param dataset: The dataset name.
|
|
667
668
|
:param path: The path to the dataset on disk.
|
|
668
669
|
:param metadata: A dictionary of metadata to be attached to the dataset.
|
|
669
|
-
:param raw:
|
|
670
|
+
:param raw: Path(s) to the input dataset(s), raw or processed. Shorthand for
|
|
671
|
+
``metadata = {'input_datasets': ...}``.
|
|
670
672
|
:param store_filename: Save metadata in this file instead of sending it to ICAT.
|
|
671
673
|
:param strict: Strict metadata validation.
|
|
672
674
|
|
|
@@ -687,7 +689,7 @@ class IcatClient(IcatClientInterface):
|
|
|
687
689
|
else:
|
|
688
690
|
metadata["input_datasets"] = [raw]
|
|
689
691
|
if not metadata.get("input_datasets"):
|
|
690
|
-
raise ValueError("Provide 'raw' dataset directories")
|
|
692
|
+
raise ValueError("Provide 'raw' input dataset directories")
|
|
691
693
|
self.store_dataset(
|
|
692
694
|
beamline=beamline,
|
|
693
695
|
proposal=proposal,
|
|
@@ -890,6 +892,9 @@ class IcatClient(IcatClientInterface):
|
|
|
890
892
|
parameters=parameters,
|
|
891
893
|
)
|
|
892
894
|
|
|
895
|
+
def get_investigation_types(self) -> List[InvestigationType]:
|
|
896
|
+
return self._icatplus_restricted_client.get_investigation_types()
|
|
897
|
+
|
|
893
898
|
def get_samples_by(
|
|
894
899
|
self,
|
|
895
900
|
investigation_id: Optional[str] = None,
|
|
@@ -929,6 +934,15 @@ class IcatClient(IcatClientInterface):
|
|
|
929
934
|
sample_id
|
|
930
935
|
)
|
|
931
936
|
|
|
937
|
+
def get_sample_information_list_by(
|
|
938
|
+
self,
|
|
939
|
+
sample_id: Optional[str] = None,
|
|
940
|
+
investigation_id: Optional[str] = None,
|
|
941
|
+
) -> List[dict]:
|
|
942
|
+
return self._icatplus_restricted_client.get_sample_information_list_by(
|
|
943
|
+
sample_id, investigation_id
|
|
944
|
+
)
|
|
945
|
+
|
|
932
946
|
def download_file_by(
|
|
933
947
|
self,
|
|
934
948
|
sample_id: str,
|
|
@@ -26,7 +26,7 @@ class IcatMessagingClient:
|
|
|
26
26
|
MONITOR_SCHEME = "http"
|
|
27
27
|
DEFAULT_MONITOR_PORT = 8778
|
|
28
28
|
MONITOR_USER = "user"
|
|
29
|
-
MONITOR_PWD = "user"
|
|
29
|
+
MONITOR_PWD = "user" # noqa: S105 -- default placeholder credential, not a secret
|
|
30
30
|
|
|
31
31
|
def __init__(
|
|
32
32
|
self,
|
|
@@ -112,7 +112,7 @@ class IcatMessagingClient:
|
|
|
112
112
|
@property
|
|
113
113
|
def _consumer_count(self):
|
|
114
114
|
url = self.__consumer_count_url.format(host=self._host)
|
|
115
|
-
response = requests.get(url, headers=self.__jolokia_headers)
|
|
115
|
+
response = requests.get(url, headers=self.__jolokia_headers) # noqa: S113 -- trusted internal ActiveMQ broker
|
|
116
116
|
if not response.ok:
|
|
117
117
|
raise RuntimeError(
|
|
118
118
|
response, "Failed to retrieve the ActiveMQ consumer count"
|
|
@@ -91,6 +91,9 @@ class IcatNullClient(IcatClientInterface):
|
|
|
91
91
|
def get_sample_files_information_by(self, *args, **kwargs) -> None:
|
|
92
92
|
pass
|
|
93
93
|
|
|
94
|
+
def get_sample_information_list_by(self, *args, **kwargs) -> None:
|
|
95
|
+
pass
|
|
96
|
+
|
|
94
97
|
def download_file_by(self, *args, **kwargs) -> None:
|
|
95
98
|
pass
|
|
96
99
|
|
|
@@ -73,3 +73,13 @@ class InvestigationUser(TypedDict):
|
|
|
73
73
|
orcid: Optional[str]
|
|
74
74
|
affiliation: Optional[str]
|
|
75
75
|
role: str
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class InvestigationType(TypedDict):
|
|
79
|
+
"""
|
|
80
|
+
Investigation type information
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
id: str
|
|
84
|
+
name: str
|
|
85
|
+
description: Optional[str]
|
|
@@ -314,7 +314,6 @@ def load_group(in_node: ElementTree.Element, **node_attributes) -> IcatFieldGrou
|
|
|
314
314
|
nodes[icat_item.name] = icat_item
|
|
315
315
|
|
|
316
316
|
for group_name, element in groups:
|
|
317
|
-
|
|
318
317
|
technique_names = _GROUP_NAME_TO_TECHNIQUES.get(group_name, None)
|
|
319
318
|
if technique_names:
|
|
320
319
|
metadata_generator = technique.get_technique_metadata(*technique_names)
|
|
@@ -367,7 +366,7 @@ def icat_fields_source(url: Optional[str] = None) -> Union[str, StringIO]:
|
|
|
367
366
|
if url.startswith("file://") or url.startswith("xml://"):
|
|
368
367
|
return re.sub(r"^[a-z]+://", "", url)
|
|
369
368
|
try:
|
|
370
|
-
response = requests.get(url)
|
|
369
|
+
response = requests.get(url) # noqa: S113 -- trusted ESRF-hosted definitions URL
|
|
371
370
|
response.raise_for_status()
|
|
372
371
|
except Exception:
|
|
373
372
|
working_url = "https://gitlab.esrf.fr/icat/hdf5-master-config/-/raw/master/src/icat_esrf_definitions/hdf5_cfg.xml"
|
|
@@ -385,7 +384,7 @@ def load_icat_fields(url: Optional[str] = None) -> IcatFieldGroup:
|
|
|
385
384
|
"file://", "xml://" or anything the `requests` library can handle.
|
|
386
385
|
:returns: a mapping object representing the tree relationship of ICAT fields
|
|
387
386
|
"""
|
|
388
|
-
tree = ElementTree.parse(icat_fields_source(url=url))
|
|
387
|
+
tree = ElementTree.parse(icat_fields_source(url=url)) # noqa: S314 -- trusted ESRF-hosted definitions file
|
|
389
388
|
in_node = tree.getroot()
|
|
390
389
|
return load_group(
|
|
391
390
|
in_node, name="", parent=IcatNodeId(), NX_class="NXentry", techniques=set()
|
|
@@ -377,7 +377,7 @@ class _Investigations:
|
|
|
377
377
|
investigation = {
|
|
378
378
|
"id": len(self._investigations),
|
|
379
379
|
"startDate": startdate.astimezone().isoformat(),
|
|
380
|
-
"unique": random.uniform(0, 1),
|
|
380
|
+
"unique": random.uniform(0, 1), # noqa: S311 -- test data, not crypto
|
|
381
381
|
}
|
|
382
382
|
if end_offset is not None:
|
|
383
383
|
enddate = self._date + end_offset
|
|
@@ -27,7 +27,11 @@ def test_login(icatplus_restricted_client):
|
|
|
27
27
|
def test_login_with_username_plugin(icatplus_restricted_client):
|
|
28
28
|
client, messages = icatplus_restricted_client
|
|
29
29
|
|
|
30
|
-
result = client.login(
|
|
30
|
+
result = client.login(
|
|
31
|
+
password="correct", # noqa: S106 -- test server sentinel value
|
|
32
|
+
username="john",
|
|
33
|
+
plugin="db",
|
|
34
|
+
)
|
|
31
35
|
|
|
32
36
|
assert result["sessionId"] == client.session_id
|
|
33
37
|
assert messages.empty()
|
|
@@ -230,13 +234,41 @@ def test_get_sample_files_information_by(icatplus_restricted_client):
|
|
|
230
234
|
|
|
231
235
|
sample_id = generate.icat_id()
|
|
232
236
|
|
|
237
|
+
with pytest.warns(DeprecationWarning, match="get_sample_files_information_by"):
|
|
238
|
+
with pytest.raises(RuntimeError, match="Login is required."):
|
|
239
|
+
_ = client.get_sample_files_information_by(sample_id)
|
|
240
|
+
|
|
241
|
+
assert client.login("correct")
|
|
242
|
+
|
|
243
|
+
with pytest.warns(DeprecationWarning, match="get_sample_files_information_by"):
|
|
244
|
+
sample_files = client.get_sample_files_information_by(sample_id)
|
|
245
|
+
|
|
246
|
+
assert sample_files == {}
|
|
247
|
+
assert messages.empty()
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def test_get_sample_information_list_by(icatplus_restricted_client):
|
|
251
|
+
client, messages = icatplus_restricted_client
|
|
252
|
+
|
|
253
|
+
sample_id = generate.icat_id()
|
|
254
|
+
investigation_id = generate.icat_id()
|
|
255
|
+
|
|
233
256
|
with pytest.raises(RuntimeError, match="Login is required."):
|
|
234
|
-
_ = client.
|
|
257
|
+
_ = client.get_sample_information_list_by(sample_id=sample_id)
|
|
235
258
|
|
|
236
259
|
assert client.login("correct")
|
|
237
260
|
|
|
238
|
-
|
|
261
|
+
with pytest.raises(
|
|
262
|
+
ValueError, match="Either 'sample_id' or 'investigation_id' must be provided."
|
|
263
|
+
):
|
|
264
|
+
client.get_sample_information_list_by()
|
|
265
|
+
|
|
266
|
+
sample_files = client.get_sample_information_list_by(sample_id=sample_id)
|
|
267
|
+
assert sample_files == []
|
|
239
268
|
|
|
269
|
+
sample_files = client.get_sample_information_list_by(
|
|
270
|
+
investigation_id=investigation_id
|
|
271
|
+
)
|
|
240
272
|
assert sample_files == []
|
|
241
273
|
assert messages.empty()
|
|
242
274
|
|
|
@@ -292,6 +324,16 @@ def test_get_investigation_users(icatplus_restricted_client):
|
|
|
292
324
|
assert messages.empty()
|
|
293
325
|
|
|
294
326
|
|
|
327
|
+
def test_get_investigation_types(icatplus_restricted_client):
|
|
328
|
+
client, messages = icatplus_restricted_client
|
|
329
|
+
|
|
330
|
+
investigation_types = client.get_investigation_types()
|
|
331
|
+
|
|
332
|
+
assert isinstance(investigation_types, list)
|
|
333
|
+
assert investigation_types
|
|
334
|
+
assert messages.empty()
|
|
335
|
+
|
|
336
|
+
|
|
295
337
|
def _release_date_from_start_date(start_date_str: str) -> datetime.date:
|
|
296
338
|
start = datetime.datetime.fromisoformat(start_date_str[:19])
|
|
297
339
|
return start.date().replace(year=start.year + 3)
|
|
@@ -83,7 +83,7 @@ def _set_expected_value(expected: dict, value: str, *keys) -> None:
|
|
|
83
83
|
|
|
84
84
|
if not isinstance(param_list, list):
|
|
85
85
|
raise TypeError(
|
|
86
|
-
f"Expected list at '{'.'.join(keys[:i+1])}', got {type(param_list).__name__}"
|
|
86
|
+
f"Expected list at '{'.'.join(keys[: i + 1])}', got {type(param_list).__name__}"
|
|
87
87
|
)
|
|
88
88
|
|
|
89
89
|
# Do not overwrite existing parameter
|
|
@@ -127,7 +127,7 @@ def _set_expected_to_actual_value(actual: dict, expected: dict, *keys: str) -> N
|
|
|
127
127
|
|
|
128
128
|
if not isinstance(value, list):
|
|
129
129
|
raise TypeError(
|
|
130
|
-
f"Expected list at '{'.'.join(keys[:i+1])}', "
|
|
130
|
+
f"Expected list at '{'.'.join(keys[: i + 1])}', "
|
|
131
131
|
f"got {type(value).__name__}"
|
|
132
132
|
)
|
|
133
133
|
|