psdi-data-conversion 0.0.33__py3-none-any.whl → 0.0.36__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 +23 -3
- psdi_data_conversion/constants.py +2 -0
- psdi_data_conversion/converter.py +16 -6
- psdi_data_conversion/converters/atomsk.py +3 -1
- psdi_data_conversion/converters/base.py +99 -39
- psdi_data_conversion/converters/c2x.py +3 -1
- psdi_data_conversion/converters/openbabel.py +40 -1
- psdi_data_conversion/database.py +5 -0
- psdi_data_conversion/main.py +18 -10
- psdi_data_conversion/static/content/accessibility.htm +5 -5
- psdi_data_conversion/static/content/convert.htm +31 -15
- psdi_data_conversion/static/content/convertato.htm +46 -28
- psdi_data_conversion/static/content/convertc2x.htm +47 -28
- psdi_data_conversion/static/content/documentation.htm +4 -4
- psdi_data_conversion/static/content/download.htm +4 -1
- psdi_data_conversion/static/content/feedback.htm +4 -4
- psdi_data_conversion/static/content/index-versions/psdi-common-header.html +1 -1
- psdi_data_conversion/static/content/psdi-common-header.html +1 -1
- psdi_data_conversion/static/content/report.htm +9 -7
- psdi_data_conversion/static/javascript/common.js +20 -0
- psdi_data_conversion/static/javascript/convert.js +1 -2
- psdi_data_conversion/static/javascript/convert_common.js +100 -7
- psdi_data_conversion/static/javascript/convertato.js +1 -2
- psdi_data_conversion/static/javascript/convertc2x.js +1 -2
- psdi_data_conversion/static/javascript/format.js +12 -0
- psdi_data_conversion/static/javascript/report.js +6 -0
- psdi_data_conversion/static/styles/format.css +13 -0
- psdi_data_conversion/static/styles/psdi-common.css +5 -2
- psdi_data_conversion/templates/index.htm +4 -1
- psdi_data_conversion/testing/conversion_test_specs.py +240 -149
- psdi_data_conversion/testing/utils.py +22 -7
- {psdi_data_conversion-0.0.33.dist-info → psdi_data_conversion-0.0.36.dist-info}/METADATA +29 -6
- {psdi_data_conversion-0.0.33.dist-info → psdi_data_conversion-0.0.36.dist-info}/RECORD +36 -36
- {psdi_data_conversion-0.0.33.dist-info → psdi_data_conversion-0.0.36.dist-info}/WHEEL +0 -0
- {psdi_data_conversion-0.0.33.dist-info → psdi_data_conversion-0.0.36.dist-info}/entry_points.txt +0 -0
- {psdi_data_conversion-0.0.33.dist-info → psdi_data_conversion-0.0.36.dist-info}/licenses/LICENSE +0 -0
@@ -15,194 +15,285 @@ from psdi_data_conversion.converters.openbabel import CONVERTER_OB, COORD_GEN_KE
|
|
15
15
|
from psdi_data_conversion.testing.conversion_callbacks import (CheckArchiveContents, CheckException, CheckLogContents,
|
16
16
|
CheckLogContentsSuccess, CheckFileStatus,
|
17
17
|
CheckStderrContents, CheckStdoutContents,
|
18
|
-
MatchOutputFile, MultiCallback)
|
19
|
-
from psdi_data_conversion.testing.utils import ConversionTestSpec
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
"""
|
18
|
+
MatchOutputFile, MultiCallback as MCB)
|
19
|
+
from psdi_data_conversion.testing.utils import ConversionTestSpec as Spec
|
20
|
+
|
21
|
+
|
22
|
+
l_all_test_specs: list[Spec] = []
|
23
|
+
"""All test specs defined in this file"""
|
24
|
+
|
25
|
+
l_all_test_specs.append(Spec(name="Basic",
|
26
|
+
filename=["1NE6.mmcif", "standard_test.cdxml",
|
27
|
+
"hemoglobin.pdb", "aceticacid.mol", "nacl.cif",
|
28
|
+
"hemoglobin.pdb", "hemoglobin.pdb", "nacl.cif",
|
29
|
+
"hemoglobin.pdb", "hemoglobin.pdb", "nacl.cif",
|
30
|
+
"ethanol.xyz"],
|
31
|
+
to_format=["pdb", "inchi",
|
32
|
+
"cif", "mol2", "xyz",
|
33
|
+
"cif", "xyz", "xyz",
|
34
|
+
"cif", "xyz", "xyz",
|
35
|
+
"cml"],
|
36
|
+
converter_name=[CONVERTER_OB, CONVERTER_OB,
|
37
|
+
CONVERTER_OB, CONVERTER_OB, CONVERTER_OB,
|
38
|
+
CONVERTER_ATO, CONVERTER_ATO, CONVERTER_ATO,
|
39
|
+
CONVERTER_C2X, CONVERTER_C2X, CONVERTER_C2X,
|
40
|
+
CONVERTER_OB],
|
41
|
+
callback=MCB(CheckFileStatus(),
|
42
|
+
CheckLogContentsSuccess()),
|
43
|
+
))
|
44
|
+
"""A basic set of test conversions which we expect to succeed without issue, running conversions with each of the
|
35
45
|
Open Babel, Atomsk, and c2x converters"""
|
36
46
|
|
37
|
-
archive_callback =
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
archive_callback = MCB(CheckFileStatus(),
|
48
|
+
CheckArchiveContents(l_filename_bases=["caffeine-no-flags",
|
49
|
+
"caffeine-ia",
|
50
|
+
"caffeine-ia-ox",
|
51
|
+
"caffeine-ia-okx",
|
52
|
+
"caffeine-ia-okx-oof4",
|
53
|
+
"caffeine-ia-okx-oof4l5",],
|
54
|
+
to_format="inchi"))
|
55
|
+
|
56
|
+
l_all_test_specs.append(Spec(name="Archive",
|
57
|
+
filename=["caffeine-smi.zip",
|
58
|
+
"caffeine-smi.tar",
|
59
|
+
"caffeine-smi.tar.gz"],
|
60
|
+
to_format="inchi",
|
61
|
+
callback=archive_callback,
|
62
|
+
))
|
50
63
|
"""A test of converting a archives of files"""
|
51
64
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
65
|
+
l_all_test_specs.append(Spec(name="Archive (wrong format)",
|
66
|
+
filename="caffeine-smi.zip",
|
67
|
+
to_format="inchi",
|
68
|
+
conversion_kwargs=[{"from_format": "pdb"},
|
69
|
+
{"from_format": "pdb", "strict": True}],
|
70
|
+
expect_success=[True, False],
|
71
|
+
callback=[CheckStderrContents(const.ERR_WRONG_EXTENSIONS),
|
72
|
+
CheckException(ex_type=FileConverterInputException,
|
73
|
+
ex_message=const.ERR_WRONG_EXTENSIONS)],
|
74
|
+
))
|
61
75
|
"""A test that if the user provides the wrong input format for files in an archive, and error will be output to stderr
|
62
76
|
"""
|
63
77
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
78
|
+
l_all_test_specs.append(Spec(name="Log mode",
|
79
|
+
conversion_kwargs=[{"log_mode": const.LOG_NONE},
|
80
|
+
{"log_mode": const.LOG_STDOUT},
|
81
|
+
{"log_mode": const.LOG_SIMPLE},
|
82
|
+
{"log_mode": const.LOG_FULL},
|
83
|
+
{"log_mode": const.LOG_FULL_FORCE},],
|
84
|
+
callback=[CheckFileStatus(expect_log_exists=False,
|
85
|
+
expect_global_log_exists=False),
|
86
|
+
CheckFileStatus(expect_log_exists=False,
|
87
|
+
expect_global_log_exists=False),
|
88
|
+
CheckFileStatus(expect_log_exists=True,
|
89
|
+
expect_global_log_exists=False),
|
90
|
+
CheckFileStatus(expect_log_exists=True,
|
91
|
+
expect_global_log_exists=True),
|
92
|
+
CheckFileStatus(expect_log_exists=True,
|
93
|
+
expect_global_log_exists=True)],
|
94
|
+
compatible_with_gui=False,
|
95
|
+
))
|
80
96
|
"""Tests that the different log modes have the desired effects on logs
|
81
97
|
|
82
|
-
|
98
|
+
Not compatible with GUI tests, since the GUI requires the log mode to always be "Full"
|
83
99
|
"""
|
84
100
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
101
|
+
l_all_test_specs.append(Spec(name="Stdout",
|
102
|
+
conversion_kwargs={"log_mode": const.LOG_STDOUT},
|
103
|
+
callback=CheckStdoutContents(l_strings_to_exclude=["ERROR", "exception",
|
104
|
+
"Exception"],
|
105
|
+
l_regex_to_find=[r"File name:\s*nacl",
|
106
|
+
const.DATETIME_RE_RAW]
|
107
|
+
),
|
108
|
+
compatible_with_gui=False,
|
109
|
+
))
|
90
110
|
"""Test that the log is output to stdout when requested
|
91
111
|
|
92
|
-
|
112
|
+
Not compatible with GUI tests, since the GUI requires the log mode to always be "Full"
|
93
113
|
"""
|
94
114
|
|
95
|
-
|
96
|
-
|
115
|
+
l_all_test_specs.append(Spec(name="Quiet",
|
116
|
+
conversion_kwargs={"log_mode": const.LOG_NONE},
|
117
|
+
callback=CheckStdoutContents(l_regex_to_exclude=r"."),
|
118
|
+
compatible_with_gui=False,
|
119
|
+
))
|
97
120
|
"""Test that nothing is output to stdout when quiet mode is enabled
|
98
121
|
|
99
|
-
|
122
|
+
Not compatible with GUI tests, since the GUI doesn't support quiet mode
|
100
123
|
"""
|
101
124
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
125
|
+
l_all_test_specs.append(Spec(name="Open Babel Warning",
|
126
|
+
filename="1NE6.mmcif",
|
127
|
+
to_format="pdb",
|
128
|
+
callback=CheckLogContentsSuccess(["Open Babel Warning",
|
129
|
+
"Failed to kekulize aromatic bonds",])
|
130
|
+
))
|
107
131
|
"""A test that confirms expected warnings form Open Babel are output and captured in the log"""
|
108
132
|
|
109
|
-
invalid_converter_callback =
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
133
|
+
invalid_converter_callback = MCB(CheckFileStatus(expect_output_exists=False,
|
134
|
+
expect_log_exists=False),
|
135
|
+
CheckException(ex_type=FileConverterInputException,
|
136
|
+
ex_message="Converter {} not recognized"))
|
137
|
+
l_all_test_specs.append(Spec(name="Invalid Converter",
|
138
|
+
converter_name="INVALID",
|
139
|
+
expect_success=False,
|
140
|
+
callback=invalid_converter_callback,
|
141
|
+
))
|
116
142
|
"""A test that a proper error is returned if an invalid converter is requested"""
|
117
143
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
144
|
+
quartz_quality_note_callback = CheckLogContentsSuccess(["WARNING",
|
145
|
+
const.QUAL_NOTE_OUT_MISSING.format(const.QUAL_2D_LABEL),
|
146
|
+
const.QUAL_NOTE_OUT_MISSING.format(const.QUAL_3D_LABEL),
|
147
|
+
const.QUAL_NOTE_IN_MISSING.format(const.QUAL_CONN_LABEL)])
|
148
|
+
ethanol_quality_note_callback = CheckLogContentsSuccess(["WARNING",
|
149
|
+
"Potential data loss or extrapolation",
|
150
|
+
const.QUAL_NOTE_IN_MISSING.format(const.QUAL_CONN_LABEL)])
|
151
|
+
hemoglobin_quality_note_callback = CheckLogContentsSuccess(["WARNING",
|
152
|
+
"Potential data loss or extrapolation",
|
153
|
+
const.QUAL_NOTE_OUT_MISSING.format(const.QUAL_CONN_LABEL)])
|
154
|
+
l_all_test_specs.append(Spec(name="Quality note",
|
155
|
+
filename=["quartz.xyz", "ethanol.xyz", "hemoglobin.pdb"],
|
156
|
+
to_format=["inchi", "cml", "xyz"],
|
157
|
+
callback=[quartz_quality_note_callback,
|
158
|
+
ethanol_quality_note_callback,
|
159
|
+
hemoglobin_quality_note_callback],
|
160
|
+
))
|
125
161
|
"""A test conversion which we expect to produce a warning for conversion quality issues, where the connections property
|
126
162
|
isn't present in the input and has to be extrapolated, and the 2D and 3D coordinates properties aren't present in the
|
127
163
|
output and will be lost"""
|
128
164
|
|
129
|
-
|
130
|
-
|
165
|
+
l_all_test_specs.append(Spec(name="Cleanup input",
|
166
|
+
conversion_kwargs={"delete_input": True},
|
167
|
+
callback=CheckFileStatus(expect_input_exists=False),
|
168
|
+
))
|
131
169
|
"""A test that the input file to a conversion is deleted when cleanup is requested"""
|
132
170
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
"
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
171
|
+
l_all_test_specs.append(Spec(name="Failed conversion - bad input file",
|
172
|
+
filename=["quartz_err.xyz", "cyclopropane_err.mol"],
|
173
|
+
to_format=["inchi", "xyz"],
|
174
|
+
expect_success=False,
|
175
|
+
converter_name=[CONVERTER_OB, CONVERTER_C2X],
|
176
|
+
callback=[MCB(CheckFileStatus(expect_output_exists=False,
|
177
|
+
expect_log_exists=None),
|
178
|
+
CheckException(ex_type=FileConverterAbortException,
|
179
|
+
ex_message="Problems reading an XYZ file")),
|
180
|
+
MCB(CheckFileStatus(expect_output_exists=False,
|
181
|
+
expect_log_exists=None),
|
182
|
+
CheckException(ex_type=FileConverterAbortException,
|
183
|
+
ex_message="Aborting: mol file contains no atoms"))],
|
184
|
+
))
|
185
|
+
"""A test that a conversion that fails due to an unreadable input file will properly fail"""
|
186
|
+
|
187
|
+
quartz_error_ob_callback = CheckLogContents(["ERROR",
|
188
|
+
"Problems reading an XYZ file: Could not read line #11, file error"])
|
189
|
+
l_all_test_specs.append(Spec(name="Errors in logs",
|
190
|
+
filename="quartz_err.xyz",
|
191
|
+
to_format="inchi",
|
192
|
+
converter_name=CONVERTER_OB,
|
193
|
+
expect_success=False,
|
194
|
+
callback=quartz_error_ob_callback,
|
195
|
+
))
|
196
|
+
"""A test that when a conversion fails, logs are still produced and contain the expected error message"""
|
197
|
+
|
198
|
+
l_all_test_specs.append(Spec(name="Failed conversion - invalid conversion",
|
199
|
+
filename=["Fapatite.ins", "nacl.mol"],
|
200
|
+
to_format=["cml", "xyz"],
|
201
|
+
expect_success=False,
|
202
|
+
converter_name=[CONVERTER_OB, CONVERTER_ATO],
|
203
|
+
callback=MCB(CheckFileStatus(expect_output_exists=False,
|
204
|
+
expect_log_exists=None),
|
205
|
+
CheckException(ex_type=FileConverterHelpException,
|
206
|
+
ex_message="is not supported")),
|
207
|
+
))
|
208
|
+
"""A test that a conversion that fails due an unsupported conversion will properly fail"""
|
209
|
+
|
210
|
+
l_all_test_specs.append(Spec(name="Failed Conversion - wrong input type",
|
211
|
+
filename="1NE6.mmcif",
|
212
|
+
to_format="cif",
|
213
|
+
conversion_kwargs={"from_format": "pdb"},
|
214
|
+
expect_success=False,
|
215
|
+
callback=MCB(CheckFileStatus(expect_output_exists=False,
|
216
|
+
expect_log_exists=None),
|
217
|
+
CheckException(ex_type=FileConverterAbortException,
|
218
|
+
ex_message="not a valid {} file")),
|
219
|
+
))
|
220
|
+
"""A test that a conversion which fails due to the wrong input file type will properly fail"""
|
221
|
+
|
222
|
+
l_all_test_specs.append(Spec(name="Large files",
|
223
|
+
filename=["ch3cl-esp.cub", "benzyne.molden", "periodic_dmol3.outmol",
|
224
|
+
"fullRhinovirus.pdb"],
|
225
|
+
to_format=["cdjson", "dmol", "mol", "cif"],
|
226
|
+
converter_name=[CONVERTER_OB, CONVERTER_OB, CONVERTER_OB, CONVERTER_C2X],
|
227
|
+
callback=CheckFileStatus(),
|
228
|
+
))
|
229
|
+
|
230
|
+
max_size_callback = MCB(CheckFileStatus(expect_output_exists=False),
|
231
|
+
CheckLogContents("file exceeds maximum size"),
|
232
|
+
CheckException(ex_type=FileConverterSizeException,
|
233
|
+
ex_message="exceeds maximum size",
|
234
|
+
ex_status_code=const.STATUS_CODE_SIZE))
|
235
|
+
l_all_test_specs.append(Spec(name="Max size exceeded",
|
236
|
+
filename=["1NE6.mmcif", "caffeine-smi.tar.gz"],
|
237
|
+
to_format="pdb",
|
238
|
+
conversion_kwargs=[{"max_file_size": 0.0001}, {"max_file_size": 0.0005}],
|
239
|
+
expect_success=False,
|
240
|
+
callback=max_size_callback,
|
241
|
+
compatible_with_cla=False,
|
242
|
+
))
|
163
243
|
"""A set of test conversion that the maximum size constraint is properly applied. In the first test, the input file
|
164
244
|
will be greater than the maximum size, and the test should fail as soon as it checks it. In the second test, the input
|
165
245
|
archive is smaller than the maximum size, but the unpacked files in it are greater, so it should fail midway through.
|
166
246
|
|
167
|
-
|
247
|
+
Not compatible with CLA tests, since the CLA doesn't allow the imposition of a maximum size.
|
168
248
|
"""
|
169
249
|
|
170
250
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
251
|
+
l_all_test_specs.append(Spec(name="Format args",
|
252
|
+
filename="caffeine.inchi",
|
253
|
+
to_format="smi",
|
254
|
+
conversion_kwargs=[{},
|
255
|
+
{"data": {"from_flags": "a"}},
|
256
|
+
{"data": {"from_flags": "a", "to_flags": "x"}},
|
257
|
+
{"data": {"from_flags": "a", "to_flags": "kx"}},
|
258
|
+
{"data": {"from_flags": "a", "to_flags": "kx",
|
259
|
+
"to_options": "f4"}},
|
260
|
+
{"data": {"from_flags": "a", "to_flags": "kx",
|
261
|
+
"to_options": "f4 l5"}}
|
262
|
+
],
|
263
|
+
callback=[MatchOutputFile("caffeine.smi"),
|
264
|
+
MatchOutputFile("caffeine_a_in.smi"),
|
265
|
+
MatchOutputFile("caffeine_a_in_x_out.smi"),
|
266
|
+
MatchOutputFile("caffeine_a_in_kx_out.smi"),
|
267
|
+
MatchOutputFile("caffeine_a_in_kx_f4_out.smi"),
|
268
|
+
MatchOutputFile("caffeine_a_in_kx_f4_l5_out.smi")
|
269
|
+
]
|
270
|
+
))
|
190
271
|
"""A set of tests which checks that format args (for how to read from and write to specific file formats) are processed
|
191
272
|
correctly, by matching tests using them to expected output files"""
|
192
273
|
|
193
274
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
275
|
+
l_all_test_specs.append(Spec(name="Coord gen",
|
276
|
+
filename="caffeine.inchi",
|
277
|
+
to_format="xyz",
|
278
|
+
conversion_kwargs=[{},
|
279
|
+
{"data": {COORD_GEN_KEY: "Gen2D",
|
280
|
+
COORD_GEN_QUAL_KEY: "fastest"}},
|
281
|
+
{"data": {COORD_GEN_KEY: "Gen3D",
|
282
|
+
COORD_GEN_QUAL_KEY: "best"}}
|
283
|
+
],
|
284
|
+
callback=[MatchOutputFile("caffeine.xyz"),
|
285
|
+
MatchOutputFile("caffeine-2D-fastest.xyz"),
|
286
|
+
MatchOutputFile("caffeine-3D-best.xyz"),
|
287
|
+
]
|
288
|
+
))
|
207
289
|
"""A set of tests which checks that coordinate generation options are processed correctly, by matching tests using them
|
208
290
|
to expected output files"""
|
291
|
+
|
292
|
+
l_library_test_specs = [x for x in l_all_test_specs if x.compatible_with_library]
|
293
|
+
"""All test specs which are compatible with being run on the Python library"""
|
294
|
+
|
295
|
+
l_cla_test_specs = [x for x in l_all_test_specs if x.compatible_with_cla]
|
296
|
+
"""All test specs which are compatible with being run on the command-line application"""
|
297
|
+
|
298
|
+
l_gui_test_specs = [x for x in l_all_test_specs if x.compatible_with_gui]
|
299
|
+
"""All test specs which are compatible with being run on the GUI"""
|
@@ -102,13 +102,16 @@ class ConversionTestSpec:
|
|
102
102
|
(as if using zip on the multiple lists) to test each element in turn.
|
103
103
|
"""
|
104
104
|
|
105
|
+
name: str
|
106
|
+
"""The name of this test specification"""
|
107
|
+
|
105
108
|
filename: str | Iterable[str] = "nacl.cif"
|
106
109
|
"""The name of the input file, relative to the input test data location, or a list thereof"""
|
107
110
|
|
108
111
|
to_format: str | Iterable[str] = "pdb"
|
109
112
|
"""The format to test converting the input file to, or a list thereof"""
|
110
113
|
|
111
|
-
|
114
|
+
converter_name: str | Iterable[str] = CONVERTER_DEFAULT
|
112
115
|
"""The name of the converter to be used for the test, or a list thereof"""
|
113
116
|
|
114
117
|
conversion_kwargs: dict[str, Any] | Iterable[dict[str, Any]] = field(default_factory=dict)
|
@@ -124,6 +127,15 @@ class ConversionTestSpec:
|
|
124
127
|
should take as its only argument a `ConversionTestInfo` and return a string. The string should be empty if the check
|
125
128
|
is passed and should explain the failure otherwise."""
|
126
129
|
|
130
|
+
compatible_with_library: bool = True
|
131
|
+
"""Whether or not this test spec is compatible with being run through the Python library, default True"""
|
132
|
+
|
133
|
+
compatible_with_cla: bool = True
|
134
|
+
"""Whether or not this test spec is compatible with being run through the command-line application, default True"""
|
135
|
+
|
136
|
+
compatible_with_gui: bool = True
|
137
|
+
"""Whether or not this test spec is compatible with being run through the GUI, default True"""
|
138
|
+
|
127
139
|
def __post_init__(self):
|
128
140
|
"""Regularize the lengths of all attribute lists, in case some were provided as single values and others as
|
129
141
|
lists, and set up initial values
|
@@ -131,7 +143,10 @@ class ConversionTestSpec:
|
|
131
143
|
|
132
144
|
# To ease maintainability, we get the list of this class's attributes automatically from its __dict__, excluding
|
133
145
|
# any which start with an underscore
|
134
|
-
self._l_attr_names: list[str] = [attr_name for attr_name in self.__dict__ if
|
146
|
+
self._l_attr_names: list[str] = [attr_name for attr_name in self.__dict__ if
|
147
|
+
not (attr_name.startswith("_") or
|
148
|
+
attr_name == "name" or
|
149
|
+
attr_name.startswith("compatible"))]
|
135
150
|
|
136
151
|
l_single_val_attrs = []
|
137
152
|
self._len: int = 1
|
@@ -196,7 +211,7 @@ class SingleConversionTestSpec:
|
|
196
211
|
to_format: str
|
197
212
|
"""The format to test converting the input file to"""
|
198
213
|
|
199
|
-
|
214
|
+
converter_name: str | Iterable[str] = CONVERTER_DEFAULT
|
200
215
|
"""The name of the converter to be used for the test"""
|
201
216
|
|
202
217
|
conversion_kwargs: dict[str, Any] = field(default_factory=dict)
|
@@ -279,7 +294,7 @@ def _run_single_test_conversion_with_library(test_spec: SingleConversionTestSpec
|
|
279
294
|
if test_spec.expect_success:
|
280
295
|
run_converter(filename=qualified_in_filename,
|
281
296
|
to_format=test_spec.to_format,
|
282
|
-
name=test_spec.
|
297
|
+
name=test_spec.converter_name,
|
283
298
|
upload_dir=input_dir,
|
284
299
|
download_dir=output_dir,
|
285
300
|
**test_spec.conversion_kwargs)
|
@@ -288,7 +303,7 @@ def _run_single_test_conversion_with_library(test_spec: SingleConversionTestSpec
|
|
288
303
|
with pytest.raises(Exception) as exc_info:
|
289
304
|
run_converter(filename=qualified_in_filename,
|
290
305
|
to_format=test_spec.to_format,
|
291
|
-
name=test_spec.
|
306
|
+
name=test_spec.converter_name,
|
292
307
|
upload_dir=input_dir,
|
293
308
|
download_dir=output_dir,
|
294
309
|
**test_spec.conversion_kwargs)
|
@@ -359,7 +374,7 @@ def _run_single_test_conversion_with_cla(test_spec: SingleConversionTestSpec,
|
|
359
374
|
if test_spec.expect_success:
|
360
375
|
run_converter_through_cla(filename=qualified_in_filename,
|
361
376
|
to_format=test_spec.to_format,
|
362
|
-
name=test_spec.
|
377
|
+
name=test_spec.converter_name,
|
363
378
|
input_dir=input_dir,
|
364
379
|
output_dir=output_dir,
|
365
380
|
log_file=os.path.join(output_dir, test_spec.log_filename),
|
@@ -369,7 +384,7 @@ def _run_single_test_conversion_with_cla(test_spec: SingleConversionTestSpec,
|
|
369
384
|
with pytest.raises(SystemExit) as exc_info:
|
370
385
|
run_converter_through_cla(filename=qualified_in_filename,
|
371
386
|
to_format=test_spec.to_format,
|
372
|
-
name=test_spec.
|
387
|
+
name=test_spec.converter_name,
|
373
388
|
input_dir=input_dir,
|
374
389
|
output_dir=output_dir,
|
375
390
|
log_file=os.path.join(output_dir, test_spec.log_filename),
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: psdi_data_conversion
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.36
|
4
4
|
Summary: Chemistry file format conversion service, provided by PSDI
|
5
5
|
Project-URL: Homepage, https://data-conversion.psdi.ac.uk/
|
6
6
|
Project-URL: Documentation, https://psdi-uk.github.io/psdi-data-conversion/
|
@@ -403,13 +403,21 @@ In addition to the dependencies listed above, this project uses the assets made
|
|
403
403
|
|
404
404
|
### Installation
|
405
405
|
|
406
|
-
The CLA and Python library are installed together. This
|
406
|
+
The CLA and Python library are installed together. This project is available on PyPI, and so can be installed via pip with:
|
407
|
+
|
408
|
+
```bash
|
409
|
+
pip install psdi-data-conversion
|
410
|
+
```
|
411
|
+
|
412
|
+
If you wish to install from source, this can be done most easily by cloning the project and then executing:
|
407
413
|
|
408
414
|
```bash
|
409
415
|
pip install .
|
410
416
|
```
|
411
417
|
|
412
|
-
|
418
|
+
from this project's directory. You can also replace the '.' in this command with the path to this project's directory to install it from elsewhere.
|
419
|
+
|
420
|
+
**Note:** This project uses git to determine the version number. If you clone the repository, you won't have to do anything special here, but if you get the source e.g. by extracting a release archive, you'll have to do one additional step before running the command above. If you have git installed, simply run `git init` in the project directory and it will be able to install. Otherwise, edit the project's `pyproject.toml` file to uncomment the line that sets a fixed version, and comment out the lines that set it up to determine the version from git - these are pointed out in the comments there.
|
413
421
|
|
414
422
|
Depending on your system, it may not be possible to install packages in this manner without creating a virtual environment to do so in. You can do this by first installing the `venv` module for Python3 with e.g.:
|
415
423
|
|
@@ -572,15 +580,23 @@ Enter https://data-conversion.psdi.ac.uk/ in a browser. Guidance on usage is giv
|
|
572
580
|
|
573
581
|
### Installation and Setup
|
574
582
|
|
575
|
-
|
583
|
+
This project is available on PyPI, and so can be installed via pip, including the necessary dependencies for the GUI, with:
|
584
|
+
|
585
|
+
```bash
|
586
|
+
pip install psdi-data-conversion'[gui]'
|
587
|
+
```
|
588
|
+
|
589
|
+
If you wish to install the project locally from source, this can be done most easily by cloning the project and then executing:
|
576
590
|
|
577
591
|
```bash
|
578
592
|
pip install .'[gui]'
|
579
593
|
```
|
580
594
|
|
581
|
-
If
|
595
|
+
**Note:** This project uses git to determine the version number. If you clone the repository, you won't have to do anything special here, but if you get the source e.g. by extracting a release archive, you'll have to do one additional step before running the command above. If you have git installed, simply run `git init` in the project directory and it will be able to install. Otherwise, edit the project's `pyproject.toml` file to uncomment the line that sets a fixed version, and comment out the lines that set it up to determine the version from git - these are pointed out in the comments there.
|
582
596
|
|
583
|
-
If
|
597
|
+
If your system does not allow installation in this manner, it may be necessary to set up a virtual environment. See the instructions in the [command-line application installation](#installation) section above for how to do that, and then try to install again once you've set one up and activated it.
|
598
|
+
|
599
|
+
If you've installed this repository from source, you can use the provided `run_local.sh` bash script to run the application. Otherwise (e.g. if you've installed from a wheel or PyPI), copy and paste the following into a script:
|
584
600
|
|
585
601
|
```bash
|
586
602
|
#!/bin/bash
|
@@ -590,6 +606,13 @@ if [ -z $MAX_FILESIZE ]; then
|
|
590
606
|
export MAX_FILESIZE=0
|
591
607
|
fi
|
592
608
|
|
609
|
+
# The envvar MAX_FILESIZE_OB can be used to set the maximum allowed filesize in MB for the Open Babel converter - 0
|
610
|
+
# indicates no maximum. This is currently set to 1 MB by default as the converter seems to hang above this limit (not
|
611
|
+
# even allowing the process to be cancelled). This can be changed in the future if this is patched
|
612
|
+
if [ -z $MAX_FILESIZE_OB ]; then
|
613
|
+
export MAX_FILESIZE_OB=1
|
614
|
+
fi
|
615
|
+
|
593
616
|
# Logging control - "full" sets server-style logging, which is necessary to produce the output logs with the expected
|
594
617
|
# names. This should not be changed, or else errors will occur
|
595
618
|
export LOG_MODE=full
|