psdi-data-conversion 0.0.38__py3-none-any.whl → 0.1.0__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.
Files changed (31) hide show
  1. psdi_data_conversion/app.py +93 -33
  2. psdi_data_conversion/constants.py +1 -0
  3. psdi_data_conversion/converter.py +145 -17
  4. psdi_data_conversion/converters/base.py +24 -20
  5. psdi_data_conversion/converters/c2x.py +13 -0
  6. psdi_data_conversion/converters/openbabel.py +2 -1
  7. psdi_data_conversion/database.py +46 -14
  8. psdi_data_conversion/dist.py +2 -1
  9. psdi_data_conversion/file_io.py +1 -2
  10. psdi_data_conversion/log_utility.py +1 -1
  11. psdi_data_conversion/main.py +32 -25
  12. psdi_data_conversion/static/content/index-versions/psdi-common-footer.html +13 -9
  13. psdi_data_conversion/static/content/index-versions/psdi-common-header.html +1 -1
  14. psdi_data_conversion/static/content/psdi-common-footer.html +13 -9
  15. psdi_data_conversion/static/content/psdi-common-header.html +1 -1
  16. psdi_data_conversion/static/data/data.json +617 -3
  17. psdi_data_conversion/static/javascript/convert.js +54 -6
  18. psdi_data_conversion/static/javascript/convert_common.js +16 -2
  19. psdi_data_conversion/static/javascript/data.js +18 -0
  20. psdi_data_conversion/static/styles/format.css +7 -0
  21. psdi_data_conversion/templates/index.htm +8 -9
  22. psdi_data_conversion/testing/conversion_callbacks.py +2 -2
  23. psdi_data_conversion/testing/conversion_test_specs.py +27 -7
  24. psdi_data_conversion/testing/gui.py +18 -12
  25. psdi_data_conversion/testing/utils.py +3 -3
  26. psdi_data_conversion/utils.py +21 -0
  27. {psdi_data_conversion-0.0.38.dist-info → psdi_data_conversion-0.1.0.dist-info}/METADATA +2 -2
  28. {psdi_data_conversion-0.0.38.dist-info → psdi_data_conversion-0.1.0.dist-info}/RECORD +31 -30
  29. {psdi_data_conversion-0.0.38.dist-info → psdi_data_conversion-0.1.0.dist-info}/WHEEL +0 -0
  30. {psdi_data_conversion-0.0.38.dist-info → psdi_data_conversion-0.1.0.dist-info}/entry_points.txt +0 -0
  31. {psdi_data_conversion-0.0.38.dist-info → psdi_data_conversion-0.1.0.dist-info}/licenses/LICENSE +0 -0
@@ -7,7 +7,9 @@
7
7
 
8
8
 
9
9
  import { getInputFlags, getOutputFlags, getInputArgFlags, getOutputArgFlags } from "./data.js";
10
- import { commonConvertReady, convertFile, getExtCheck, splitArchiveExt, isArchiveExt } from "./convert_common.js"
10
+ import {
11
+ SAFE_CHAR_REGEX, commonConvertReady, convertFile, getExtCheck, splitArchiveExt, isArchiveExt
12
+ } from "./convert_common.js"
11
13
 
12
14
  var token = "",
13
15
  in_ext = "",
@@ -51,8 +53,24 @@ function enterArgument(event) {
51
53
  }
52
54
  }
53
55
 
56
+
57
+ /**
58
+ * Validate the input for a format option - if invalid, display the error message, if valid, hide it
59
+ *
60
+ * @param {*} event
61
+ */
62
+ function validateInput(event) {
63
+ var err_id = this.id.replace('text', 'err')
64
+ if (this.validity.patternMismatch) {
65
+ $('#' + err_id).css({ display: "block" })
66
+ } else {
67
+ $('#' + err_id).css({ display: "none" })
68
+ }
69
+ }
70
+
54
71
  // Uploads a user-supplied file
