psdi-data-conversion 0.0.35__tar.gz → 0.0.36__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/PKG-INFO +29 -6
  2. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/README.md +28 -5
  3. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/app.py +23 -3
  4. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/constants.py +2 -0
  5. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/converter.py +16 -6
  6. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/converters/atomsk.py +3 -1
  7. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/converters/base.py +99 -39
  8. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/converters/c2x.py +3 -1
  9. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/converters/openbabel.py +40 -1
  10. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/database.py +5 -0
  11. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/main.py +18 -10
  12. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/content/accessibility.htm +5 -5
  13. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/content/convert.htm +18 -13
  14. psdi_data_conversion-0.0.36/psdi_data_conversion/static/content/convertato.htm +87 -0
  15. psdi_data_conversion-0.0.36/psdi_data_conversion/static/content/convertc2x.htm +88 -0
  16. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/content/documentation.htm +4 -4
  17. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/content/download.htm +4 -1
  18. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/content/feedback.htm +4 -4
  19. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/content/index-versions/psdi-common-header.html +1 -1
  20. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/content/psdi-common-header.html +1 -1
  21. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/content/report.htm +9 -7
  22. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/javascript/common.js +20 -0
  23. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/javascript/convert.js +1 -2
  24. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/javascript/convert_common.js +80 -7
  25. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/javascript/convertato.js +1 -2
  26. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/javascript/convertc2x.js +1 -2
  27. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/javascript/format.js +12 -0
  28. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/javascript/report.js +6 -0
  29. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/styles/format.css +0 -6
  30. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/styles/psdi-common.css +5 -2
  31. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/templates/index.htm +4 -1
  32. psdi_data_conversion-0.0.36/psdi_data_conversion/testing/conversion_test_specs.py +299 -0
  33. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/testing/utils.py +22 -7
  34. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/pyproject.toml +15 -7
  35. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/run_local.sh +7 -0
  36. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/tests/cli_test.py +20 -84
  37. psdi_data_conversion-0.0.36/tests/converter_test.py +78 -0
  38. psdi_data_conversion-0.0.35/psdi_data_conversion/static/content/convertato.htm +0 -80
  39. psdi_data_conversion-0.0.35/psdi_data_conversion/static/content/convertc2x.htm +0 -81
  40. psdi_data_conversion-0.0.35/psdi_data_conversion/testing/conversion_test_specs.py +0 -208
  41. psdi_data_conversion-0.0.35/test_data/output/caffeine-no-flags.smi +0 -1
  42. psdi_data_conversion-0.0.35/test_data/output/caffeine_a_in.smi +0 -1
  43. psdi_data_conversion-0.0.35/test_data/output/caffeine_a_in_kx_f4_l5_out.smi +0 -1
  44. psdi_data_conversion-0.0.35/test_data/output/caffeine_a_in_kx_f4_out.smi +0 -1
  45. psdi_data_conversion-0.0.35/test_data/output/caffeine_a_in_kx_out.smi +0 -1
  46. psdi_data_conversion-0.0.35/test_data/output/caffeine_a_in_x_out.smi +0 -1
  47. psdi_data_conversion-0.0.35/test_data/output/error_Fapatite_ins_to_cml_OB +0 -33
  48. psdi_data_conversion-0.0.35/test_data/output/error_cyclopropane_mol_to_xyz_c2x +0 -33
  49. psdi_data_conversion-0.0.35/test_data/output/error_nacl_mol_to_xyz_atomsk +0 -33
  50. psdi_data_conversion-0.0.35/tests/converter_test.py +0 -143
  51. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/.github/workflows/ci-cron.yml +0 -0
  52. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/.github/workflows/ci-deploy-production.yml +0 -0
  53. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/.github/workflows/ci-feature.yml +0 -0
  54. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/.github/workflows/ci-main.yml +0 -0
  55. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/.github/workflows/ci-pr.yml +0 -0
  56. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/.github/workflows/ci-rc-hotfix.yml +0 -0
  57. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/.github/workflows/ci-release.yml +0 -0
  58. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/.github/workflows/job-anchore-scan.yml +0 -0
  59. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/.github/workflows/job-container-push.yml +0 -0
  60. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/.github/workflows/job-deploy-k8s.yml +0 -0
  61. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/.github/workflows/job-open-pull-request.yml +0 -0
  62. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/.github/workflows/job-publish-doc.yml +0 -0
  63. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/.github/workflows/job-tag.yml +0 -0
  64. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/.github/workflows/job-test-gui.yml +0 -0
  65. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/.github/workflows/job-test-python.yml +0 -0
  66. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/.gitignore +0 -0
  67. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/CHANGELOG.md +0 -0
  68. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/CONTRIBUTING.md +0 -0
  69. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/LICENSE +0 -0
  70. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/__init__.py +0 -0
  71. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/bin/LICENSE_ATOMSK +0 -0
  72. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/bin/LICENSE_C2X +0 -0
  73. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/bin/linux/atomsk +0 -0
  74. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/bin/linux/c2x +0 -0
  75. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/bin/mac/atomsk +0 -0
  76. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/bin/mac/c2x +0 -0
  77. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/converters/__init__.py +0 -0
  78. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/dist.py +0 -0
  79. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/file_io.py +0 -0
  80. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/log_utility.py +0 -0
  81. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/scripts/atomsk.sh +0 -0
  82. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/scripts/c2x.sh +0 -0
  83. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/security.py +0 -0
  84. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/content/header-links.html +0 -0
  85. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/content/index-versions/header-links.html +0 -0
  86. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/content/index-versions/psdi-common-footer.html +0 -0
  87. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/content/psdi-common-footer.html +0 -0
  88. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/data/data.json +0 -0
  89. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/colormode-toggle-dm.svg +0 -0
  90. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/colormode-toggle-lm.svg +0 -0
  91. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/psdi-icon-dark.svg +0 -0
  92. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/psdi-icon-light.svg +0 -0
  93. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/psdi-logo-darktext-simple.png +0 -0
  94. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/psdi-logo-darktext.png +0 -0
  95. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/psdi-logo-lighttext-simple.png +0 -0
  96. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/psdi-logo-lighttext.png +0 -0
  97. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/social-logo-bluesky-black.svg +0 -0
  98. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/social-logo-bluesky-white.svg +0 -0
  99. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/social-logo-instagram-black.svg +0 -0
  100. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/social-logo-instagram-white.svg +0 -0
  101. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/social-logo-linkedin-black.png +0 -0
  102. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/social-logo-linkedin-white.png +0 -0
  103. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/social-logo-mastodon-black.svg +0 -0
  104. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/social-logo-mastodon-white.svg +0 -0
  105. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/social-logo-x-black.svg +0 -0
  106. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/social-logo-x-white.svg +0 -0
  107. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/social-logo-youtube-black.png +0 -0
  108. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/social-logo-youtube-white.png +0 -0
  109. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/ukri-epsr-logo-darktext.png +0 -0
  110. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/ukri-epsr-logo-lighttext.png +0 -0
  111. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/ukri-logo-darktext.png +0 -0
  112. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/img/ukri-logo-lighttext.png +0 -0
  113. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/javascript/accessibility.js +0 -0
  114. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/javascript/data.js +0 -0
  115. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/javascript/load_accessibility.js +0 -0
  116. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/static/javascript/psdi-common.js +0 -0
  117. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/testing/__init__.py +0 -0
  118. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/testing/constants.py +0 -0
  119. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/psdi_data_conversion/testing/conversion_callbacks.py +0 -0
  120. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/scripts/setup_bin.py +0 -0
  121. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/1ARJ.mmcif +0 -0
  122. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/1NE6.mmcif +0 -0
  123. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/5a9z-assembly1.cif +0 -0
  124. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/Fapatite.ins +0 -0
  125. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/aceticacid.mol +0 -0
  126. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/benzyne.molden +0 -0
  127. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/caffeine-smi.tar +0 -0
  128. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/caffeine-smi.tar.gz +0 -0
  129. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/caffeine-smi.zip +0 -0
  130. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/caffeine.inchi +0 -0
  131. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/ch3cl-esp.cub +0 -0
  132. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/cyclopropane_err.mol +0 -0
  133. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/ethanol.xyz +0 -0
  134. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/fullRhinovirus.pdb +0 -0
  135. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/hemoglobin.pdb +0 -0
  136. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/nacl.cif +0 -0
  137. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/nacl.mol +0 -0
  138. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/output/aceticacid.log.txt +0 -0
  139. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/output/aceticacid.mol2 +0 -0
  140. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/output/caffeine-2D-fastest.xyz +0 -0
  141. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/output/caffeine-3D-best.xyz +0 -0
  142. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/output/caffeine.smi +0 -0
  143. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/output/caffeine.xyz +0 -0
  144. /psdi_data_conversion-0.0.35/test_data/output/caffeine-ia.smi → /psdi_data_conversion-0.0.36/test_data/output/caffeine_a_in.smi +0 -0
  145. /psdi_data_conversion-0.0.35/test_data/output/caffeine-ia-okx-oof4l5.smi → /psdi_data_conversion-0.0.36/test_data/output/caffeine_a_in_kx_f4_l5_out.smi +0 -0
  146. /psdi_data_conversion-0.0.35/test_data/output/caffeine-ia-okx-oof4.smi → /psdi_data_conversion-0.0.36/test_data/output/caffeine_a_in_kx_f4_out.smi +0 -0
  147. /psdi_data_conversion-0.0.35/test_data/output/caffeine-ia-okx.smi → /psdi_data_conversion-0.0.36/test_data/output/caffeine_a_in_kx_out.smi +0 -0
  148. /psdi_data_conversion-0.0.35/test_data/output/caffeine-ia-ox.smi → /psdi_data_conversion-0.0.36/test_data/output/caffeine_a_in_x_out.smi +0 -0
  149. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/output/hemoglobin_Atomsk.xyz +0 -0
  150. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/output/hemoglobin_c2x.xyz +0 -0
  151. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/output/nacl.log +0 -0
  152. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/output/nacl.mol +0 -0
  153. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/output/quartz_OB.cif +0 -0
  154. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/output/quartz_OB.log.txt +0 -0
  155. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/output/quartz_atomsk.cif +0 -0
  156. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/output/quartz_atomsk.log.txt +0 -0
  157. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/output/standard_test.inchi +0 -0
  158. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/output/xyz_files-mol.zip +0 -0
  159. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/output/xyz_files.log.txt +0 -0
  160. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/periodic_dmol3.outmol +0 -0
  161. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/quartz.xyz +0 -0
  162. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/quartz_err.xyz +0 -0
  163. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/test_data/standard_test.cdxml +0 -0
  164. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/tests/database_test.py +0 -0
  165. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/tests/dist_test.py +0 -0
  166. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/tests/file_io_test.py +0 -0
  167. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/tests/logging_test.py +0 -0
  168. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/tests/security_test.py +0 -0
  169. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/tests/selenium/files/standard_test.cdxml +0 -0
  170. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/tests/selenium/run.sh +0 -0
  171. {psdi_data_conversion-0.0.35 → psdi_data_conversion-0.0.36}/tests/selenium/selenium_tests.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: psdi_data_conversion
