psdi-data-conversion 0.2.0__py3-none-any.whl → 0.2.2__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.
@@ -151,7 +151,7 @@ QUAL_CONN_LABEL = "Atomic connections are"
151
151
  QUAL_2D_KEY = "two_dim"
152
152
  QUAL_2D_LABEL = "2D atomic coordinates are"
153
153
  QUAL_3D_KEY = "three_dim"
154
- QUAL_3D_LABEL = "2D atomic coordinates are"
154
+ QUAL_3D_LABEL = "3D atomic coordinates are"
155
155
 
156
156
  # Notes for conversion quality
157
157
  QUAL_NOTE_IN_UNKNOWN = ("Potential data extrapolation: {} represented in the output format but its representation in "
@@ -20,6 +20,7 @@ from typing import Any
20
20
  from psdi_data_conversion import constants as const
21
21
  from psdi_data_conversion import log_utility
22
22
  from psdi_data_conversion.dist import bin_exists, get_bin_path, get_dist
23
+ from psdi_data_conversion.file_io import get_package_path
23
24
  from psdi_data_conversion.security import SAFE_STRING_RE, string_is_safe
24
25
 
25
26
  try:
@@ -744,7 +745,9 @@ class ScriptFileConverter(FileConverter):
744
745
  if self.required_bin is not None:
745
746
  env["BIN_PATH"] = get_bin_path(self.required_bin)
746
747
 
747
- process = subprocess.run(['sh', f'psdi_data_conversion/scripts/{self.script}', *self._get_script_args()],
748
+ script_abs_path = os.path.join(get_package_path(), "scripts", self.script)
749
+
750
+ process = subprocess.run(['sh', script_abs_path, *self._get_script_args()],
748
751
  env=env, capture_output=True, text=True)
749
752
 
750
753
  self.out = process.stdout
@@ -9,12 +9,14 @@ from __future__ import annotations
9
9
 
10
10
  import json
11
11
  import os
12
+ import sys
12
13
  from copy import copy
13
14
  from dataclasses import dataclass, field
14
15
  from functools import lru_cache
15
16
  from itertools import product
16
17
  from logging import getLogger
17
18
  from typing import Any, Literal, overload
19
+ from warnings import catch_warnings
18
20
 
19
21
  import igraph as ig
20
22
 
@@ -22,6 +24,7 @@ from psdi_data_conversion import constants as const
22
24
  from psdi_data_conversion.converter import (L_REGISTERED_CONVERTERS, L_SUPPORTED_CONVERTERS,
23
25
  get_registered_converter_class)
24
26
  from psdi_data_conversion.converters.base import FileConverter, FileConverterException
27
+ from psdi_data_conversion.file_io import get_package_path
25
28
  from psdi_data_conversion.utils import regularize_name
26
29
 
27
30
  # Keys for top-level and general items in the database
@@ -863,12 +866,18 @@ class ConversionsTable:
863
866
  # TODO: When there's some better measure of conversion quality, use it to choose which converter to use
864
867
  return [l_possible_direct_conversions[0]]
865
868
 
866
- # Query the graph for the shortest paths to perform this conversion
867
869
  graph: ig.Graph = self._get_desired_graph(only)
868
- l_paths: list[list[int]] = graph.get_shortest_paths(in_format_info.id, to=out_format_info.id)
870
+
871
+ # Query the graph for the shortest paths to perform this conversion. If no conversions are possible, igraph
872
+ # will print a warning, which we catch and suppress here
873
+ with catch_warnings(record=True) as l_warnings:
874
+ l_paths: list[list[int]] = graph.get_shortest_paths(in_format_info.id, to=out_format_info.id)
875
+ for warning in l_warnings:
876
+ if "Couldn't reach some vertices" not in str(warning.message):
877
+ print(warning, file=sys.stderr)
869
878
 
870
879
  # Check if any paths are possible
871
- if not l_paths:
880
+ if not l_paths or not l_paths[0]:
872
881
  return None
873
882
 
874
883
  # Check each path to find the first which doesn't lose any unnecessary info, or else the one which loses the
@@ -1198,10 +1207,7 @@ def get_database_path() -> str:
1198
1207
  str
1199
1208
  """
1200
1209
 
1201
- # For an interactive shell, __file__ won't be defined for this module, so use the constants module instead
1202
- reference_file = os.path.realpath(const.__file__)
1203
-
1204
- qualified_database_filename = os.path.join(os.path.dirname(reference_file), const.DATABASE_FILENAME)
1210
+ qualified_database_filename = os.path.join(get_package_path(), const.DATABASE_FILENAME)
1205
1211
 
1206
1212
  return qualified_database_filename
1207
1213
 
@@ -9,7 +9,7 @@ import os
9
9
  import shutil
10
10
  import sys
11
11
 
12
- import psdi_data_conversion
12
+ from psdi_data_conversion.file_io import get_package_path
13
13
 
14
14
  # Labels for each platform (which we use for the folder in this project), and the head of the name each platform will
15
15
  # have in `sys.platform`
@@ -29,7 +29,7 @@ D_DIST_NAME_HEADS = {LINUX_LABEL: LINUX_NAME_HEAD,
29
29
 
30
30
 
31
31
  # Determine the fully-qualified binary directory when this module is first imported
32
- BIN_DIR: str = os.path.join(psdi_data_conversion.__path__[0], "bin")
32
+ BIN_DIR: str = os.path.join(get_package_path(), "bin")
33
33
 
34
34
 
35
35
  def get_dist():
@@ -7,12 +7,30 @@ Functions and classes related to general filesystem input/output
7
7
 
8
8
  import glob
9
9
  import os
10
+ from functools import lru_cache
10
11
  from shutil import copyfile, make_archive, unpack_archive
11
12
  from tempfile import TemporaryDirectory
12
13
 
13
14
  from psdi_data_conversion import constants as const
14
15
 
15
16
 
17
+ @lru_cache(maxsize=1)
18
+ def get_package_path() -> str:
19
+ """Gets the absolute path to where the `psdi_data_conversion` package is on disk
20
+
21
+ Returns
22
+ -------
23
+ str
24
+ """
25
+
26
+ # For an interactive shell, __file__ won't be defined for this module, so use the constants module instead
27
+ reference_file = os.path.realpath(const.__file__)
28
+
29
+ package_path = os.path.dirname(reference_file)
30
+
31
+ return package_path
32
+
33
+
16
34
  def is_archive(filename: str) -> bool:
17
35
  """Uses a file's extension to check if it's an archive or not
18
36
  """
@@ -9,7 +9,7 @@ import os
9
9
  # Locations relative to the root directory of the project - to ensure the files are found, tests should chdir to this
10
10
  # directory before searching for files
11
11
 
12
- TEST_DATA_LOC_IN_PROJECT = "./test_data"
12
+ TEST_DATA_LOC_IN_PROJECT = "test_data"
13
13
 
14
14
  INPUT_TEST_DATA_LOC_IN_PROJECT = TEST_DATA_LOC_IN_PROJECT
15
15
  OUTPUT_TEST_DATA_LOC_IN_PROJECT = os.path.join(TEST_DATA_LOC_IN_PROJECT, "output")
@@ -11,6 +11,7 @@ import shlex
11
11
  import sys
12
12
  from collections.abc import Callable, Iterable
13
13
  from dataclasses import dataclass, field
14
+ from functools import lru_cache
14
15
  from math import isclose
15
16
  from tempfile import TemporaryDirectory
16
17
  from typing import Any
@@ -19,32 +20,43 @@ from unittest.mock import patch
19
20
  import py
20
21
  import pytest
21
22
 
22
- import psdi_data_conversion
23
23
  from psdi_data_conversion.constants import CONVERTER_DEFAULT, GLOBAL_LOG_FILENAME, LOG_NONE, OUTPUT_LOG_EXT
24
24
  from psdi_data_conversion.converter import run_converter
25
25
  from psdi_data_conversion.converters.openbabel import COORD_GEN_KEY, COORD_GEN_QUAL_KEY
26
26
  from psdi_data_conversion.database import get_format_info
27
27
  from psdi_data_conversion.dist import LINUX_LABEL, get_dist
28
- from psdi_data_conversion.file_io import is_archive, split_archive_ext
28
+ from psdi_data_conversion.file_io import get_package_path, is_archive, split_archive_ext
29
29
  from psdi_data_conversion.main import main as data_convert_main
30
30
  from psdi_data_conversion.testing.constants import (INPUT_TEST_DATA_LOC_IN_PROJECT, OUTPUT_TEST_DATA_LOC_IN_PROJECT,
31
31
  TEST_DATA_LOC_IN_PROJECT)
32
32
 
33
33
 
34
- def get_path_in_project(filename):
35
- """Get the realpath to a file contained within the project, given its project-relative path"""
34
+ @lru_cache(maxsize=1)
35
+ def get_project_path() -> str:
36
+ """Gets the absolute path to where the project is on disk, using the package path to find it and checking that it
37
+ contains the expected files
38
+
39
+ Returns
40
+ -------
41
+ str
42
+ """
36
43
 
37
- old_cwd = os.getcwd()
44
+ project_path = os.path.abspath(os.path.join(get_package_path(), ".."))
38
45
 
39
- try:
40
- os.chdir(os.path.join(psdi_data_conversion.__path__[0], ".."))
41
- realpath = os.path.realpath(filename)
46
+ # Check that the project path contains the expected test_data folder
47
+ if not os.path.isdir(os.path.join(project_path, TEST_DATA_LOC_IN_PROJECT)):
48
+ raise FileNotFoundError(f"Project path was expected to be '{project_path}', but this does not contain the "
49
+ f"expected directory '{TEST_DATA_LOC_IN_PROJECT}'")
42
50
 
43
- finally:
44
- # Change back to the previous directory
45
- os.chdir(old_cwd)
51
+ return project_path
52
+
53
+
54
+ def get_path_in_project(filename):
55
+ """Get the realpath to a file contained within the project, given its project-relative path"""
56
+
57
+ abs_path = os.path.abspath(os.path.join(get_project_path(), filename))
46
58
 
47
- return realpath
59
+ return abs_path
48
60
 
49
61
 
50
62
  def get_test_data_loc():
@@ -567,7 +579,7 @@ def check_file_match(filename: str, ex_filename: str) -> str:
567
579
 
568
580
  # Read in both files
569
581
  text = open(filename, "r").read()
570
- ex_text = open(ex_filename, "r").read()
582
+ ex_text = open(get_path_in_project(ex_filename), "r").read()
571
583
 
572
584
  # We want to check they're the same without worrying about whitespace (which doesn't matter for this format),
573
585
  # so we accomplish this by using the string's `split` method, which splits on whitespace by default
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: psdi_data_conversion
3
- Version: 0.2.0
3
+ Version: 0.2.2
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/
@@ -241,6 +241,8 @@ Requires-Dist: pytest; extra == 'gui-test'
241
241
  Requires-Dist: requests; extra == 'gui-test'
242
242
  Requires-Dist: selenium; extra == 'gui-test'
243
243
  Requires-Dist: webdriver-manager; extra == 'gui-test'
244
+ Provides-Extra: plots
245
+ Requires-Dist: matplotlib; extra == 'plots'
244
246
  Provides-Extra: test
245
247
  Requires-Dist: coverage; extra == 'test'
246
248
  Requires-Dist: pytest; extra == 'test'
@@ -251,7 +253,7 @@ Description-Content-Type: text/markdown
251
253
  [![License Badge](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
252
254
  ![Coverage Badge](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/brgillis/dbd938192dc4de9b7779978e515c0e79/raw/covbadge.json)
253
255
 
254
- Release date: 2024-04-29
256
+ Release date: 2024-06-03
255
257
 
256
258
  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:
257
259
 
@@ -1,10 +1,10 @@
1
1
  psdi_data_conversion/__init__.py,sha256=urMsTqsTHTch1q4rMT9dgGnrvdPFMP9B8r-6Kr8H5sE,404
2
2
  psdi_data_conversion/app.py,sha256=VmZlIAZ_J9W6p_WUcTA_2UNmZxssmq1aT72I2d1ObDc,3606
3
- psdi_data_conversion/constants.py,sha256=w-P3QrS2MQm3gorqZfKqX15YhOTvqZSZ7h6pdxwlzao,7348
3
+ psdi_data_conversion/constants.py,sha256=eXE43_9YFahoehiUV7FtqN9MKb-UpSfY2win9ic9W8I,7348
4
4
  psdi_data_conversion/converter.py,sha256=OlwGKxI8nj76wrlVzP5S7fpXb6L-Ql8-mYLYGhW81Fk,27816
5
- psdi_data_conversion/database.py,sha256=86jxDXNnyo44lUg78IvwmhyoZaNzNCL9crSZbzcokm4,65284
6
- psdi_data_conversion/dist.py,sha256=LOcKEP7H7JA9teX1m-5awuBi69gmdhtUit7yxtCTOZ8,2293
7
- psdi_data_conversion/file_io.py,sha256=LvdPmnYL_7Xlcr-7LJjUbbky4gKiqTTvPRzdbtvQaJo,8794
5
+ psdi_data_conversion/database.py,sha256=0hSuvjpgj6OApNXhEPTzD4VAS8UY00RdtpFkaFsVXho,65564
6
+ psdi_data_conversion/dist.py,sha256=Db7mbLLANfugaptrcWCoVddwHT2rdP4X4HuP6uxr9AI,2309
7
+ psdi_data_conversion/file_io.py,sha256=SE7cXVedm5ZLdxDQ7W7L2R9LXTqJz2Tak9-YTvc7_js,9250
8
8
  psdi_data_conversion/log_utility.py,sha256=CHAq-JvBnTKaE0SHK5hM5j2dTbfSli4iUc3hsf6dBhc,8789
9
9
  psdi_data_conversion/main.py,sha256=LWiYiELF_LY1GghQLt37eZS3ZNojmwHWuSnAhe3qbDI,44768
10
10
  psdi_data_conversion/security.py,sha256=wjdrMre29TpkF2NqrsXJ5sschSAnDzqLYTLUcNR21Qw,902
@@ -17,7 +17,7 @@ psdi_data_conversion/bin/mac/atomsk,sha256=pqExRdkR8NSqSasHZjE74R_CiM6Dkr_yvfyak
17
17
  psdi_data_conversion/bin/mac/c2x,sha256=dI-bBoQ6uqc6KMYKJaq0x7ejJgOf_wysTxQA5BrF8AY,2581960
18
18
  psdi_data_conversion/converters/__init__.py,sha256=15Ldt06eyZ0bgNPB4qg419U0Zcjt6TUCTzjCBo8EIzM,210
19
19
  psdi_data_conversion/converters/atomsk.py,sha256=_V33me1e4HW0-YXvdE-z6PdwtSK2gYV6QZf5d8aPqH4,1523
20
- psdi_data_conversion/converters/base.py,sha256=0hK9IeC306zvQ1qAWb19eI_m_e6CA8TfuEoWgypimeo,36403
20
+ psdi_data_conversion/converters/base.py,sha256=yGlwQmYcLSKP9DH2reTBGvJ-HhfxjO_dYo6qVX501Zw,36515
21
21
  psdi_data_conversion/converters/c2x.py,sha256=jDA84H8Jpz--ajTWNWX6K6oMfOMMbMxkA31-VnGi0gU,2019
22
22
  psdi_data_conversion/converters/openbabel.py,sha256=OYppOMfnvxmVgRY5vUkcVokWn-bQSSeG8MOFqN1MCIY,13224
23
23
  psdi_data_conversion/gui/__init__.py,sha256=Q52GAaJWfNWGDOAEM_fIfAoivLIgM3krhVTiHFTRixM,125
@@ -82,13 +82,13 @@ psdi_data_conversion/templates/documentation.htm,sha256=BeEPgklJOB9tA6jna0Qp4lwR
82
82
  psdi_data_conversion/templates/index.htm,sha256=zY9zihO6adJwLU8bB-iaz0AAsRvg24CNx2gVXJFqNLw,7858
83
83
  psdi_data_conversion/templates/report.htm,sha256=bru_5EtKqHtKnQ3JB9HpTdK047zCwd5akTLQr2pGd5c,5612
84
84
  psdi_data_conversion/testing/__init__.py,sha256=Xku7drtLTYLLPsd403eC0LIEa_iohVifyeyAITy2w7U,135
85
- psdi_data_conversion/testing/constants.py,sha256=BtIafruSobZ9cFY0VW5Bu209eiftnN8b3ObouZBrFQU,521
85
+ psdi_data_conversion/testing/constants.py,sha256=uYUp3FIwoXG_mDFgitpv0bD5M3xK5ThVm9fUHooons0,519
86
86
  psdi_data_conversion/testing/conversion_callbacks.py,sha256=ATR-_BsYCUN8KyOyUjfdWCELzySxLN5jOI0JyrQnmHQ,18858
87
87
  psdi_data_conversion/testing/conversion_test_specs.py,sha256=PFzTZYonQ0PsZBKjcn0Hp-UPbwphT3zRH5v-VdNImmQ,27585
88
88
  psdi_data_conversion/testing/gui.py,sha256=ul7ixYANIzmOG2ZNOZmQO6wsHmGHdiBGAlw-KuoN0j8,19085
89
- psdi_data_conversion/testing/utils.py,sha256=A2CDiGr4Gah1eRvGwFmHt1m0F7RdXOxzCuTyYhcAIR4,26122
90
- psdi_data_conversion-0.2.0.dist-info/METADATA,sha256=_GG0nAM1Dm9QdA5DW9UZVPWf9izJNgwKqj7OeNfy9pU,48472
91
- psdi_data_conversion-0.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
92
- psdi_data_conversion-0.2.0.dist-info/entry_points.txt,sha256=xL7XTzaPRr2E67WhOD1M1Q-76hB8ausQlnNiHzuZQPA,123
93
- psdi_data_conversion-0.2.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
94
- psdi_data_conversion-0.2.0.dist-info/RECORD,,
89
+ psdi_data_conversion/testing/utils.py,sha256=uhJQUceaNmpQd3SioFLZVMExMVzO3Ds8V9DD2hqP-mQ,26700
90
+ psdi_data_conversion-0.2.2.dist-info/METADATA,sha256=pIAVKNVVo-_VO3lbTA-MTvuR7t9LvUfHoIj0CD30imw,48538
91
+ psdi_data_conversion-0.2.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
92
+ psdi_data_conversion-0.2.2.dist-info/entry_points.txt,sha256=xL7XTzaPRr2E67WhOD1M1Q-76hB8ausQlnNiHzuZQPA,123
93
+ psdi_data_conversion-0.2.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
94
+ psdi_data_conversion-0.2.2.dist-info/RECORD,,