55
72
  function submitFile() {
73
+
56
74
  const file = $("#fileToUpload")[0].files[0],
57
75
  [fname, ext] = splitArchiveExt(file.name);
58
76
 
@@ -78,9 +96,16 @@ function submitFile() {
78
96
  const checked_in = $('input[name=in_arg_check]:checked'),
79
97
  checked_out = $('input[name=out_arg_check]:checked');
80
98
 
99
+ let security_passed = true;
100
+
81
101
  checked_in.each(function () {
82
102
  read_arg_flags += $("#" + this.id).val()[0];
83
- const arg = $("#in_arg_text" + this.id.substring(this.id.length - 1, this.id.length)).val();
103
+ const e = $("#in_arg_text" + this.id.substring(this.id.length - 1, this.id.length));
104
+ const arg = e.val();
105
+
106
+ if (e[0].validity.patternMismatch) {
107
+ security_passed = false;
108
+ }
84
109
 
85
110
  if (/\S/.test(arg)) {
86
111
  read_args += arg.trim() + '£';
@@ -92,7 +117,12 @@ function submitFile() {
92
117
 
93
118
  checked_out.each(function () {
94
119
  write_arg_flags += $("#" + this.id).val()[0];
95
- const arg = $("#out_arg_text" + this.id.substring(this.id.length - 1, this.id.length)).val();
120
+ const e = $("#out_arg_text" + this.id.substring(this.id.length - 1, this.id.length));
121
+ const arg = e.val();
122
+
123
+ if (e[0].validity.patternMismatch) {
124
+ security_passed = false;
125
+ }
96
126
 
97
127
  if (/\S/.test(arg)) {
98
128
  write_args += arg.trim() + '£';
@@ -102,9 +132,21 @@ function submitFile() {
102
132
  }
103
133
  })
104
134
 
135
+ let alert_msg = '';
136
+
137
+ if (!security_passed) {
138
+ alert_msg += 'ERROR: One or more ticked options contains invalid characters. They must match the regex /' +
139
+ SAFE_CHAR_REGEX + '/ .\n';
140
+ }
141
+
105
142
  if (!all_args_entered) {
106
- alert('All ticked option flags need additional information to be entered into the associated text box.');
107
- return;
143
+ alert_msg += 'ERROR: All ticked options need additional information to be entered into the associated ' +
144
+ 'text box.\n';
145
+ }
146
+
147
+ if (alert_msg) {
148
+ alert(alert_msg);
149
+ return
108
150
  }
109
151
 
110
152
  const coordinates = $('input[name="coordinates"]:checked').val(),
@@ -216,11 +258,17 @@ function addCheckboxes(argFlags, type) {
216
258
  <tr>
217
259
  <td><input type='checkbox' id="${type}_check${flagCount}" name=${type}_check value="${flag}"></input></td>
218
260
  <td><label for="${type}_check${flagCount}">${flag} [${brief}]: ${description}<label></td>
219
- <td><input type='text' id=${type}_text${flagCount} placeholder='-- type info. here --'></input></td>
261
+ <td><input type='text' id="${type}_text${flagCount}" placeholder='-- type info. here --'
262
+ pattern='` + SAFE_CHAR_REGEX + `'></input>
263
+ <p class="init-hidden" id="${type}_err${flagCount}"><strong>ERROR:</strong> Input contains
264
+ invalid characters; it must match the regex
265
+ <code class="secondary">/` + SAFE_CHAR_REGEX + `/</code></p>
266
+ </td>
220
267
  <td><span id= ${type}_label${flagCount}>${furtherInfo}</span></td>
221
268
  </tr>`);
222
269
 
223
270
  $(`#${type}_text${flagCount}`).hide();
271
+ $(`#${type}_text${flagCount}`).on('input', validateInput);
224
272
  $(`#${type}_label${flagCount}`).hide();
225
273
  $(`#${type}_check${flagCount}`).change(enterArgument);
226
274
 
@@ -18,6 +18,20 @@ const TARGZ_EXT = "tar.gz"
18
18
  const TARBZ_EXT = "tar.bz"
19
19
  const TARXZ_EXT = "tar.xz"
20
20
 
21
+ // Short list of safe allowed characters:
22
+ // \w: All letters and digits
23
+ // \s: All whitespace characters
24
+ // .: Period
25
+ // \-: Hyphen
26
+ // :: Colon
27
+ // +: Plus symbol
28
+ // *: Asterisk
29
+ // =: Equals sign
30
+ // $: Dollar sign
31
+ // /: Forward-slash
32
+ // \\: Backslash
33
+ export const SAFE_CHAR_REGEX = "[\\w\\s.\\-:+*=$\\/\\\\]*"
34
+
21
35
  // Whether or not file extensions will be checked
22
36
  let extCheck = true;
23
37
 
@@ -271,10 +285,10 @@ function checkFile(event) {
271
285
  }
272
286
 
273
287
  /**
274
- * Allow the file upload to only accept the expected type of file
288
+ * Allow the file upload to only accept the expected type of file, plus archives
275
289
  */
276
290
  function limitFileType() {
277
- $("#fileToUpload")[0].accept = "." + in_ext;
291
+ $("#fileToUpload")[0].accept = "." + in_ext + ", .zip, .tar, .tar.gz, .tar.xz, .tar.bz";
278
292
  }
279
293
 
280
294
  /**
@@ -63,6 +63,24 @@ export async function getOutputFormats() {
63
63
  return outFormats.sort((a, b) => compare([a.extension, b.extension], [a.note, b.note]))
64
64
  }
65
65
 
66
+ /**
67
+ * Gets the ID for a format, given its extension and note
68
+ *
69
+ * @param {string} extension - The extension of the format, e.g. 'pdb'
70
+ * @param {string} note - The note of the format, e.g. 'Protein Databank'
71
+ * @returns {(int|null)} - The ID of the format if found, or else null
72
+ */
73
+ export async function getFormatId(extension, note) {
74
+
75
+ var format = (data.formats.filter(format => (format.extension === extension) && (format.note === note)));
76
+
77
+ if (format === undefined) {
78
+ return null;
79
+ }
80
+
81
+ return format[0].id;
82
+ }
83
+
66
84
  export async function getOutputFormatsForInputFormat(inExtension, inNote) {
67
85
 
68
86
  const inputFormat = (data.formats.filter(format => (format.extension === inExtension) && (format.note === inNote)))[0];
@@ -44,6 +44,13 @@ form {
44
44
  }
45
45
  }
46
46
 
47
+ /* Invalid input fields switch to alternate background */
48
+
49
+ input:invalid {
50
+ background-color: var(--ifm-color-primary);
51
+ color : var(--ifm-hero-text-color);
52
+ }
53
+
47
54
  /* Converter details, user input and file conversion initially not displayed. */
48
55
  .init-hidden {
49
56
  display: none
@@ -20,13 +20,12 @@
20
20
  crossorigin="anonymous"></script>
21
21
  <script src="https://cdn.jsdelivr.net/jquery.dirtyforms/2.0.0/jquery.dirtyforms.min.js"></script>
22
22
 
23
- {% for item in data %}
24
23
  <script>
25
- const token = "{{item.token}}";
26
- const max_file_size = "{{item.max_file_size}}";
27
- const max_file_size_ob = "{{item.max_file_size_ob}}";
28
- const service_mode = "{{item.service_mode}}";
29
- const production_mode = "{{item.production_mode}}";
24
+ const token = "{{token}}";
25
+ const max_file_size = "{{max_file_size}}";
26
+ const max_file_size_ob = "{{max_file_size_ob}}";
27
+ const service_mode = "{{service_mode}}";
28
+ const production_mode = "{{production_mode}}";
30
29
  document.documentElement.setAttribute("service-mode", service_mode);
31
30
  document.documentElement.setAttribute("production-mode", production_mode);
32
31
  </script>
@@ -121,11 +120,11 @@
121
120
  <div class="medGap"></div>
122
121
  </div>
123
122
  </form>
124
-
123
+ {% if sha %}
125
124
  <div class="secondary prod-only">
126
- <div class="max-width-box">SHA: {{item.sha}}</div>
125
+ <div class="max-width-box">SHA: {{ sha }}</div>
127
126
  </div>
128
- {% endfor %}
127
+ {% endif %}
129
128
  <script src="{{url_for('static', filename='/javascript/format.js')}}" type="module" language="JavaScript"></script>
130
129
 
131
130
  <footer class="footer" id="psdi-footer"></footer>
@@ -6,10 +6,10 @@ conversion test, run with the functions and classes defined in the `utils.py` mo
6
6
  """
7
7
 
8
8
  import abc
9
- from collections.abc import Callable, Iterable
10
- from dataclasses import dataclass, field
11
9
  import os
12
10
  import re
11
+ from collections.abc import Callable, Iterable
12
+ from dataclasses import dataclass, field
13
13
  from tempfile import TemporaryDirectory
14
14
 
15
15
  from psdi_data_conversion.constants import DATETIME_RE_RAW
@@ -13,10 +13,11 @@ from psdi_data_conversion.converters.base import (FileConverterAbortException, F
13
13
  from psdi_data_conversion.converters.c2x import CONVERTER_C2X
14
14
  from psdi_data_conversion.converters.openbabel import CONVERTER_OB, COORD_GEN_KEY, COORD_GEN_QUAL_KEY
15
15
  from psdi_data_conversion.database import FileConverterDatabaseException
16
- from psdi_data_conversion.testing.conversion_callbacks import (CheckArchiveContents, CheckException, CheckLogContents,
17
- CheckLogContentsSuccess, CheckFileStatus,
16
+ from psdi_data_conversion.testing.conversion_callbacks import (CheckArchiveContents, CheckException, CheckFileStatus,
17
+ CheckLogContents, CheckLogContentsSuccess,
18
18
  CheckStderrContents, CheckStdoutContents,
19
- MatchOutputFile, MultiCallback as MCB)
19
+ MatchOutputFile)
20
+ from psdi_data_conversion.testing.conversion_callbacks import MultiCallback as MCB
20
21
  from psdi_data_conversion.testing.utils import ConversionTestSpec as Spec
21
22
 
22
23
  l_all_test_specs: list[Spec] = []
@@ -29,7 +30,9 @@ l_all_test_specs.append(Spec(name="Standard Single Test",
29
30
  CheckLogContentsSuccess(),
30
31
  MatchOutputFile("standard_test.inchi")),
31
32
  ))
33
+ """A quick single test, functioning mostly as a smoke test for things going right in the simplest case"""
32
34
 
35
+ simple_success_callback = MCB(CheckFileStatus(), CheckLogContentsSuccess())
33
36
  l_all_test_specs.append(Spec(name="Standard Multiple Tests",
34
37
  filename=["1NE6.mmcif",
35
38
  "hemoglobin.pdb", "aceticacid.mol", "nacl.cif",
@@ -39,7 +42,7 @@ l_all_test_specs.append(Spec(name="Standard Multiple Tests",
39
42
  to_format=["pdb-0",
40
43
  "cif", "mol2", "xyz",
41
44
  "cif", "xyz", "xyz",
42
- "cif", "xyz", "xyz",
45
+ "cif", "xyz-0", "xyz-0",
43
46
  "cml"],
44
47
  from_format=[None,
45
48
  None, None, None,
@@ -51,12 +54,29 @@ l_all_test_specs.append(Spec(name="Standard Multiple Tests",
51
54
  CONVERTER_ATO, CONVERTER_ATO, CONVERTER_ATO,
52
55
  CONVERTER_C2X, CONVERTER_C2X, CONVERTER_C2X,
53
56
  CONVERTER_OB],
54
- callback=MCB(CheckFileStatus(),
55
- CheckLogContentsSuccess()),
57
+ callback=simple_success_callback,
56
58
  ))
57
59
  """A basic set of test conversions which we expect to succeed without issue, running conversions with each of the
58
60
  Open Babel, Atomsk, and c2x converters"""
59
61
 
62
+ l_all_test_specs.append(Spec(name="c2x Formats Tests",
63
+ to_format=["res", "abi", "POSCAR", "cml"],
64
+ converter_name=CONVERTER_C2X,
65
+ callback=simple_success_callback,
66
+ compatible_with_gui=False,
67
+ ))
68
+ """Test converting with c2x to a few different formats which require special input. This test isn't run in the GUI
69
+ solely to save on resources, since there are unlikely to be an GUI-specific issues raised by this test that aren't
70
+ caught in others."""
71
+
72
+ l_all_test_specs.append(Spec(name="Converter Name Sensitivity Tests",
73
+ converter_name=["open babel", "oPeNbaBEL", "C2X", "atomsk"],
74
+ to_format="xyz-0",
75
+ callback=simple_success_callback,
76
+ compatible_with_gui=False,
77
+ ))
78
+ """Tests that converters can be specified case- and space-insensitively in the library and CLI"""
79
+
60
80
  archive_callback = MCB(CheckFileStatus(),
61
81
  CheckArchiveContents(l_filename_bases=["caffeine-no-flags",
62
82
  "caffeine-ia",
@@ -209,7 +229,7 @@ Not compatible with the GUI, since the GUI can't forcibly delete files uploaded
209
229
 
210
230
  l_all_test_specs.append(Spec(name="Failed conversion - bad input file",
211
231
  filename=["quartz_err.xyz", "cyclopropane_err.mol"],
212
- to_format=["inchi", "xyz"],
232
+ to_format=["inchi", "xyz-0"],
213
233
  from_format=[None, "mol-0"],
214
234
  expect_success=False,
215
235
  converter_name=[CONVERTER_OB, CONVERTER_C2X],
@@ -6,10 +6,10 @@ Utilities to aid in testing of the GUI
6
6
 
7
7
  import os
8
8
  import shutil
9
- from tempfile import TemporaryDirectory
10
-
11
9
  import time
12
10
  from dataclasses import dataclass
11
+ from tempfile import TemporaryDirectory
12
+
13
13
  import pytest
14
14
  from selenium.common.exceptions import TimeoutException
15
15
  from selenium.webdriver.common.alert import Alert
@@ -45,6 +45,11 @@ def wait_and_find_element(root: WebDriver | EC.WebElement, xpath: str, by=By.XPA
45
45
  return root.find_element(by, xpath)
46
46
 
47
47
 
48
+ def wait_for_cover_hidden(root: WebDriver):
49
+ """Wait until the page cover is removed"""
50
+ WebDriverWait(root, TIMEOUT).until(EC.invisibility_of_element((By.XPATH, "//div[@id='cover']")))
51
+
52
+
48
53
  @dataclass
49
54
  class GuiTestSpecRunner():
50
55
  """Class which provides an interface to run test conversions through the GUI
@@ -253,25 +258,30 @@ class GuiSingleTestSpecRunner:
253
258
  4. Click the "Yes" button to confirm and go to the convert page
254
259
  """
255
260
 
256
- # Get the homepage
261
+ # Get the homepage and wait for the cover to be removed
257
262
  self.driver.get(f"{self.origin}/")
263
+ wait_for_cover_hidden(self.driver)
258
264
 
259
265
  wait_for_element(self.driver, "//select[@id='fromList']/option")
260
266
 
261
267
  # Select from_format from the 'from' list.
268
+ full_from_format = f"{self._from_format_info.name}: {self._from_format_info.note}"
262
269
  self.driver.find_element(
263
- By.XPATH, f"//select[@id='fromList']/option[starts-with(.,'{self._from_format_info.name}:')]").click()
270
+ By.XPATH, f"//select[@id='fromList']/option[starts-with(.,'{full_from_format}')]").click()
264
271
 
265
272
  # Select to_format from the 'to' list.
273
+ full_to_format = f"{self._to_format_info.name}: {self._to_format_info.note}"
266
274
  self.driver.find_element(
267
- By.XPATH, f"//select[@id='toList']/option[starts-with(.,'{self._to_format_info.name}:')]").click()
275
+ By.XPATH, f"//select[@id='toList']/option[starts-with(.,'{full_to_format}')]").click()
268
276
 
269
277
  # Select converter from the available conversion options list.
270
278
  self.driver.find_element(
271
279
  By.XPATH, f"//select[@id='success']/option[contains(.,'{self.single_test_spec.converter_name}')]").click()
272
280
 
273
- # Click on the "Yes" button to accept the converter and go to the conversion page
281
+ # Click on the "Yes" button to accept the converter and go to the conversion page, and wait for the cover to be
282
+ # removed there
274
283
  self.driver.find_element(By.XPATH, "//input[@id='yesButton']").click()
284
+ wait_for_cover_hidden(self.driver)
275
285
 
276
286
  def _set_conversion_settings(self):
277
287
  """Set settings on the convert page appropriately for the desired conversion
@@ -315,13 +325,11 @@ class GuiSingleTestSpecRunner:
315
325
  continue
316
326
  flags_select = Select(wait_and_find_element(self.driver, f"//select[@id='{select_id}']"))
317
327
  for flag in l_flags:
318
- found = False
319
328
  for option in flags_select.options:
320
329
  if option.text.startswith(f"{flag}:"):
321
330
  flags_select.select_by_visible_text(option.text)
322
- found = True
323
331
  break
324
- if not found:
332
+ else:
325
333
  raise ValueError(f"Flag {flag} was not found in {select_id} selection box for conversion from "
326
334
  f"{self._from_format_info.name} to {self._to_format_info.name} with "
327
335
  f"converter {self.single_test_spec.converter_name}")
@@ -343,7 +351,6 @@ class GuiSingleTestSpecRunner:
343
351
 
344
352
  # Look for and set each option
345
353
  for option in l_options:
346
- found = False
347
354
  for row in l_rows:
348
355
  l_items = row.find_elements(By.XPATH, "./td")
349
356
  label = l_items[1]
@@ -357,10 +364,9 @@ class GuiSingleTestSpecRunner:
357
364
  input_box = wait_and_find_element(l_items[2], "./input")
358
365
  input_box.send_keys(option[1:])
359
366
 
360
- found = True
361
367
  break
362
368
 
363
- if not found:
369
+ else:
364
370
  raise ValueError(f"Option {option} was not found in {table_id} options table for conversion from "
365
371
  f"{self._from_format_info.name} to {self._to_format_info.name} with "
366
372
  f"converter {self.single_test_spec.converter_name}")
@@ -6,12 +6,12 @@ This module defines general classes and methods used for unit tests.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
- from dataclasses import dataclass, field
10
- from collections.abc import Callable, Iterable
11
- from math import isclose
12
9
  import os
13
10
  import shlex
14
11
  import sys
12
+ from collections.abc import Callable, Iterable
13
+ from dataclasses import dataclass, field
14
+ from math import isclose
15
15
  from tempfile import TemporaryDirectory
16
16
  from typing import Any
17
17
  from unittest.mock import patch
@@ -0,0 +1,21 @@
1
+ """
2
+ # utils.py
3
+
4
+ Miscellaneous utility functions used by this project
5
+ """
6
+
7
+
8
+ def regularize_name(name: str):
9
+ """Regularizes a name for comparisons, making it lowercase and stripping spaces
10
+
11
+ Parameters
12
+ ----------
13
+ name : str
14
+ The name, e.g. "Open Babel"
15
+
16
+ Returns
17
+ -------
18
+ str
19
+ The regularized name, e.g. "openbabel"
20
+ """
21
+ return name.lower().replace(" ", "")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: psdi_data_conversion
3
- Version: 0.0.38
3
+ Version: 0.1.0
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/
@@ -243,7 +243,7 @@ Description-Content-Type: text/markdown
243
243
 
244
244
  # PSDI Data Conversion
245
245
 
246
- Version: Pre-release 2024-04-14
246
+ Release date: 2024-04-29
247
247
 
248
248
  This is the repository for the PSDI PF2 Chemistry File Format Conversion project. The goal of this project is to provide utilities to assist in converting files between the many different file formats used in chemistry, providing information on what converters are available for a given conversion and the expected quality of it, and providing multiple interfaces to perform these conversions. These interfaces are:
249
249
 
@@ -1,13 +1,14 @@
1
1
  psdi_data_conversion/__init__.py,sha256=urMsTqsTHTch1q4rMT9dgGnrvdPFMP9B8r-6Kr8H5sE,404
2
- psdi_data_conversion/app.py,sha256=Ef8gXALojMrHaEWp1VJqEJ9CqYPWnXKFyObzlorNy9A,13253
3
- psdi_data_conversion/constants.py,sha256=JWYC2gXsEi6bBl_NdEBh5nLZ7qX2LZZV_DutfEHJ8qo,7390
4
- psdi_data_conversion/converter.py,sha256=wgh13gzkzouEyEg1cXZ8KfIUXerXFF8VU-a4WgSO9ZE,23185
5
- psdi_data_conversion/database.py,sha256=CmV-yPBMa1Y9Uq_6h_C_dgIq9yi-qRvZCXlnLHNfxd4,55170
6
- psdi_data_conversion/dist.py,sha256=Ju6BcEuLrB738diTbK6HX6ZBiZ40Ctq1exj44nSCMlE,2292
7
- psdi_data_conversion/file_io.py,sha256=UXxNxTl_EabQ96UrLp4b38ctkYhXV_KIHJeTuyRBVpM,8857
8
- psdi_data_conversion/log_utility.py,sha256=WIgQp0pMsFtJJZKgIhStBNnjLzC6gEIodQAoXji5ht0,8789
9
- psdi_data_conversion/main.py,sha256=LBGTj2K_tx_YSPe-9I2biN0XEUpEiCnqhHa0kox0kHU,41791
2
+ psdi_data_conversion/app.py,sha256=DCY5TLLYdCj-r9GH-SKXvwtWm9AcQJ0SJbCsefl3K94,15738
3
+ psdi_data_conversion/constants.py,sha256=Hq2OVbcSkcv6T87-YJlo1PVlr9ILlB4H3E9JYjzvCF4,7423
4
+ psdi_data_conversion/converter.py,sha256=Y77mqH2OKxf2YelphWDl82AKoRa-APle-l3e8wG_WZA,27315
5
+ psdi_data_conversion/database.py,sha256=XzKvtT-cFmKLWLo5OBB5CV_rGHuqEEuENNyZnbS39qE,56419
6
+ psdi_data_conversion/dist.py,sha256=LOcKEP7H7JA9teX1m-5awuBi69gmdhtUit7yxtCTOZ8,2293
7
+ psdi_data_conversion/file_io.py,sha256=LvdPmnYL_7Xlcr-7LJjUbbky4gKiqTTvPRzdbtvQaJo,8794
8
+ psdi_data_conversion/log_utility.py,sha256=CHAq-JvBnTKaE0SHK5hM5j2dTbfSli4iUc3hsf6dBhc,8789
9
+ psdi_data_conversion/main.py,sha256=9Gu3CxbUfMuDxyNBx_-kQwWB4eOTWRHGmxCsVnpdbvs,42421
10
10
  psdi_data_conversion/security.py,sha256=wjdrMre29TpkF2NqrsXJ5sschSAnDzqLYTLUcNR21Qw,902
11
+ psdi_data_conversion/utils.py,sha256=iTjNfrD4n_hU9h20ldYrX2Bmp5KhCBIeMSUMLtPZ_8k,402
11
12
  psdi_data_conversion/bin/LICENSE_ATOMSK,sha256=-Ay6SFTAf9x-OaRAiOgMNoutfUMLHx5jQQA1HqZ6p7I,34886
12
13
  psdi_data_conversion/bin/LICENSE_C2X,sha256=-Ay6SFTAf9x-OaRAiOgMNoutfUMLHx5jQQA1HqZ6p7I,34886
13
14
  psdi_data_conversion/bin/linux/atomsk,sha256=GDsG1MlEvmk_XPspadzEzuil6N775iewDvNZS6rWJWk,34104032
@@ -16,9 +17,9 @@ psdi_data_conversion/bin/mac/atomsk,sha256=pqExRdkR8NSqSasHZjE74R_CiM6Dkr_yvfyak
16
17
  psdi_data_conversion/bin/mac/c2x,sha256=dI-bBoQ6uqc6KMYKJaq0x7ejJgOf_wysTxQA5BrF8AY,2581960
17
18
  psdi_data_conversion/converters/__init__.py,sha256=15Ldt06eyZ0bgNPB4qg419U0Zcjt6TUCTzjCBo8EIzM,210
18
19
  psdi_data_conversion/converters/atomsk.py,sha256=_V33me1e4HW0-YXvdE-z6PdwtSK2gYV6QZf5d8aPqH4,1523
19
- psdi_data_conversion/converters/base.py,sha256=K6Zwfj6VHC_aEnuflqjGf0xF5kX24v_smTAQiyE0pzs,35892
20
- psdi_data_conversion/converters/c2x.py,sha256=9eSg85-FEhZ4Xj_yEAmbmq75Zg8woaplSfvDygZVbb0,1539
21
- psdi_data_conversion/converters/openbabel.py,sha256=Y0PN5BwlZaekUrt8dM6IuEtrvpmXYgvwnkLFlENDNoE,13223
20
+ psdi_data_conversion/converters/base.py,sha256=gYZ-2f693_YBgJdlXFUZOpjVhB8PAbkbLFkOS9BFg9Q,36022
21
+ psdi_data_conversion/converters/c2x.py,sha256=jDA84H8Jpz--ajTWNWX6K6oMfOMMbMxkA31-VnGi0gU,2019
22
+ psdi_data_conversion/converters/openbabel.py,sha256=OYppOMfnvxmVgRY5vUkcVokWn-bQSSeG8MOFqN1MCIY,13224
22
23
  psdi_data_conversion/scripts/atomsk.sh,sha256=N_NMO5q8sI3Lt1TerC-xcKbMI0kfscAudy5UAbY0uR0,804
23
24
  psdi_data_conversion/scripts/c2x.sh,sha256=F48jhgtgouKKZDQ9p6tCCNBN5bPuidBq2GcTurdWzQc,770
24
25
  psdi_data_conversion/static/content/accessibility.htm,sha256=5mzlPM-d5KBoOuvuBTmer5QEI9lWQSd7FPH1KFn_7B0,14187
@@ -29,13 +30,13 @@ psdi_data_conversion/static/content/documentation.htm,sha256=1GiEjlDCP0kJ3CKkx3l
29
30
  psdi_data_conversion/static/content/download.htm,sha256=DQKWEuq_Bjv2TyV6DnPXnHrSOBvGYRHOU-m6YOwfsh4,4727
30
31
  psdi_data_conversion/static/content/feedback.htm,sha256=fZrhn4Egs9g6ygqPzV6ZG9ndYK02VdALNVNXRsZ716k,1788
31
32
  psdi_data_conversion/static/content/header-links.html,sha256=7B2bHa7dLfSZ4hPMvVJ3kR0niVAOO3FtHJo0K6m1oP4,693
32
- psdi_data_conversion/static/content/psdi-common-footer.html,sha256=CM9F6AXM1LVMLvTP51xTzOicEelSXlyXQyN-BjrQAJk,3933
33
- psdi_data_conversion/static/content/psdi-common-header.html,sha256=vRAgLGKE_RhXgBUQnarxnpkGl9j2Qeedqqo3VNDVGdk,1825
33
+ psdi_data_conversion/static/content/psdi-common-footer.html,sha256=3_KqTtwtkvCvi52LcRrN7oVfMfFdHqrHc39gMrYzGxg,4070
34
+ psdi_data_conversion/static/content/psdi-common-header.html,sha256=2upXPOZ-EM6Bv7ltPJnynPBjYz4Z27sNl4LuUaVdVjM,1815
34
35
  psdi_data_conversion/static/content/report.htm,sha256=CRwlF7a7QvAjHsajuehWOtLxbo-JAjqrS_Q-I4BWxzs,4549
35
36
  psdi_data_conversion/static/content/index-versions/header-links.html,sha256=WN9oZL7hLtH_yv5PvX3Ky7_YGrNvQL_RQ5eU8DB50Rg,764
36
- psdi_data_conversion/static/content/index-versions/psdi-common-footer.html,sha256=zzizo_YEPhvH3_jNPFkFoKZA0TnIG6EXzQOsgooU1K8,3989
37
- psdi_data_conversion/static/content/index-versions/psdi-common-header.html,sha256=IXmvdlArY-60b7HgvKjcNF3eSmEmTImX7Hdasswyi5s,1907
38
- psdi_data_conversion/static/data/data.json,sha256=_3o3BFEmnWGhoGMaviJsu-U9dJnk_tH9Wf0g-eDVWuU,3630027
37
+ psdi_data_conversion/static/content/index-versions/psdi-common-footer.html,sha256=APBMI9c5-4fNV-CCYEs9ySgAahc7u1w-0e3EjM1MiD8,4126
38
+ psdi_data_conversion/static/content/index-versions/psdi-common-header.html,sha256=w6Q_uu0W4MdioVoh6w0Cy4m2ACr7xAnampx1TfPvT9M,1897
39
+ psdi_data_conversion/static/data/data.json,sha256=1nljosxtwbLRfIIIa6-GHJnhvzhB759oEGvVQ18QP_4,3647095
39
40
  psdi_data_conversion/static/img/colormode-toggle-dm.svg,sha256=Q85ODwU67chZ77lyT9gITtnmqzJEycFmz35dJuqaPXE,502
40
41
  psdi_data_conversion/static/img/colormode-toggle-lm.svg,sha256=sIKXsNmLIXU4fSuuqrN0r-J4Hd3NIqoiXNT3mdq5-Fo,1155
41
42
  psdi_data_conversion/static/img/psdi-icon-dark.svg,sha256=-hYXxegsw67i0qqAOYCx-I-ZPyG04wG0aBVTKoZQlL0,69747
@@ -62,26 +63,26 @@ psdi_data_conversion/static/img/ukri-logo-darktext.png,sha256=3UgghERAmFdnre0Ffc
62
63
  psdi_data_conversion/static/img/ukri-logo-lighttext.png,sha256=ptIQwIGGdVsO2rTximo9QjtJFH9DpkJcAs1glwKFjwo,25579
63
64
  psdi_data_conversion/static/javascript/accessibility.js,sha256=kbnWHeBNPrTLrnYRjMEUmiOcCXM2bORYIRfzUB03TAE,7208
64
65
  psdi_data_conversion/static/javascript/common.js,sha256=3YZdwfq54OPl-xIImTwjbXqxKqlrAaEbeac0cAHvScU,1720
65
- psdi_data_conversion/static/javascript/convert.js,sha256=UfrqaO7VNiLeed-d92O_jpKXRa63-0tCb_e-rqjTdFM,9074
66
- psdi_data_conversion/static/javascript/convert_common.js,sha256=o4KHIlYToC3AfOa8MTzbPaNDjPEesyvUy50AVgTRxvI,11000
66
+ psdi_data_conversion/static/javascript/convert.js,sha256=xWd0V9wyPD6t2ltTbaAQqqnvneU6_VEdMhVyg7UUo6c,10453
67
+ psdi_data_conversion/static/javascript/convert_common.js,sha256=nr0UTAPv2hahqCjl_JzxoOAtsyKIsk6qDXO6cItmChg,11369
67
68
  psdi_data_conversion/static/javascript/convertato.js,sha256=faSvfm9HWT3i8piqEDq8OfekiPo3jCV2vKT_VjdzwmE,3555
68
69
  psdi_data_conversion/static/javascript/convertc2x.js,sha256=TTqC9B2FD_q3RcPE2GJh6yAhocQyJLRfQsbSWzm2g3U,3550
69
- psdi_data_conversion/static/javascript/data.js,sha256=JNJLzMLyC6ke2vDzK-dgeMH2Z4LmB6R3DQ4ykMzjnK0,6376
70
+ psdi_data_conversion/static/javascript/data.js,sha256=ZM5PkPqiq8aUaB0ARWLK4TVSuxJKAFAAxlF1-7BsJ1g,6915
70
71
  psdi_data_conversion/static/javascript/format.js,sha256=S-ovNuqOSfS-RYDhFxxCDpTKFKdxOWAYvJuzeEPcXB0,21260
71
72
  psdi_data_conversion/static/javascript/load_accessibility.js,sha256=jTLfmubEmko2bJ_MKWMkmYxUeBxotozc-0-ua69CYJo,3265
72
73
  psdi_data_conversion/static/javascript/psdi-common.js,sha256=I0QqGQ7l_rA4KEfenQTfPc-uOXXp8sxMh_NHL3EkFm4,6231
73
74
  psdi_data_conversion/static/javascript/report.js,sha256=BHH5UOhXJtB6J_xk_y6woquNKt5W9hCrQapxKtGG1eA,12470
74
- psdi_data_conversion/static/styles/format.css,sha256=HKgKkepZtY0NCtKm4JlsuchDL_vymBQ0pRnmfVE8L30,3097
75
+ psdi_data_conversion/static/styles/format.css,sha256=PaQkUVxQfXI9nbJ-7YsN1tNIcLXfwXk8wJC-zht8nRA,3269
75
76
  psdi_data_conversion/static/styles/psdi-common.css,sha256=09VY-lldoZCrohuqPKnd9fvDget5g9ybi6uh13pYeY0,17249
76
- psdi_data_conversion/templates/index.htm,sha256=wuHECSzTwVwmaGg55RnYunsaSFCYBmxf6_P4OygTNEQ,6824
77
+ psdi_data_conversion/templates/index.htm,sha256=oZEJNc1aenHExnUZMv6XJfn7nibtYevGGpOaeRbIZ2Y,6784
77
78
  psdi_data_conversion/testing/__init__.py,sha256=Xku7drtLTYLLPsd403eC0LIEa_iohVifyeyAITy2w7U,135
78
79
  psdi_data_conversion/testing/constants.py,sha256=BtIafruSobZ9cFY0VW5Bu209eiftnN8b3ObouZBrFQU,521
79
- psdi_data_conversion/testing/conversion_callbacks.py,sha256=FeRcS06ynLzQOWwqf2QiIR5EaM-icKGolvrVI88ZOOg,18858
80
- psdi_data_conversion/testing/conversion_test_specs.py,sha256=vsNj2YKX1ZYglAPVN4smuLn6fjZKYMfaxuwkyLDj39g,24878
81
- psdi_data_conversion/testing/gui.py,sha256=I44QeLztcnt-37Zf2nOvrqjo_y6a40VhjehdVwGejW0,18708
82
- psdi_data_conversion/testing/utils.py,sha256=ZuwB5rEW-eB-38xQb3ZvJpSzuI4ocbFUNAc-uiC4vW4,26134
83
- psdi_data_conversion-0.0.38.dist-info/METADATA,sha256=eIHXKGbPOKrQgYQGA5uIrP9xGgaSNoec6UN_KulmhBE,48116
84
- psdi_data_conversion-0.0.38.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
85
- psdi_data_conversion-0.0.38.dist-info/entry_points.txt,sha256=xL7XTzaPRr2E67WhOD1M1Q-76hB8ausQlnNiHzuZQPA,123
86
- psdi_data_conversion-0.0.38.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
87
- psdi_data_conversion-0.0.38.dist-info/RECORD,,
80
+ psdi_data_conversion/testing/conversion_callbacks.py,sha256=ATR-_BsYCUN8KyOyUjfdWCELzySxLN5jOI0JyrQnmHQ,18858
81
+ psdi_data_conversion/testing/conversion_test_specs.py,sha256=8W97tI6dVbHE9BEW76dsKDlfsm5oTlrlntG--b0h8HU,26106
82
+ psdi_data_conversion/testing/gui.py,sha256=ul7ixYANIzmOG2ZNOZmQO6wsHmGHdiBGAlw-KuoN0j8,19085
83
+ psdi_data_conversion/testing/utils.py,sha256=YrFxjyiIx1seph0j7jCUgAVm6HvXY9QJjx0MvNJRbfw,26134
84
+ psdi_data_conversion-0.1.0.dist-info/METADATA,sha256=mD4CvjwfelhGA25tGlYa2XUqQyzwycNCod3r7SD052Q,48108
85
+ psdi_data_conversion-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
86
+ psdi_data_conversion-0.1.0.dist-info/entry_points.txt,sha256=xL7XTzaPRr2E67WhOD1M1Q-76hB8ausQlnNiHzuZQPA,123
87
+ psdi_data_conversion-0.1.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
88
+ psdi_data_conversion-0.1.0.dist-info/RECORD,,