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.
@@ -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*const.MEGABYTE
287
+ self.max_file_size = const.DEFAULT_MAX_FILE_SIZE_OB
288
288
  else:
289
- self.max_file_size = const.DEFAULT_MAX_FILE_SIZE*const.MEGABYTE
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
- <p>When installed in this manner, the helper script to run the local webpage is provided in the root directory
90
- of the repository as <code class="secondary">run_local.sh</code>. It can be run from this directory, copied to
91
- your <code class="secondary">$PATH</code>, or aliased as desired.
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 : 9999;
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: unset;
550
+ display: flex;
550
551
  color : var(--ifm-heading-color);
551
- margin : 0 0 0.5rem 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
- TEST_DATA_LOC = os.path.abspath("./test_data")
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
- INPUT_TEST_DATA_LOC = TEST_DATA_LOC
12
- OUTPUT_TEST_DATA_LOC = os.path.join(TEST_DATA_LOC, "output")
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 OUTPUT_TEST_DATA_LOC
19
- from psdi_data_conversion.testing.utils import ConversionTestInfo, LibraryConversionTestInfo, check_file_match
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
- if not isinstance(test_info, LibraryConversionTestInfo):
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(OUTPUT_TEST_DATA_LOC, self.ex_output_filename)
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="Basic",
26
- filename=["1NE6.mmcif", "standard_test.cdxml",
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", "inchi",
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, 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, logs are still produced and contain the expected error message"""
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 that fails due an unsupported conversion will properly fail"""
276
+ """A test that a conversion which is blocked in the GUI"""
209
277
 
210
- l_all_test_specs.append(Spec(name="Failed Conversion - wrong input type",
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
- expect_log_exists=None),
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"""