3
- Version: 0.0.35
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 package is not yet available on PyPI, and so must be installed locally. This can be done most easily with:
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
- executed 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.
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
- Install the package and its requirements, including the optional requirements used to run the GUI locally, by executing the following command from this project's directory:
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 your system does not allow installs 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.
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 you've cloned this repository, you can use the `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:
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
@@ -158,13 +158,21 @@ In addition to the dependencies listed above, this project uses the assets made
158
158
 
159
159
  ### Installation
160
160
 
161
- The CLA and Python library are installed together. This package is not yet available on PyPI, and so must be installed locally. This can be done most easily with:
161
+ The CLA and Python library are installed together. This project is available on PyPI, and so can be installed via pip with:
162
+
163
+ ```bash
164
+ pip install psdi-data-conversion
165
+ ```
166
+
167
+ If you wish to install from source, this can be done most easily by cloning the project and then executing:
162
168
 
163
169
  ```bash
164
170
  pip install .
165
171
  ```
166
172
 
167
- executed 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.
173
+ 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.
174
+
175
+ **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.
168
176
 
169
177
  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.:
170
178
 
@@ -327,15 +335,23 @@ Enter https://data-conversion.psdi.ac.uk/ in a browser. Guidance on usage is giv
327
335
 
328
336
  ### Installation and Setup
