psdi-data-conversion 0.0.36__py3-none-any.whl → 0.0.37__py3-none-any.whl
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.
- psdi_data_conversion/app.py +94 -14
- psdi_data_conversion/converters/base.py +2 -2
- psdi_data_conversion/static/content/download.htm +22 -9
- psdi_data_conversion/static/styles/psdi-common.css +5 -4
- psdi_data_conversion/templates/index.htm +6 -1
- psdi_data_conversion/testing/constants.py +6 -3
- psdi_data_conversion/testing/conversion_callbacks.py +7 -6
- psdi_data_conversion/testing/conversion_test_specs.py +107 -18
- psdi_data_conversion/testing/gui.py +366 -0
- psdi_data_conversion/testing/utils.py +86 -44
- {psdi_data_conversion-0.0.36.dist-info → psdi_data_conversion-0.0.37.dist-info}/METADATA +73 -57
- {psdi_data_conversion-0.0.36.dist-info → psdi_data_conversion-0.0.37.dist-info}/RECORD +15 -14
- {psdi_data_conversion-0.0.36.dist-info → psdi_data_conversion-0.0.37.dist-info}/WHEEL +1 -1
- {psdi_data_conversion-0.0.36.dist-info → psdi_data_conversion-0.0.37.dist-info}/entry_points.txt +1 -0
- {psdi_data_conversion-0.0.36.dist-info → psdi_data_conversion-0.0.37.dist-info}/licenses/LICENSE +0 -0
psdi_data_conversion/app.py
CHANGED
@@ -5,6 +5,7 @@ Version 1.0, 8th November 2024
|
|
5
5
|
This script acts as a server for the PSDI Data Conversion Service website.
|
6
6
|
"""
|
7
7
|
|
8
|
+
from argparse import ArgumentParser
|
8
9
|
import hashlib
|
9
10
|
import os
|
10
11
|
import json
|
@@ -14,6 +15,7 @@ import sys
|
|
14
15
|
import traceback
|
15
16
|
from flask import Flask, request, render_template, abort, Response
|
16
17
|
|
18
|
+
import psdi_data_conversion
|
17
19
|
from psdi_data_conversion import log_utility
|
18
20
|
from psdi_data_conversion import constants as const
|
19
21
|
from psdi_data_conversion.converter import run_converter
|
@@ -63,6 +65,20 @@ else:
|
|
63
65
|
print(f"ERROR: {str(e)}")
|
64
66
|
exit(1)
|
65
67
|
|
68
|
+
# Get the maximum allowed size from the envvar for it
|
69
|
+
ev_max_file_size = os.environ.get(const.MAX_FILESIZE_EV)
|
70
|
+
if ev_max_file_size is not None:
|
71
|
+
max_file_size = float(ev_max_file_size)*const.MEGABYTE
|
72
|
+
else:
|
73
|
+
max_file_size = const.DEFAULT_MAX_FILE_SIZE
|
74
|
+
|
75
|
+
# And same for the Open Babel maximum file size
|
76
|
+
ev_max_file_size_ob = os.environ.get(const.MAX_FILESIZE_OB_EV)
|
77
|
+
if ev_max_file_size_ob is not None:
|
78
|
+
max_file_size_ob = float(ev_max_file_size_ob)*const.MEGABYTE
|
79
|
+
else:
|
80
|
+
max_file_size_ob = const.DEFAULT_MAX_FILE_SIZE_OB
|
81
|
+
|
66
82
|
app = Flask(__name__)
|
67
83
|
|
68
84
|
|
@@ -95,19 +111,6 @@ def get_last_sha() -> str:
|
|
95
111
|
def website():
|
96
112
|
"""Return the web page along with the token
|
97
113
|
"""
|
98
|
-
# Get the maximum allowed size from the envvar for it
|
99
|
-
ev_max_file_size = os.environ.get(const.MAX_FILESIZE_EV)
|
100
|
-
if ev_max_file_size is not None:
|
101
|
-
max_file_size = float(ev_max_file_size)*const.MEGABYTE
|
102
|
-
else:
|
103
|
-
max_file_size = const.DEFAULT_MAX_FILE_SIZE
|
104
|
-
|
105
|
-
# And same for the Open Babel maximum file size
|
106
|
-
ev_max_file_size_ob = os.environ.get(const.MAX_FILESIZE_OB_EV)
|
107
|
-
if ev_max_file_size_ob is not None:
|
108
|
-
max_file_size_ob = float(ev_max_file_size_ob)*const.MEGABYTE
|
109
|
-
else:
|
110
|
-
max_file_size_ob = const.DEFAULT_MAX_FILE_SIZE_OB
|
111
114
|
|
112
115
|
data = [{'token': token,
|
113
116
|
'max_file_size': max_file_size,
|
@@ -143,7 +146,7 @@ def convert():
|
|
143
146
|
data=request.form,
|
144
147
|
to_format=request.form['to'],
|
145
148
|
from_format=request.form['from'],
|
146
|
-
strict=request.form['check_ext'],
|
149
|
+
strict=(request.form['check_ext'] != "false"),
|
147
150
|
log_mode=log_mode,
|
148
151
|
log_level=log_level,
|
149
152
|
delete_input=True,
|
@@ -260,3 +263,80 @@ def data():
|
|
260
263
|
else:
|
261
264
|
# return http status code 405
|
262
265
|
abort(405)
|
266
|
+
|
267
|
+
|
268
|
+
def start_app():
|
269
|
+
"""Start the Flask app - this requires being run from the base directory of the project, so this changes the
|
270
|
+
current directory to there. Anything else which changes it while the app is running may interfere with its proper
|
271
|
+
execution.
|
272
|
+
"""
|
273
|
+
|
274
|
+
os.chdir(os.path.join(psdi_data_conversion.__path__[0], ".."))
|
275
|
+
app.run()
|
276
|
+
|
277
|
+
|
278
|
+
def main():
|
279
|
+
"""Standard entry-point function for this script.
|
280
|
+
"""
|
281
|
+
|
282
|
+
parser = ArgumentParser()
|
283
|
+
|
284
|
+
parser.add_argument("--use-env-vars", action="store_true",
|
285
|
+
help="If set, all other arguments and defaults for this script are ignored, and environmental "
|
286
|
+
"variables and their defaults will instead control execution. These defaults will result in "
|
287
|
+
"the app running in production server mode.")
|
288
|
+
|
289
|
+
parser.add_argument("--max-file-size", type=float, default=const.DEFAULT_MAX_FILE_SIZE,
|
290
|
+
help="The maximum allowed filesize in MB - 0 (default) indicates no maximum")
|
291
|
+
|
292
|
+
parser.add_argument("--max-file-size-ob", type=float, default=const.DEFAULT_MAX_FILE_SIZE_OB,
|
293
|
+
help="The maximum allowed filesize in MB for the Open Babel converter, taking precendence over "
|
294
|
+
"the general maximum file size when Open Babel is used - 0 indicates no maximum. Default 1 MB.")
|
295
|
+
|
296
|
+
parser.add_argument("--service-mode", action="store_true",
|
297
|
+
help="If set, will run as if deploying a service rather than the local GUI")
|
298
|
+
|
299
|
+
parser.add_argument("--dev-mode", action="store_true",
|
300
|
+
help="If set, will expose development elements")
|
301
|
+
|
302
|
+
parser.add_argument("--log-mode", type=str, default=const.LOG_FULL,
|
303
|
+
help="How logs should be stored. Allowed values are: \n"
|
304
|
+
"- 'full' - Multi-file logging, not recommended for the CLI, but allowed for a compatible "
|
305
|
+
"interface with the public web app"
|
306
|
+
"- 'simple' - Logs saved to one file"
|
307
|
+
"- 'stdout' - Output logs and errors only to stdout"
|
308
|
+
"- 'none' - Output only errors to stdout")
|
309
|
+
|
310
|
+
parser.add_argument("--log-level", type=str, default=None,
|
311
|
+
help="The desired level to log at. Allowed values are: 'DEBUG', 'INFO', 'WARNING', 'ERROR, "
|
312
|
+
"'CRITICAL'. Default: 'INFO' for logging to file, 'WARNING' for logging to stdout")
|
313
|
+
|
314
|
+
# Set global variables for settings based on parsed arguments, unless it's set to use env vars
|
315
|
+
args = parser.parse_args()
|
316
|
+
|
317
|
+
if not args.use_env_vars:
|
318
|
+
|
319
|
+
global max_file_size
|
320
|
+
max_file_size = args.max_file_size*const.MEGABYTE
|
321
|
+
|
322
|
+
global max_file_size_ob
|
323
|
+
max_file_size_ob = args.max_file_size_ob*const.MEGABYTE
|
324
|
+
|
325
|
+
global service_mode
|
326
|
+
service_mode = args.service_mode
|
327
|
+
|
328
|
+
global production_mode
|
329
|
+
production_mode = not args.dev_mode
|
330
|
+
|
331
|
+
global log_mode
|
332
|
+
log_mode = args.log_mode
|
333
|
+
|
334
|
+
global log_level
|
335
|
+
log_level = args.log_level
|
336
|
+
|
337
|
+
start_app()
|
338
|
+
|
339
|
+
|
340
|
+
if __name__ == "__main__":
|
341
|
+
|
342
|
+
main()
|
@@ -284,9 +284,9 @@ class FileConverter:
|
|
284
284
|
if max_file_size is None:
|
285
285
|
from psdi_data_conversion.converters.openbabel import CONVERTER_OB
|
286
286
|
if self.name == CONVERTER_OB:
|
287
|
-
self.max_file_size = const.DEFAULT_MAX_FILE_SIZE_OB
|
287
|
+
self.max_file_size = const.DEFAULT_MAX_FILE_SIZE_OB
|
288
288
|
else:
|
289
|
-
self.max_file_size = const.DEFAULT_MAX_FILE_SIZE
|
289
|
+
self.max_file_size = const.DEFAULT_MAX_FILE_SIZE
|
290
290
|
else:
|
291
291
|
self.max_file_size = max_file_size*const.MEGABYTE
|
292
292
|
|
@@ -43,6 +43,8 @@
|
|
43
43
|
Python library.
|
44
44
|
</p>
|
45
45
|
|
46
|
+
<h2>Installation</h2>
|
47
|
+
|
46
48
|
<h3>Install via pip</h3>
|
47
49
|
|
48
50
|
<ul>
|
@@ -63,12 +65,6 @@
|
|
63
65
|
Python library.
|
64
66
|
</p>
|
65
67
|
|
66
|
-
<p>
|
67
|
-
If you do wish to run the local version of this webpage, you'll need to create a helper script to set up the
|
68
|
-
proper parameters and start the server. See the README provided on the front page of this project's PyPI page,
|
69
|
-
linked above, for the source of this helper script, which you can paste and use locally.
|
70
|
-
</p>
|
71
|
-
|
72
68
|
<h3>Source Code</h3>
|
73
69
|
|
74
70
|
<ul>
|
@@ -86,11 +82,28 @@
|
|
86
82
|
for other possible optional dependencies sets that can be installed.
|
87
83
|
</p>
|
88
84
|
|
89
|
-
<
|
90
|
-
|
91
|
-
|
85
|
+
<h2>Use</h2>
|
86
|
+
|
87
|
+
<p>
|
88
|
+
Once installed, the project can be used in one of three ways:
|
92
89
|
</p>
|
93
90
|
|
91
|
+
<ul>
|
92
|
+
<li><strong>Local Gui:</strong> Run the script <code class="secondary">psdi-data-convert-gui</code> to start the
|
93
|
+
server. Append the <code class="secondary">--help</code> option for to see optional arguments (generally not
|
94
|
+
required for end-users)
|
95
|
+
</li>
|
96
|
+
<li><strong>Command-Line Application:</strong> Run the script <code class="secondary">psdi-data-convert</code>
|
97
|
+
to use the application at the command-line. Append the <code class="secondary">--help</code> option to see
|
98
|
+
arguments for it, and/or find documentation in the project's README.
|
99
|
+
</li>
|
100
|
+
<li><strong>Python Library:</strong> Within a Python script, library, or terminal, the project can be imported
|
101
|
+
via <code class="secondary">import psdi_data_conversion</code>, with the most useful function being <code
|
102
|
+
class="secondary">psdi_data_conversion.converter.run_converter</code> - see the <code
|
103
|
+
class="secondary">help()</code> of this function and/or find documentation in the project's README.
|
104
|
+
</li>
|
105
|
+
</ul>
|
106
|
+
|
94
107
|
<h2>Documentation</h2>
|
95
108
|
|
96
109
|
<ul>
|
@@ -228,7 +228,7 @@ body {
|
|
228
228
|
top : 0;
|
229
229
|
left : 0;
|
230
230
|
background: var(--ifm-background-color);
|
231
|
-
z-index :
|
231
|
+
z-index : 99999;
|
232
232
|
}
|
233
233
|
|
234
234
|
select,
|
@@ -412,7 +412,8 @@ h6 {
|
|
412
412
|
}
|
413
413
|
|
414
414
|
p {
|
415
|
-
margin: 0 0 1.25rem 0;
|
415
|
+
margin : 0 0 1.25rem 0;
|
416
|
+
padding-bottom: 0;
|
416
417
|
}
|
417
418
|
|
418
419
|
.text--center {
|
@@ -546,9 +547,9 @@ a svg {
|
|
546
547
|
}
|
547
548
|
|
548
549
|
.navbar__title h5 {
|
549
|
-
display:
|
550
|
+
display: flex;
|
550
551
|
color : var(--ifm-heading-color);
|
551
|
-
margin : 0 0 0.5rem
|
552
|
+
margin : 0 0 0.5rem 1.5rem;
|
552
553
|
}
|
553
554
|
|
554
555
|
.navbar__logo img {
|
@@ -57,6 +57,11 @@
|
|
57
57
|
|
58
58
|
<form name="gui" class="gui">
|
59
59
|
<div class="max-width-box">
|
60
|
+
<p>Your one-stop shop for file format conversion, PSDI's Data Conversion Service enables users to seamlessly
|
61
|
+
convert between different file formats and assess the quality of proposed conversions. This is the web version
|
62
|
+
of our service. To find out more about Data Conversion and our other tools, click
|
63
|
+
<a href="https://resources.psdi.ac.uk/resource-themes/7bcc430a-fdc9-413e-bf32-bf163236430b"
|
64
|
+
id="more" target="_blank">here.</a></p>
|
60
65
|
<p>Select 'from' and 'to' file formats in the 'Convert from/to' boxes, in either order. Typing where indicated
|
61
66
|
filters the options (case insensitive); for example, typing 'can' or 'NON' reduces the number of options to one:
|
62
67
|
'can: Canonical SMILES.' If you change your mind about a conversion, it is advisable to click on the 'Reset'
|
@@ -118,4 +123,4 @@
|
|
118
123
|
|
119
124
|
</body>
|
120
125
|
|
121
|
-
</html>
|
126
|
+
</html>
|
@@ -6,7 +6,10 @@ Constants related to unit testing
|
|
6
6
|
|
7
7
|
import os
|
8
8
|
|
9
|
-
|
9
|
+
# Locations relative to the root directory of the project - to ensure the files are found, tests should chdir to this
|
10
|
+
# directory before searching for files
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
TEST_DATA_LOC_IN_PROJECT = "./test_data"
|
13
|
+
|
14
|
+
INPUT_TEST_DATA_LOC_IN_PROJECT = TEST_DATA_LOC_IN_PROJECT
|
15
|
+
OUTPUT_TEST_DATA_LOC_IN_PROJECT = os.path.join(TEST_DATA_LOC_IN_PROJECT, "output")
|
@@ -15,8 +15,8 @@ from tempfile import TemporaryDirectory
|
|
15
15
|
from psdi_data_conversion.constants import DATETIME_RE_RAW
|
16
16
|
from psdi_data_conversion.file_io import unpack_zip_or_tar
|
17
17
|
from psdi_data_conversion.log_utility import string_with_placeholders_matches
|
18
|
-
from psdi_data_conversion.testing.constants import
|
19
|
-
from psdi_data_conversion.testing.utils import ConversionTestInfo,
|
18
|
+
from psdi_data_conversion.testing.constants import OUTPUT_TEST_DATA_LOC_IN_PROJECT
|
19
|
+
from psdi_data_conversion.testing.utils import ConversionTestInfo, check_file_match
|
20
20
|
|
21
21
|
|
22
22
|
class MultiCallback:
|
@@ -326,7 +326,7 @@ class CheckException:
|
|
326
326
|
"""Callable class which checks an exception raised for its type, status code, and message. Tests will only be
|
327
327
|
run on tests with the python library, as that's the only route that provides exceptions."""
|
328
328
|
|
329
|
-
ex_type: type[Exception]
|
329
|
+
ex_type: type[Exception] | None = None
|
330
330
|
"""The expected type of the raised exception (subclasses of it will also be allowed)"""
|
331
331
|
|
332
332
|
ex_message: str | None = None
|
@@ -339,7 +339,8 @@ class CheckException:
|
|
339
339
|
def __call__(self, test_info: ConversionTestInfo) -> str:
|
340
340
|
"""Perform the check on the exception"""
|
341
341
|
|
342
|
-
|
342
|
+
# Skip check on CLA, since this won't catch any exceptions
|
343
|
+
if test_info.run_type == "cla":
|
343
344
|
return ""
|
344
345
|
|
345
346
|
# Confirm that an exception was indeed raised
|
@@ -350,7 +351,7 @@ class CheckException:
|
|
350
351
|
l_errors: list[str] = []
|
351
352
|
|
352
353
|
# Check the exception type
|
353
|
-
if not issubclass(exc_info.type, self.ex_type):
|
354
|
+
if self.ex_type and not issubclass(exc_info.type, self.ex_type):
|
354
355
|
l_errors.append(f"ERROR: Raised exception is of type '{exc_info.type}', but expected '{self.ex_type}'")
|
355
356
|
|
356
357
|
exc = exc_info.value
|
@@ -389,6 +390,6 @@ class MatchOutputFile:
|
|
389
390
|
def __call__(self, test_info: ConversionTestInfo):
|
390
391
|
"""Run the check comparing the two files"""
|
391
392
|
|
392
|
-
qualified_ex_output_filename = os.path.join(
|
393
|
+
qualified_ex_output_filename = os.path.join(OUTPUT_TEST_DATA_LOC_IN_PROJECT, self.ex_output_filename)
|
393
394
|
|
394
395
|
return check_file_match(test_info.qualified_out_filename, qualified_ex_output_filename)
|
@@ -22,18 +22,26 @@ from psdi_data_conversion.testing.utils import ConversionTestSpec as Spec
|
|
22
22
|
l_all_test_specs: list[Spec] = []
|
23
23
|
"""All test specs defined in this file"""
|
24
24
|
|
25
|
-
l_all_test_specs.append(Spec(name="
|
26
|
-
filename=
|
25
|
+
l_all_test_specs.append(Spec(name="Standard Single Test",
|
26
|
+
filename="standard_test.cdxml",
|
27
|
+
to_format="inchi",
|
28
|
+
callback=MCB(CheckFileStatus(),
|
29
|
+
CheckLogContentsSuccess(),
|
30
|
+
MatchOutputFile("standard_test.inchi")),
|
31
|
+
))
|
32
|
+
|
33
|
+
l_all_test_specs.append(Spec(name="Standard Multiple Tests",
|
34
|
+
filename=["1NE6.mmcif",
|
27
35
|
"hemoglobin.pdb", "aceticacid.mol", "nacl.cif",
|
28
36
|
"hemoglobin.pdb", "hemoglobin.pdb", "nacl.cif",
|
29
37
|
"hemoglobin.pdb", "hemoglobin.pdb", "nacl.cif",
|
30
38
|
"ethanol.xyz"],
|
31
|
-
to_format=["pdb",
|
39
|
+
to_format=["pdb",
|
32
40
|
"cif", "mol2", "xyz",
|
33
41
|
"cif", "xyz", "xyz",
|
34
42
|
"cif", "xyz", "xyz",
|
35
43
|
"cml"],
|
36
|
-
converter_name=[CONVERTER_OB,
|
44
|
+
converter_name=[CONVERTER_OB,
|
37
45
|
CONVERTER_OB, CONVERTER_OB, CONVERTER_OB,
|
38
46
|
CONVERTER_ATO, CONVERTER_ATO, CONVERTER_ATO,
|
39
47
|
CONVERTER_C2X, CONVERTER_C2X, CONVERTER_C2X,
|
@@ -57,12 +65,13 @@ l_all_test_specs.append(Spec(name="Archive",
|
|
57
65
|
filename=["caffeine-smi.zip",
|
58
66
|
"caffeine-smi.tar",
|
59
67
|
"caffeine-smi.tar.gz"],
|
68
|
+
conversion_kwargs={"from_format": "smi"},
|
60
69
|
to_format="inchi",
|
61
70
|
callback=archive_callback,
|
62
71
|
))
|
63
72
|
"""A test of converting a archives of files"""
|
64
73
|
|
65
|
-
l_all_test_specs.append(Spec(name="Archive (wrong format)",
|
74
|
+
l_all_test_specs.append(Spec(name="Archive (wrong format) - Library and CLA",
|
66
75
|
filename="caffeine-smi.zip",
|
67
76
|
to_format="inchi",
|
68
77
|
conversion_kwargs=[{"from_format": "pdb"},
|
@@ -71,10 +80,27 @@ l_all_test_specs.append(Spec(name="Archive (wrong format)",
|
|
71
80
|
callback=[CheckStderrContents(const.ERR_WRONG_EXTENSIONS),
|
72
81
|
CheckException(ex_type=FileConverterInputException,
|
73
82
|
ex_message=const.ERR_WRONG_EXTENSIONS)],
|
83
|
+
compatible_with_gui=False,
|
74
84
|
))
|
75
85
|
"""A test that if the user provides the wrong input format for files in an archive, and error will be output to stderr
|
76
86
|
"""
|
77
87
|
|
88
|
+
l_all_test_specs.append(Spec(name="Archive (wrong format) - GUI",
|
89
|
+
filename="caffeine-smi.zip",
|
90
|
+
to_format="inchi",
|
91
|
+
conversion_kwargs=[{"from_format": "pdb"},
|
92
|
+
{"from_format": "pdb", "strict": True}],
|
93
|
+
expect_success=[False, False],
|
94
|
+
callback=CheckException(ex_type=FileConverterInputException,
|
95
|
+
ex_message=const.ERR_WRONG_EXTENSIONS),
|
96
|
+
compatible_with_library=False,
|
97
|
+
compatible_with_cla=False,
|
98
|
+
))
|
99
|
+
"""A test that if the user provides the wrong input format for files in an archive - variant for the GUI test, which is
|
100
|
+
more strict
|
101
|
+
"""
|
102
|
+
|
103
|
+
|
78
104
|
l_all_test_specs.append(Spec(name="Log mode",
|
79
105
|
conversion_kwargs=[{"log_mode": const.LOG_NONE},
|
80
106
|
{"log_mode": const.LOG_STDOUT},
|
@@ -138,8 +164,12 @@ l_all_test_specs.append(Spec(name="Invalid Converter",
|
|
138
164
|
converter_name="INVALID",
|
139
165
|
expect_success=False,
|
140
166
|
callback=invalid_converter_callback,
|
167
|
+
compatible_with_gui=False,
|
141
168
|
))
|
142
|
-
"""A test that a proper error is returned if an invalid converter is requested
|
169
|
+
"""A test that a proper error is returned if an invalid converter is requested
|
170
|
+
|
171
|
+
Not compatible with GUI tests, since the GUI only offers valid converters to choose from
|
172
|
+
"""
|
143
173
|
|
144
174
|
quartz_quality_note_callback = CheckLogContentsSuccess(["WARNING",
|
145
175
|
const.QUAL_NOTE_OUT_MISSING.format(const.QUAL_2D_LABEL),
|
@@ -165,8 +195,12 @@ output and will be lost"""
|
|
165
195
|
l_all_test_specs.append(Spec(name="Cleanup input",
|
166
196
|
conversion_kwargs={"delete_input": True},
|
167
197
|
callback=CheckFileStatus(expect_input_exists=False),
|
198
|
+
compatible_with_gui=False,
|
168
199
|
))
|
169
|
-
"""A test that the input file to a conversion is deleted when cleanup is requested
|
200
|
+
"""A test that the input file to a conversion is deleted when cleanup is requested.
|
201
|
+
|
202
|
+
Not compatible with the GUI, since the GUI can't forcibly delete files uploaded from the user's computer
|
203
|
+
"""
|
170
204
|
|
171
205
|
l_all_test_specs.append(Spec(name="Failed conversion - bad input file",
|
172
206
|
filename=["quartz_err.xyz", "cyclopropane_err.mol"],
|
@@ -186,14 +220,29 @@ l_all_test_specs.append(Spec(name="Failed conversion - bad input file",
|
|
186
220
|
|
187
221
|
quartz_error_ob_callback = CheckLogContents(["ERROR",
|
188
222
|
"Problems reading an XYZ file: Could not read line #11, file error"])
|
189
|
-
l_all_test_specs.append(Spec(name="Errors in logs",
|
223
|
+
l_all_test_specs.append(Spec(name="Errors in logs - Library and CLA",
|
190
224
|
filename="quartz_err.xyz",
|
191
225
|
to_format="inchi",
|
192
226
|
converter_name=CONVERTER_OB,
|
193
227
|
expect_success=False,
|
194
228
|
callback=quartz_error_ob_callback,
|
229
|
+
compatible_with_gui=False,
|
230
|
+
))
|
231
|
+
"""A test that when a conversion fails in the library or CLA, logs are still produced and contain the expected error
|
232
|
+
message"""
|
233
|
+
|
234
|
+
l_all_test_specs.append(Spec(name="Errors in logs - GUI",
|
235
|
+
filename="quartz_err.xyz",
|
236
|
+
to_format="inchi",
|
237
|
+
converter_name=CONVERTER_OB,
|
238
|
+
expect_success=False,
|
239
|
+
callback=CheckException(ex_type=FileConverterAbortException,
|
240
|
+
ex_message=("Problems reading an XYZ file: Could not read line "
|
241
|
+
"#11, file error")),
|
242
|
+
compatible_with_library=False,
|
243
|
+
compatible_with_cla=False,
|
195
244
|
))
|
196
|
-
"""A test that when a conversion fails,
|
245
|
+
"""A test that when a conversion fails in the GUI, the log message is output to the alert box"""
|
197
246
|
|
198
247
|
l_all_test_specs.append(Spec(name="Failed conversion - invalid conversion",
|
199
248
|
filename=["Fapatite.ins", "nacl.mol"],
|
@@ -204,28 +253,64 @@ l_all_test_specs.append(Spec(name="Failed conversion - invalid conversion",
|
|
204
253
|
expect_log_exists=None),
|
205
254
|
CheckException(ex_type=FileConverterHelpException,
|
206
255
|
ex_message="is not supported")),
|
256
|
+
compatible_with_gui=False,
|
257
|
+
))
|
258
|
+
"""A test that a conversion that fails due an unsupported conversion will properly fail.
|
259
|
+
|
260
|
+
Not compatible with the GUI, since the GUI only offers valid conversions.
|
261
|
+
"""
|
262
|
+
|
263
|
+
l_all_test_specs.append(Spec(name="Blocked conversion - wrong input type",
|
264
|
+
filename="1NE6.mmcif",
|
265
|
+
to_format="cif",
|
266
|
+
conversion_kwargs={"from_format": "pdb", "strict": True},
|
267
|
+
expect_success=False,
|
268
|
+
callback=MCB(CheckFileStatus(expect_output_exists=False,
|
269
|
+
expect_log_exists=None),
|
270
|
+
CheckException(ex_type=FileConverterInputException,
|
271
|
+
ex_message=("The file extension is not {} or a zip or tar "
|
272
|
+
"archive extension"))),
|
273
|
+
compatible_with_library=False,
|
274
|
+
compatible_with_cla=False,
|
207
275
|
))
|
208
|
-
"""A test that a conversion
|
276
|
+
"""A test that a conversion which is blocked in the GUI"""
|
209
277
|
|
210
|
-
l_all_test_specs.append(Spec(name="Failed
|
278
|
+
l_all_test_specs.append(Spec(name="Failed conversion - wrong input type",
|
211
279
|
filename="1NE6.mmcif",
|
212
280
|
to_format="cif",
|
213
|
-
conversion_kwargs={"from_format": "pdb"},
|
281
|
+
conversion_kwargs={"from_format": "pdb", "strict": False},
|
214
282
|
expect_success=False,
|
215
283
|
callback=MCB(CheckFileStatus(expect_output_exists=False,
|
216
|
-
|
284
|
+
expect_log_exists=None),
|
217
285
|
CheckException(ex_type=FileConverterAbortException,
|
218
|
-
ex_message="not a valid {} file")),
|
286
|
+
ex_message=("not a valid {} file"))),
|
219
287
|
))
|
220
288
|
"""A test that a conversion which fails due to the wrong input file type will properly fail"""
|
221
289
|
|
222
|
-
l_all_test_specs.append(Spec(name="Large files",
|
290
|
+
l_all_test_specs.append(Spec(name="Large files - Library and CLA",
|
223
291
|
filename=["ch3cl-esp.cub", "benzyne.molden", "periodic_dmol3.outmol",
|
224
292
|
"fullRhinovirus.pdb"],
|
225
293
|
to_format=["cdjson", "dmol", "mol", "cif"],
|
226
294
|
converter_name=[CONVERTER_OB, CONVERTER_OB, CONVERTER_OB, CONVERTER_C2X],
|
227
295
|
callback=CheckFileStatus(),
|
296
|
+
compatible_with_gui=False,
|
297
|
+
))
|
298
|
+
"""Test that the library and CLA can process large files properly"""
|
299
|
+
|
300
|
+
l_all_test_specs.append(Spec(name="Large files - GUI",
|
301
|
+
filename=["ch3cl-esp.cub", "benzyne.molden",
|
302
|
+
"periodic_dmol3.outmol", "fullRhinovirus.pdb"],
|
303
|
+
to_format=["cdjson", "dmol", "mol", "cif"],
|
304
|
+
converter_name=[CONVERTER_OB, CONVERTER_OB, CONVERTER_OB, CONVERTER_C2X],
|
305
|
+
expect_success=[False, False, False, True],
|
306
|
+
callback=[CheckException(ex_type=FileConverterInputException),
|
307
|
+
CheckException(ex_type=FileConverterInputException),
|
308
|
+
CheckException(ex_type=FileConverterInputException),
|
309
|
+
CheckFileStatus()],
|
310
|
+
compatible_with_library=False,
|
311
|
+
compatible_with_cla=False,
|
228
312
|
))
|
313
|
+
"""Test that the GUI will refuse to process large files with OB, but will with other converters"""
|
229
314
|
|
230
315
|
max_size_callback = MCB(CheckFileStatus(expect_output_exists=False),
|
231
316
|
CheckLogContents("file exceeds maximum size"),
|
@@ -239,12 +324,16 @@ l_all_test_specs.append(Spec(name="Max size exceeded",
|
|
239
324
|
expect_success=False,
|
240
325
|
callback=max_size_callback,
|
241
326
|
compatible_with_cla=False,
|
327
|
+
compatible_with_gui=False,
|
242
328
|
))
|
243
329
|
"""A set of test conversion that the maximum size constraint is properly applied. In the first test, the input file
|
244
330
|
will be greater than the maximum size, and the test should fail as soon as it checks it. In the second test, the input
|
245
331
|
archive is smaller than the maximum size, but the unpacked files in it are greater, so it should fail midway through.
|
246
332
|
|
247
333
|
Not compatible with CLA tests, since the CLA doesn't allow the imposition of a maximum size.
|
334
|
+
|
335
|
+
Not compatible with GUI tests in current setup of test implementation, which doesn't let us set env vars to control
|
336
|
+
things like maximum size on a per-test basis. May be possible to set up in the future though
|
248
337
|
"""
|
249
338
|
|
250
339
|
|
@@ -289,11 +378,11 @@ l_all_test_specs.append(Spec(name="Coord gen",
|
|
289
378
|
"""A set of tests which checks that coordinate generation options are processed correctly, by matching tests using them
|
290
379
|
to expected output files"""
|
291
380
|
|
292
|
-
l_library_test_specs = [x for x in l_all_test_specs if x.compatible_with_library]
|
381
|
+
l_library_test_specs = [x for x in l_all_test_specs if x.compatible_with_library and not x.skip_all]
|
293
382
|
"""All test specs which are compatible with being run on the Python library"""
|
294
383
|
|
295
|
-
l_cla_test_specs = [x for x in l_all_test_specs if x.compatible_with_cla]
|
384
|
+
l_cla_test_specs = [x for x in l_all_test_specs if x.compatible_with_cla and not x.skip_all]
|
296
385
|
"""All test specs which are compatible with being run on the command-line application"""
|
297
386
|
|
298
|
-
l_gui_test_specs = [x for x in l_all_test_specs if x.compatible_with_gui]
|
387
|
+
l_gui_test_specs = [x for x in l_all_test_specs if x.compatible_with_gui and not x.skip_all]
|
299
388
|
"""All test specs which are compatible with being run on the GUI"""
|