329
337
 
330
- Install the package and its requirements, including the optional requirements used to run the GUI locally, by executing the following command from this project's directory:
338
+ This project is available on PyPI, and so can be installed via pip, including the necessary dependencies for the GUI, with:
339
+
340
+ ```bash
341
+ pip install psdi-data-conversion'[gui]'
342
+ ```
343
+
344
+ If you wish to install the project locally from source, this can be done most easily by cloning the project and then executing:
331
345
 
332
346
  ```bash
333
347
  pip install .'[gui]'
334
348
  ```
335
349
 
336
- If your system does not allow installs 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.
350
+ **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.
337
351
 
338
- If you've cloned this repository, you can use the `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:
352
+ 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.
353
+
354
+ 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:
339
355
 
340
356
  ```bash
341
357
  #!/bin/bash
@@ -345,6 +361,13 @@ if [ -z $MAX_FILESIZE ]; then
345
361
  export MAX_FILESIZE=0
346
362
  fi
347
363
 
364
+ # The envvar MAX_FILESIZE_OB can be used to set the maximum allowed filesize in MB for the Open Babel converter - 0
365
+ # indicates no maximum. This is currently set to 1 MB by default as the converter seems to hang above this limit (not
366
+ # even allowing the process to be cancelled). This can be changed in the future if this is patched
367
+ if [ -z $MAX_FILESIZE_OB ]; then
368
+ export MAX_FILESIZE_OB=1
369
+ fi
370
+
348
371
  # Logging control - "full" sets server-style logging, which is necessary to produce the output logs with the expected
349
372
  # names. This should not be changed, or else errors will occur
350
373
  export LOG_MODE=full
@@ -102,8 +102,16 @@ def website():
102
102
  else:
103
103
  max_file_size = const.DEFAULT_MAX_FILE_SIZE
104
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
+
105
112
  data = [{'token': token,
106
113
  'max_file_size': max_file_size,
114
+ 'max_file_size_ob': max_file_size_ob,
107
115
  'service_mode': service_mode,
108
116
  'production_mode': production_mode,
109
117
  'sha': get_last_sha()}]
@@ -150,11 +158,23 @@ def convert():
150
158
  fo.write(str(e))
151
159
  abort(const.STATUS_CODE_GENERAL)
152
160
 
153
- # Failsafe exception message
154
- msg = "The following unexpected exception was raised by the converter:\n" + traceback.format_exc()+"\n"
161
+ # If the exception provides a status code, get it
162
+ status_code: int
163
+ if hasattr(e, "status_code"):
164
+ status_code = e.status_code
165
+ else:
166
+ status_code = const.STATUS_CODE_GENERAL
167
+
168
+ # If the exception provides a message, report it
169
+ if hasattr(e, "message"):
170
+ msg = f"An unexpected exception was raised by the converter, with error message:\n{e.message}\n"
171
+ else:
172
+ # Failsafe exception message
173
+ msg = ("The following unexpected exception was raised by the converter:\n" +
174
+ traceback.format_exc()+"\n")
155
175
  with open(qualified_output_log, "w") as fo:
156
176
  fo.write(msg)
157
- abort(const.STATUS_CODE_GENERAL)
177
+ abort(status_code)
158
178
 
159
179
  return repr(conversion_output)
160
180
  else:
@@ -40,6 +40,7 @@ CL_SCRIPT_NAME = "psdi-data-convert"
40
40
  LOG_MODE_EV = "LOG_MODE"
41
41
  LOG_LEVEL_EV = "LOG_LEVEL"
42
42
  MAX_FILESIZE_EV = "MAX_FILESIZE"
43
+ MAX_FILESIZE_OB_EV = "MAX_FILESIZE_OB"
43
44
 
44
45
  # Files and Folders
45
46
  # -----------------
@@ -47,6 +48,7 @@ MAX_FILESIZE_EV = "MAX_FILESIZE"
47
48
  # Maximum output file size in bytes
48
49
  MEGABYTE = 1024*1024
49
50
  DEFAULT_MAX_FILE_SIZE = 0*MEGABYTE
51
+ DEFAULT_MAX_FILE_SIZE_OB = 1*MEGABYTE
50
52
 
51
53
  DEFAULT_UPLOAD_DIR = './psdi_data_conversion/static/uploads'
52
54
  DEFAULT_DOWNLOAD_DIR = './psdi_data_conversion/static/downloads'
@@ -17,6 +17,7 @@ from psdi_data_conversion.converters import base
17
17
 
18
18
  import glob
19
19
 
20
+ from psdi_data_conversion.converters.openbabel import CONVERTER_OB
20
21
  from psdi_data_conversion.file_io import (is_archive, is_supported_archive, pack_zip_or_tar, split_archive_ext,
21
22
  unpack_zip_or_tar)
22
23
 
@@ -105,7 +106,8 @@ def get_converter(*args, name=const.CONVERTER_DEFAULT, **converter_kwargs) -> ba
105
106
  name : str
106
107
  The desired converter type, by default 'Open Babel'
107
108
  data : dict[str | Any] | None
108
- A dict of any other data needed by a converter or for extra logging information, default empty dict
109
+ A dict of any other data needed by a converter or for extra logging information, default empty dict. See the
110
+ docstring of each converter for supported keys and values that can be passed to `data` here
109
111
  abort_callback : Callable[[int], None]
110
112
  Function to be called if the conversion hits an error and must be aborted, default `abort_raise`, which
111
113
  raises an appropriate exception
@@ -117,7 +119,9 @@ def get_converter(*args, name=const.CONVERTER_DEFAULT, **converter_kwargs) -> ba
117
119
  download_dir : str
118
120
  The location of output files relative to the current directory
119
121
  max_file_size : float
120
- The maximum allowed file size for input/output files, in MB, default 1 MB. If 0, will be unlimited
122
+ The maximum allowed file size for input/output files, in MB, default 1 MB for Open Babel, unlimited for other
123
+ converters. If 0, will be unlimited. If an archive of files is provided, this will apply to the total of all
124
+ files contained in it
121
125
  no_check : bool
122
126
  If False (default), will check at setup whether or not a conversion between the desired file formats is
123
127
  supported with the specified converter
@@ -238,7 +242,7 @@ def run_converter(filename: str,
238
242
  *args,
239
243
  from_format: str | None = None,
240
244
  download_dir=const.DEFAULT_DOWNLOAD_DIR,
241
- max_file_size=const.DEFAULT_MAX_FILE_SIZE,
245
+ max_file_size=None,
242
246
  log_file: str | None = None,
243
247
  log_mode=const.LOG_SIMPLE,
244
248
  strict=False,
@@ -261,7 +265,8 @@ def run_converter(filename: str,
261
265
  name : str
262
266
  The desired converter type, by default 'Open Babel'
263
267
  data : dict[str | Any] | None
264
- A dict of any other data needed by a converter or for extra logging information, default empty dict
268
+ A dict of any other data needed by a converter or for extra logging information, default empty dict. See the
269
+ docstring of each converter for supported keys and values that can be passed to `data` here
265
270
  abort_callback : Callable[[int], None]
266
271
  Function to be called if the conversion hits an error and must be aborted, default `abort_raise`, which
267
272
  raises an appropriate exception
@@ -280,8 +285,9 @@ def run_converter(filename: str,
280
285
  into a file of the same format, their logs will be combined into a single log, and the converted files and
281
286
  individual logs will be deleted
282
287
  max_file_size : float
283
- The maximum allowed file size for input/output files, in MB, default 1 MB. If 0, will be unlimited. If an
284
- archive of files is provided, this will apply to the total of all files contained in it
288
+ The maximum allowed file size for input/output files, in MB, default 1 MB for Open Babel, unlimited for other
289
+ converters. If 0, will be unlimited. If an archive of files is provided, this will apply to the total of all
290
+ files contained in it
285
291
  no_check : bool
286
292
  If False (default), will check at setup whether or not a conversion between the desired file formats is
287
293
  supported with the specified converter
@@ -318,6 +324,10 @@ def run_converter(filename: str,
318
324
  If something goes wrong during the conversion process
319
325
  """
320
326
 
327
+ # Set the maximum file size based on which converter is being used if using the default
328
+ if max_file_size is None:
329
+ max_file_size = const.DEFAULT_MAX_FILE_SIZE_OB if name == CONVERTER_OB else const.DEFAULT_MAX_FILE_SIZE
330
+
321
331
  # Set the log file if it was unset - note that in server logging mode, this value won't be used within the
322
332
  # converter class, so it needs to be set up here to match what will be set up there
323
333
  if log_file is None:
@@ -11,7 +11,9 @@ CONVERTER_ATO = 'Atomsk'
11
11
 
12
12
 
13
13
  class AtoFileConverter(ScriptFileConverter):
14
- """File Converter specialized to use Atomsk for conversions
14
+ """File Converter specialized to use Atomsk for conversions.
15
+
16
+ This converter does not yet support any additional configuration options provided at class init to the `data` kwarg.
15
17
  """
16
18
 
17
19
  name = CONVERTER_ATO
@@ -34,7 +34,12 @@ except ImportError:
34
34
  class FileConverterException(RuntimeError):
35
35
  """Exception class to represent any runtime error encountered by this package.
36
36
  """
37
- pass
37
+
38
+ def __init__(self,
39
+ *args,
40
+ logged: bool = False):
41
+ super().__init__(*args)
42
+ self.logged = logged
38
43
 
39
44
 
40
45
  class FileConverterAbortException(FileConverterException):
@@ -212,7 +217,7 @@ class FileConverter:
212
217
  use_envvars=False,
213
218
  upload_dir=const.DEFAULT_UPLOAD_DIR,
214
219
  download_dir=const.DEFAULT_DOWNLOAD_DIR,
215
- max_file_size=const.DEFAULT_MAX_FILE_SIZE,
220
+ max_file_size=None,
216
221
  no_check=False,
217
222
  log_file: str | None = None,
218
223
  log_mode=const.LOG_FULL,
@@ -231,7 +236,8 @@ class FileConverter:
231
236
  The format to convert from, as the file extension (e.g. "pdb"). If None is provided (default), will be
232
237
  determined from the extension of `filename`
233
238
  data : dict[str | Any] | None
234
- A dict of any other data needed by a converter or for extra logging information, default empty dict
239
+ A dict of any other data needed by a converter or for extra logging information, default empty dict. See the
240
+ docstring of each converter for supported keys and values that can be passed to `data` here
235
241
  abort_callback : Callable[[int], None]
236
242
  Function to be called if the conversion hits an error and must be aborted, default `abort_raise`, which
237
243
  raises an appropriate exception
@@ -275,12 +281,32 @@ class FileConverter:
275
281
 
276
282
  try:
277
283
 
284
+ if max_file_size is None:
285
+ from psdi_data_conversion.converters.openbabel import CONVERTER_OB
286
+ if self.name == CONVERTER_OB:
287
+ self.max_file_size = const.DEFAULT_MAX_FILE_SIZE_OB*const.MEGABYTE
288
+ else:
289
+ self.max_file_size = const.DEFAULT_MAX_FILE_SIZE*const.MEGABYTE
290
+ else:
291
+ self.max_file_size = max_file_size*const.MEGABYTE
292
+
293
+ # Set values from envvars if desired
294
+ if use_envvars:
295
+ # Get the maximum allowed size from the envvar for it
296
+ from psdi_data_conversion.converters.openbabel import CONVERTER_OB
297
+ if self.name == CONVERTER_OB:
298
+ ev_max_file_size = os.environ.get(const.MAX_FILESIZE_OB_EV)
299
+ else:
300
+ ev_max_file_size = os.environ.get(const.MAX_FILESIZE_EV)
301
+
302
+ if ev_max_file_size is not None:
303
+ self.max_file_size = float(ev_max_file_size)*const.MEGABYTE
304
+
278
305
  # Set member variables directly from input
279
306
  self.in_filename = filename
280
307
  self.to_format = to_format
281
308
  self.upload_dir = upload_dir
282
309
  self.download_dir = download_dir
283
- self.max_file_size = max_file_size*const.MEGABYTE
284
310
  self.log_file = log_file
285
311
  self.log_mode = log_mode
286
312
  self.log_level = log_level
@@ -312,13 +338,6 @@ class FileConverter:
312
338
  self.err: str | None = None
313
339
  self.quality: str | None = None
314
340
 
315
- # Set values from envvars if desired
316
- if use_envvars:
317
- # Get the maximum allowed size from the envvar for it
318
- ev_max_file_size = os.environ.get(const.MAX_FILESIZE_EV)
319
- if ev_max_file_size is not None:
320
- self.max_file_size = float(ev_max_file_size)*const.MEGABYTE
321
-
322
341
  # Create directory 'uploads' if not extant.
323
342
  if not os.path.exists(self.upload_dir):
324
343
  os.makedirs(self.upload_dir, exist_ok=True)
@@ -351,10 +370,13 @@ class FileConverter:
351
370
  self.logger.debug("Finished FileConverter initialisation")
352
371
 
353
372
  except Exception as e:
373
+ # Don't catch a deliberate abort; let it pass through
354
374
  if isinstance(e, l_abort_exceptions):
355
- # Don't catch a deliberate abort; let it pass through
356
- self.logger.error(f"Unexpected exception raised while initializing the converter, of type '{type(e)}' "
357
- f"with message: {str(e)}")
375
+ if not hasattr(e, "logged") or e.logged is False:
376
+ self.logger.error(f"Unexpected exception raised while running the converter, of type '{type(e)}' "
377
+ f"with message: {str(e)}")
378
+ if e:
379
+ e.logged = True
358
380
  raise
359
381
  # Try to run the standard abort method. There's a good chance this will fail though depending on what went
360
382
  # wrong when during init, so we fallback to printing the exception to stderr
@@ -362,6 +384,8 @@ class FileConverter:
362
384
  if not isinstance(e, FileConverterHelpException):
363
385
  self.logger.error(f"Exception triggering an abort was raised while initializing the converter. "
364
386
  f"Exception was type '{type(e)}', with message: {str(e)}")
387
+ if e:
388
+ e.logged = True
365
389
  self._abort(message="The application encountered an error while initializing the converter:\n" +
366
390
  traceback.format_exc(), e=e)
367
391
  except Exception as ee:
@@ -445,20 +469,28 @@ class FileConverter:
445
469
  """
446
470
 
447
471
  try:
472
+ self.logger.debug("Checking input file size")
473
+ self._check_input_file_size_and_status()
474
+
448
475
  self.logger.debug("Starting file conversion")
449
476
  self._convert()
450
477
 
451
478
  self.logger.debug("Finished file conversion; performing cleanup tasks")
452
479
  self._finish_convert()
453
480
  except Exception as e:
481
+ # Don't catch a deliberate abort; let it pass through
454
482
  if isinstance(e, l_abort_exceptions):
455
- # Don't catch a deliberate abort; let it pass through
456
- self.logger.error(f"Unexpected exception raised while running the converter, of type '{type(e)}' with "
457
- f"message: {str(e)}")
483
+ # Log the error if it hasn't yet been logged
484
+ if not hasattr(e, "logged") or e.logged is False:
485
+ self.logger.error(f"Unexpected exception raised while running the converter, of type '{type(e)}' "
486
+ f"with message: {str(e)}")
487
+ e.logged = True
458
488
  raise
459
489
  if not isinstance(e, FileConverterHelpException):
460
490
  self.logger.error(f"Exception triggering an abort was raised while running the converter. Exception "
461
491
  f"was type '{type(e)}', with message: {str(e)}")
492
+ if e:
493
+ e.logged = True
462
494
  self._abort(message="The application encountered an error while running the converter:\n" +
463
495
  traceback.format_exc(), e=e)
464
496
 
@@ -522,13 +554,23 @@ class FileConverter:
522
554
  # Note this message in the dev logger as well
523
555
  if not isinstance(e, FileConverterHelpException):
524
556
  self.logger.error(message)
557
+ if e:
558
+ e.logged = True
525
559
 
526
- # Call the abort callback function now. We first try to add information to it, but in case that isn't supported,
527
- # we fall back to just calling it with the status code
560
+ # Call the abort callback function now. We first try passing information to the callback function
528
561
  try:
529
562
  self.abort_callback(status_code, message, e=e, **kwargs)
530
563
  except TypeError:
531
- self.abort_callback(status_code)
564
+ # The callback function doesn't support arguments, so we instead call the callback, catch any exception it
565
+ # raises, monkey-patch on the extra info, and reraise it
566
+ try:
567
+ self.abort_callback(status_code)
568
+ except Exception as ee:
569
+ ee.status_code = status_code
570
+ ee.message = message
571
+ ee.e = e
572
+ ee.abort_kwargs = kwargs
573
+ raise ee
532
574
 
533
575
  def _abort_from_err(self):
534
576
  """Call an abort after a call to the converter has completed, but it's returned an error. Create a message for
@@ -538,7 +580,7 @@ class FileConverter:
538
580
  self._create_message() +
539
581
  self.out + '\n' +
540
582
  self.err)
541
- self._abort(message=self.err)
583
+ self._abort(message=self.err, logged=True)
542
584
 
543
585
  def _create_message(self) -> str:
544
586
  """Create a log of options passed to the converter - this method should be overloaded to log any information
@@ -578,19 +620,38 @@ class FileConverter:
578
620
 
579
621
  self.logger.info(message)
580
622
 
581
- def _check_file_size_and_status(self):
582
- """Get file sizes, checking that output file isn't too large
623
+ def _check_input_file_size_and_status(self):
624
+ """Get input file size and status, checking that the file isn't too large
625
+ """
583
626
 
584
- Returns
585
- -------
586
- in_size : int
587
- Size of input file in bytes
588
- out_size : int
589
- Size of output file in bytes
627
+ try:
628
+ self.in_size = os.path.getsize(os.path.realpath(self.in_filename))
629
+ except FileNotFoundError:
630
+ # Something went wrong and the output file doesn't exist
631
+ err_message = f"Expected output file {self.in_filename} does not exist."
632
+ self.logger.error(err_message)
633
+ self.err += f"ERROR: {err_message}\n"
634
+ self._abort_from_err()
635
+
636
+ # Check that the input file doesn't exceed the maximum allowed size
637
+ if self.max_file_size > 0 and self.in_size > self.max_file_size:
638
+
639
+ self._abort(const.STATUS_CODE_SIZE,
640
+ f"ERROR converting {os.path.basename(self.in_filename)} to " +
641
+ os.path.basename(self.out_filename) + ": "
642
+ f"Input file exceeds maximum size.\nInput file size is "
643
+ f"{self.in_size/const.MEGABYTE:.2f} MB; maximum input file size is "
644
+ f"{self.max_file_size/const.MEGABYTE:.2f} MB.\n",
645
+ max_file_size=self.max_file_size,
646
+ in_size=self.in_size,
647
+ out_size=None)
648
+
649
+ def _check_output_file_size_and_status(self):
650
+ """Get output file size and status, checking that the file isn't too large
590
651
  """
591
- in_size = os.path.getsize(os.path.realpath(self.in_filename))
652
+
592
653
  try:
593
- out_size = os.path.getsize(os.path.realpath(self.out_filename))
654
+ self.out_size = os.path.getsize(os.path.realpath(self.out_filename))
594
655
  except FileNotFoundError:
595
656
  # Something went wrong and the output file doesn't exist
596
657
  err_message = f"Expected output file {self.out_filename} does not exist."
@@ -599,20 +660,19 @@ class FileConverter:
599
660
  self._abort_from_err()
600
661
 
601
662
  # Check that the output file doesn't exceed the maximum allowed size
602
- if self.max_file_size > 0 and out_size > self.max_file_size:
663
+ if self.max_file_size > 0 and self.out_size > self.max_file_size:
603
664
 
604
665
  self._abort(const.STATUS_CODE_SIZE,
605
666
  f"ERROR converting {os.path.basename(self.in_filename)} to " +
606
667
  os.path.basename(self.out_filename) + ": "
607
668
  f"Output file exceeds maximum size.\nInput file size is "
608
- f"{in_size/const.MEGABYTE:.2f} MB; Output file size is {out_size/const.MEGABYTE:.2f} "
669
+ f"{self.in_size/const.MEGABYTE:.2f} MB; Output file size is {self.out_size/const.MEGABYTE:.2f} "
609
670
  f"MB; maximum output file size is {self.max_file_size/const.MEGABYTE:.2f} MB.\n",
610
- in_size=in_size,
611
- out_size=out_size,
612
- max_file_size=self.max_file_size)
613
- self.logger.debug(f"Output file found to have size {out_size/const.MEGABYTE:.2f} MB")
671
+ max_file_size=self.max_file_size,
672
+ in_size=self.in_size,
673
+ out_size=self.out_size)
614
674
 
615
- return in_size, out_size
675
+ self.logger.debug(f"Output file found to have size {self.out_size/const.MEGABYTE:.2f} MB")
616
676
 
617
677
  def get_quality(self) -> str:
618
678
  """Query the JSON file to obtain conversion quality
@@ -630,7 +690,7 @@ class FileConverter:
630
690
  """Run final common steps to clean up a conversion and log success or abort due to an error
631
691
  """
632
692
 
633
- self.in_size, self.out_size = self._check_file_size_and_status()
693
+ self._check_output_file_size_and_status()
634
694
 
635
695
  if self.delete_input:
636
696
  os.remove(self.in_filename)
@@ -11,7 +11,9 @@ CONVERTER_C2X = 'c2x'
11
11
 
12
12
 
13
13
  class C2xFileConverter(ScriptFileConverter):
14
- """File Converter specialized to use c2x for conversions
14
+ """File Converter specialized to use c2x for conversions.
15
+
16
+ This converter does not yet support any additional configuration options provided at class init to the `data` kwarg.
15
17
  """
16
18
 
17
19
  name = CONVERTER_C2X
@@ -76,7 +76,46 @@ def get_coord_gen(l_opts: list[str] | None) -> dict[str, str]:
76
76
 
77
77
 
78
78
  class OBFileConverter(FileConverter):
79
- """File Converter specialized to use Open Babel for conversions
79
+ """File Converter specialized to use Open Babel for conversions.
80
+
81
+ This converter supports some additional configuration options which can be provided at class init or call to
82
+ `run_converter()` through providing a dict to the `data` kwarg. The supported keys and values are:
83
+
84
+ "from_flags": str
85
+ String of concatenated one-letter flags for how to read the input file. To list the flags supported for a given
86
+ input format, call ``psdi-data-convert -l -f <format> -w Open Babel`` at the command-line and look for the
87
+ "Allowed input flags" section, if one exists, or alternatively call the library function
88
+ ``psdi_data_conversion.database.get_in_format_args("Open Babel", <format>)`` from within Python code.
89
+
90
+ "to_flags": str
91
+ String of concatenated one-letter flags for how to write the output file. To list the flags supported for a
92
+ given output format, call ``psdi-data-convert -l -f <format> -w Open Babel`` at the command-line and look for
93
+ the "Allowed output flags" section, if one exists, or alternatively call the library function
94
+ ``psdi_data_conversion.database.get_out_format_args("Open Babel", <format>)`` from within Python code.
95
+
96
+ "from_options": str
97
+ String of space-separated options for how to read the input file. Each option "word" in this string should start
98
+ with the letter indicating which option is being used, followed by the value for that option. To list the
99
+ options supported for a given input format, call ``psdi-data-convert -l -f <format> -w Open Babel`` at the
100
+ command-line and look for the "Allowed input options" section, if one exists, or alternatively call the library
101
+ function ``psdi_data_conversion.database.get_in_format_args("Open Babel", <format>)`` from within Python code.
102
+
103
+ "to_options": str
104
+ String of space-separated options for how to write the output file. Each option "word" in this string should
105
+ start with the letter indicating which option is being used, followed by the value for that option. To list the
106
+ options supported for a given output format, call ``psdi-data-convert -l -t <format> -w Open Babel`` at the
107
+ command-line and look for the "Allowed output options" section, if one exists, or alternatively call the library
108
+ function ``psdi_data_conversion.database.get_out_format_args("Open Babel", <format>)`` from within Python code.
109
+
110
+ "coordinates": str
111
+ One of "Gen2D", "Gen3D", or "neither", specifying how positional coordinates should be generated in the output
112
+ file. Default "neither"
113
+
114
+ "coordOption": str
115
+ One of "fastest", "fast", "medium", "better", or "best", specifying the quality of the calculation of
116
+ coordinates. Default "medium"
117
+
118
+ Note that some other keys are supported for compatibility purposes, but these may be deprecated in the future.
80
119
  """
81
120
 
82
121
  name = CONVERTER_OB
@@ -284,6 +284,11 @@ class ConverterInfo:
284
284
  d_format_args: dict[str | int, set[ArgInfo]] = {}
285
285
  l_parent_format_info = self.parent.l_format_info
286
286
 
287
+ # If the converter doesn't provide argument info, set l_arg_info to an empty list so it can be iterated in
288
+ # the next step, rather than None
289
+ if not l_arg_info:
290
+ l_arg_info = []
291
+
287
292
  for arg_info in l_arg_info:
288
293
 
289
294
  if arg_info is None: