psdi-data-conversion 0.0.36__py3-none-any.whl → 0.0.38__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- psdi_data_conversion/app.py +122 -16
- psdi_data_conversion/constants.py +6 -5
- psdi_data_conversion/converter.py +13 -6
- psdi_data_conversion/converters/base.py +58 -55
- psdi_data_conversion/converters/c2x.py +1 -0
- psdi_data_conversion/converters/openbabel.py +10 -10
- psdi_data_conversion/database.py +335 -113
- psdi_data_conversion/main.py +151 -69
- psdi_data_conversion/static/content/download.htm +22 -9
- psdi_data_conversion/static/javascript/data.js +18 -4
- psdi_data_conversion/static/javascript/format.js +22 -9
- psdi_data_conversion/static/styles/psdi-common.css +5 -4
- psdi_data_conversion/templates/index.htm +59 -45
- psdi_data_conversion/testing/constants.py +9 -3
- psdi_data_conversion/testing/conversion_callbacks.py +9 -7
- psdi_data_conversion/testing/conversion_test_specs.py +128 -27
- psdi_data_conversion/testing/gui.py +428 -0
- psdi_data_conversion/testing/utils.py +121 -60
- {psdi_data_conversion-0.0.36.dist-info → psdi_data_conversion-0.0.38.dist-info}/METADATA +160 -60
- {psdi_data_conversion-0.0.36.dist-info → psdi_data_conversion-0.0.38.dist-info}/RECORD +23 -22
- {psdi_data_conversion-0.0.36.dist-info → psdi_data_conversion-0.0.38.dist-info}/WHEEL +1 -1
- {psdi_data_conversion-0.0.36.dist-info → psdi_data_conversion-0.0.38.dist-info}/entry_points.txt +1 -0
- {psdi_data_conversion-0.0.36.dist-info → psdi_data_conversion-0.0.38.dist-info}/licenses/LICENSE +0 -0
psdi_data_conversion/main.py
CHANGED
@@ -7,6 +7,7 @@ Created 2025-01-14 by Bryan Gillis.
|
|
7
7
|
Entry-point file for the command-line interface for data conversion.
|
8
8
|
"""
|
9
9
|
|
10
|
+
from itertools import product
|
10
11
|
import logging
|
11
12
|
from argparse import ArgumentParser
|
12
13
|
import os
|
@@ -17,10 +18,10 @@ from psdi_data_conversion import constants as const
|
|
17
18
|
from psdi_data_conversion.constants import CL_SCRIPT_NAME, CONVERTER_DEFAULT, TERM_WIDTH
|
18
19
|
from psdi_data_conversion.converter import (D_CONVERTER_ARGS, D_SUPPORTED_CONVERTERS, L_REGISTERED_CONVERTERS,
|
19
20
|
L_SUPPORTED_CONVERTERS, run_converter)
|
20
|
-
from psdi_data_conversion.converters.base import (FileConverterAbortException,
|
21
|
-
|
22
|
-
from psdi_data_conversion.database import (get_conversion_quality, get_converter_info, get_format_info,
|
23
|
-
get_in_format_args, get_out_format_args,
|
21
|
+
from psdi_data_conversion.converters.base import (FileConverterAbortException, FileConverterException,
|
22
|
+
FileConverterInputException)
|
23
|
+
from psdi_data_conversion.database import (FormatInfo, get_conversion_quality, get_converter_info, get_format_info,
|
24
|
+
get_in_format_args, get_out_format_args, get_possible_conversions,
|
24
25
|
get_possible_formats)
|
25
26
|
from psdi_data_conversion.file_io import split_archive_ext
|
26
27
|
from psdi_data_conversion.log_utility import get_log_level_from_str
|
@@ -84,9 +85,21 @@ class ConvertArgs:
|
|
84
85
|
try:
|
85
86
|
self.log_level = get_log_level_from_str(args.log_level)
|
86
87
|
except ValueError as e:
|
87
|
-
# A ValueError indicates an unrecognised logging level, so we reraise this
|
88
|
+
# A ValueError indicates an unrecognised logging level, so we reraise this with the help flag to
|
88
89
|
# indicate we want to provide this as feedback to the user so they can correct their command
|
89
|
-
raise
|
90
|
+
raise FileConverterInputException(str(e), help=True)
|
91
|
+
|
92
|
+
# If formats were provided as ints, convert them to the int type now
|
93
|
+
try:
|
94
|
+
if self.from_format:
|
95
|
+
self.from_format = int(self.from_format)
|
96
|
+
except ValueError:
|
97
|
+
pass
|
98
|
+
try:
|
99
|
+
if self.to_format:
|
100
|
+
self.to_format = int(self.to_format)
|
101
|
+
except ValueError:
|
102
|
+
pass
|
90
103
|
|
91
104
|
# Special handling for listing converters
|
92
105
|
if self.list:
|
@@ -114,40 +127,40 @@ class ConvertArgs:
|
|
114
127
|
# Check validity of input
|
115
128
|
|
116
129
|
if len(self.l_args) == 0:
|
117
|
-
raise
|
130
|
+
raise FileConverterInputException("One or more names of files to convert must be provided", help=True)
|
118
131
|
|
119
132
|
if self._input_dir is not None and not os.path.isdir(self._input_dir):
|
120
|
-
raise
|
121
|
-
|
133
|
+
raise FileConverterInputException(f"The provided input directory '{self._input_dir}' does not exist as a "
|
134
|
+
"directory", help=True)
|
122
135
|
|
123
136
|
if self.to_format is None:
|
124
137
|
msg = textwrap.fill("ERROR Output format (-t or --to) must be provided. For information on supported "
|
125
138
|
"formats and converters, call:\n")
|
126
139
|
msg += f"{CL_SCRIPT_NAME} -l"
|
127
|
-
raise
|
140
|
+
raise FileConverterInputException(msg, msg_preformatted=True, help=True)
|
128
141
|
|
129
142
|
# If the output directory doesn't exist, silently create it
|
130
143
|
if self._output_dir is not None and not os.path.isdir(self._output_dir):
|
131
144
|
if os.path.exists(self._output_dir):
|
132
|
-
raise
|
133
|
-
|
145
|
+
raise FileConverterInputException(f"Output directory '{self._output_dir}' exists but is not a "
|
146
|
+
"directory", help=True)
|
134
147
|
os.makedirs(self._output_dir, exist_ok=True)
|
135
148
|
|
136
149
|
# Check the converter is recognized
|
137
150
|
if self.name not in L_SUPPORTED_CONVERTERS:
|
138
151
|
msg = textwrap.fill(f"ERROR: Converter '{self.name}' not recognised", width=TERM_WIDTH)
|
139
152
|
msg += f"\n\n{get_supported_converters()}"
|
140
|
-
raise
|
153
|
+
raise FileConverterInputException(msg, help=True, msg_preformatted=True)
|
141
154
|
elif self.name not in L_REGISTERED_CONVERTERS:
|
142
155
|
msg = textwrap.fill(f"ERROR: Converter '{self.name}' is not registered. It may be possible to register "
|
143
156
|
"it by installing an appropriate binary for your platform.", width=TERM_WIDTH)
|
144
157
|
msg += f"\n\n{get_supported_converters()}"
|
145
|
-
raise
|
158
|
+
raise FileConverterInputException(msg, help=True, msg_preformatted=True)
|
146
159
|
|
147
160
|
# Logging mode is valid
|
148
161
|
if self.log_mode not in const.L_ALLOWED_LOG_MODES:
|
149
|
-
raise
|
150
|
-
|
162
|
+
raise FileConverterInputException(f"Unrecognised logging mode: {self.log_mode}. Allowed "
|
163
|
+
f"modes are: {const.L_ALLOWED_LOG_MODES}", help=True)
|
151
164
|
|
152
165
|
# Arguments specific to this converter
|
153
166
|
self.d_converter_args = {}
|
@@ -194,10 +207,10 @@ class ConvertArgs:
|
|
194
207
|
if os.path.isfile(test_filename):
|
195
208
|
first_filename = test_filename
|
196
209
|
else:
|
197
|
-
raise
|
198
|
-
|
210
|
+
raise FileConverterInputException(f"Input file {first_filename} cannot be found. Also "
|
211
|
+
f"checked for {test_filename}.", help=True)
|
199
212
|
else:
|
200
|
-
raise
|
213
|
+
raise FileConverterInputException(f"Input file {first_filename} cannot be found.", help=True)
|
201
214
|
|
202
215
|
filename_base = os.path.split(split_archive_ext(first_filename)[0])[1]
|
203
216
|
if self.log_mode == const.LOG_FULL:
|
@@ -345,7 +358,7 @@ def detail_converter_use(args: ConvertArgs):
|
|
345
358
|
print_wrap(converter_class.info, break_long_words=False, break_on_hyphens=False, newline=True)
|
346
359
|
|
347
360
|
# If both an input and output format are specified, provide the degree of success for this conversion. Otherwise
|
348
|
-
# list possible input
|
361
|
+
# list possible input/output formats
|
349
362
|
if args.from_format is not None and args.to_format is not None:
|
350
363
|
qual = get_conversion_quality(args.name, args.from_format, args.to_format)
|
351
364
|
if qual is None:
|
@@ -375,19 +388,19 @@ def detail_converter_use(args: ConvertArgs):
|
|
375
388
|
print_wrap(f"Conversion {to_or_from} {format_name} is {optional_not}supported by {args.name}.\n")
|
376
389
|
|
377
390
|
# List all possible formats, and which can be used for input and which for output
|
378
|
-
s_all_formats: set[
|
391
|
+
s_all_formats: set[FormatInfo] = set(l_input_formats)
|
379
392
|
s_all_formats.update(l_output_formats)
|
380
|
-
l_all_formats: list[
|
381
|
-
l_all_formats.sort(key=lambda
|
393
|
+
l_all_formats: list[FormatInfo] = list(s_all_formats)
|
394
|
+
l_all_formats.sort(key=lambda x: x.disambiguated_name.lower())
|
382
395
|
|
383
396
|
print_wrap(f"File formats supported by {args.name}:", newline=True)
|
384
|
-
max_format_length = max([len(x) for x in l_all_formats])
|
397
|
+
max_format_length = max([len(x.disambiguated_name) for x in l_all_formats])
|
385
398
|
print(" "*(max_format_length+4) + " INPUT OUTPUT")
|
386
399
|
print(" "*(max_format_length+4) + " ----- ------")
|
387
400
|
for file_format in l_all_formats:
|
388
401
|
in_yes_or_no = "yes" if file_format in l_input_formats else "no"
|
389
402
|
out_yes_or_no = "yes" if file_format in l_output_formats else "no"
|
390
|
-
print(f" {file_format:>{max_format_length}}{in_yes_or_no:>8}{out_yes_or_no:>8}")
|
403
|
+
print(f" {file_format.disambiguated_name:>{max_format_length}}{in_yes_or_no:>8}{out_yes_or_no:>8}")
|
391
404
|
print("")
|
392
405
|
|
393
406
|
if converter_class.allowed_flags is None:
|
@@ -472,10 +485,16 @@ def list_supported_formats(err=False):
|
|
472
485
|
"""Prints a list of all formats recognised by at least one registered converter
|
473
486
|
"""
|
474
487
|
# Make a list of all formats recognised by at least one registered converter
|
475
|
-
s_all_formats: set[
|
476
|
-
s_registered_formats: set[
|
488
|
+
s_all_formats: set[FormatInfo] = set()
|
489
|
+
s_registered_formats: set[FormatInfo] = set()
|
477
490
|
for converter_name in L_SUPPORTED_CONVERTERS:
|
478
491
|
l_in_formats, l_out_formats = get_possible_formats(converter_name)
|
492
|
+
|
493
|
+
# To make sure we don't see any unexpected duplicates in the set due to cached/uncached values, get the
|
494
|
+
# disambiguated name of each format first
|
495
|
+
[x.disambiguated_name for x in l_in_formats]
|
496
|
+
[x.disambiguated_name for x in l_out_formats]
|
497
|
+
|
479
498
|
s_all_formats.update(l_in_formats)
|
480
499
|
s_all_formats.update(l_out_formats)
|
481
500
|
if converter_name in L_REGISTERED_CONVERTERS:
|
@@ -486,14 +505,14 @@ def list_supported_formats(err=False):
|
|
486
505
|
|
487
506
|
# Convert the sets to lists and alphabetise them
|
488
507
|
l_registered_formats = list(s_registered_formats)
|
489
|
-
l_registered_formats.sort(key=lambda
|
508
|
+
l_registered_formats.sort(key=lambda x: x.disambiguated_name.lower())
|
490
509
|
l_unregistered_formats = list(s_unregistered_formats)
|
491
|
-
l_unregistered_formats.sort(key=lambda
|
510
|
+
l_unregistered_formats.sort(key=lambda x: x.disambiguated_name.lower())
|
492
511
|
|
493
512
|
# Pad the format strings to all be the same length. To keep columns aligned, all padding is done with non-
|
494
513
|
# breaking spaces (\xa0), and each format is followed by a single normal space
|
495
|
-
longest_format_len = max([len(x) for x in l_registered_formats])
|
496
|
-
l_padded_formats = [f"{x:\xa0<{longest_format_len}} " for x in l_registered_formats]
|
514
|
+
longest_format_len = max([len(x.disambiguated_name) for x in l_registered_formats])
|
515
|
+
l_padded_formats = [f"{x.disambiguated_name:\xa0<{longest_format_len}} " for x in l_registered_formats]
|
497
516
|
|
498
517
|
print_wrap("Formats supported by registered converters: ", err=err, newline=True)
|
499
518
|
print_wrap("".join(l_padded_formats), err=err, initial_indent=" ", subsequent_indent=" ", newline=True)
|
@@ -508,9 +527,33 @@ def list_supported_formats(err=False):
|
|
508
527
|
initial_indent=" ", subsequent_indent=" ", newline=True)
|
509
528
|
|
510
529
|
print_wrap("Note that not all formats are supported with all converters, or both as input and as output.")
|
530
|
+
if err:
|
531
|
+
print("")
|
532
|
+
print_wrap("For more details on a format, call:")
|
533
|
+
print(f"{CL_SCRIPT_NAME} -l -f <format>")
|
511
534
|
|
512
535
|
|
513
|
-
def
|
536
|
+
def detail_format(format_name: str):
|
537
|
+
"""Prints details on a format
|
538
|
+
"""
|
539
|
+
|
540
|
+
l_format_info: list[FormatInfo] = get_format_info(format_name, which="all")
|
541
|
+
|
542
|
+
if len(l_format_info) == 0:
|
543
|
+
print_wrap(f"ERROR: Format '{format_name}' not recognised", err=True, newline=True)
|
544
|
+
list_supported_formats(err=True)
|
545
|
+
exit(1)
|
546
|
+
|
547
|
+
if len(l_format_info) > 1:
|
548
|
+
print_wrap(f"WARNING: Format '{format_name}' is ambiguous and could refer to multiple formats. It may be "
|
549
|
+
"necessary to explicitly specify which you want to use when calling this script, e.g. with "
|
550
|
+
f"'-f {format_name}-0' - see the disambiguated names in the list below:", newline=True)
|
551
|
+
|
552
|
+
for format_info in l_format_info:
|
553
|
+
print_wrap(f"{format_info.id}: {format_info.disambiguated_name} ({format_info.note})")
|
554
|
+
|
555
|
+
|
556
|
+
def detail_formats_and_possible_converters(from_format: str, to_format: str):
|
514
557
|
"""Prints details on converters that can perform a conversion from one format to another
|
515
558
|
"""
|
516
559
|
|
@@ -518,13 +561,13 @@ def detail_possible_converters(from_format: str, to_format: str):
|
|
518
561
|
either_format_failed = False
|
519
562
|
|
520
563
|
try:
|
521
|
-
get_format_info(from_format)
|
564
|
+
get_format_info(from_format, which=0)
|
522
565
|
except KeyError:
|
523
566
|
either_format_failed = True
|
524
567
|
print_wrap(f"ERROR: Input format '{from_format}' not recognised", newline=True, err=True)
|
525
568
|
|
526
569
|
try:
|
527
|
-
get_format_info(to_format)
|
570
|
+
get_format_info(to_format, which=0)
|
528
571
|
except KeyError:
|
529
572
|
either_format_failed = True
|
530
573
|
print_wrap(f"ERROR: Output format '{from_format}' not recognised", newline=True, err=True)
|
@@ -534,32 +577,58 @@ def detail_possible_converters(from_format: str, to_format: str):
|
|
534
577
|
list_supported_formats(err=True)
|
535
578
|
exit(1)
|
536
579
|
|
537
|
-
|
580
|
+
# Provide details on both the input and output formats
|
581
|
+
detail_format(from_format)
|
582
|
+
print()
|
583
|
+
detail_format(to_format)
|
538
584
|
|
539
|
-
|
540
|
-
l_possible_unregistered_converters = [x for x in l_possible_converters if
|
541
|
-
x in L_SUPPORTED_CONVERTERS and x not in L_REGISTERED_CONVERTERS]
|
585
|
+
l_possible_conversions = get_possible_conversions(from_format, to_format)
|
542
586
|
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
"the following converters are supported by this package on other platforms and can perform this "
|
549
|
-
"conversion:", newline=True)
|
550
|
-
print("\n ".join(l_possible_unregistered_converters))
|
551
|
-
return
|
587
|
+
# Get a list of all different formats which share the provided name, cutting out duplicates
|
588
|
+
l_from_formats = list(set([x[1] for x in l_possible_conversions]))
|
589
|
+
l_from_formats.sort(key=lambda x: x.disambiguated_name)
|
590
|
+
l_to_formats = list(set([x[2] for x in l_possible_conversions]))
|
591
|
+
l_to_formats.sort(key=lambda x: x.disambiguated_name)
|
552
592
|
|
553
|
-
|
554
|
-
print(" " + "\n ".join(l_possible_registered_converters) + "\n")
|
555
|
-
if l_possible_unregistered_converters:
|
556
|
-
print("")
|
557
|
-
print_wrap("Additionally, the following converters are supported by this package on other platforms and can "
|
558
|
-
"perform this conversion:", newline=True)
|
559
|
-
print(" " + "\n ".join(l_possible_unregistered_converters) + "\n")
|
593
|
+
# Loop over all possible combinations of formats
|
560
594
|
|
561
|
-
|
562
|
-
|
595
|
+
for possible_from_format, possible_to_format in product(l_from_formats, l_to_formats):
|
596
|
+
|
597
|
+
from_name = possible_from_format.disambiguated_name
|
598
|
+
to_name = possible_to_format.disambiguated_name
|
599
|
+
|
600
|
+
l_conversions_matching_formats = [x for x in l_possible_conversions
|
601
|
+
if x[1] == possible_from_format and x[2] == possible_to_format]
|
602
|
+
|
603
|
+
l_possible_registered_converters = [x[0] for x in l_conversions_matching_formats
|
604
|
+
if x[0] in L_REGISTERED_CONVERTERS]
|
605
|
+
l_possible_unregistered_converters = [x[0] for x in l_conversions_matching_formats
|
606
|
+
if x[0] in L_SUPPORTED_CONVERTERS and x[0] not in L_REGISTERED_CONVERTERS]
|
607
|
+
|
608
|
+
print()
|
609
|
+
|
610
|
+
if len(l_possible_registered_converters)+len(l_possible_unregistered_converters) == 0:
|
611
|
+
print_wrap(f"No converters are available which can perform a conversion from {from_name} to "
|
612
|
+
f"{to_name}")
|
613
|
+
continue
|
614
|
+
elif len(l_possible_registered_converters) == 0:
|
615
|
+
print_wrap(f"No registered converters can perform a conversion from {from_name} to "
|
616
|
+
f"{to_name}, however the following converters are supported by this package on other "
|
617
|
+
"platforms and can perform this conversion:", newline=True)
|
618
|
+
print("\n ".join(l_possible_unregistered_converters))
|
619
|
+
continue
|
620
|
+
|
621
|
+
print_wrap(f"The following registered converters can convert from {from_name} to "
|
622
|
+
f"{to_name}:", newline=True)
|
623
|
+
print(" " + "\n ".join(l_possible_registered_converters) + "\n")
|
624
|
+
if l_possible_unregistered_converters:
|
625
|
+
print("")
|
626
|
+
print_wrap("Additionally, the following converters are supported by this package on other platforms and "
|
627
|
+
"can perform this conversion:", newline=True)
|
628
|
+
print(" " + "\n ".join(l_possible_unregistered_converters) + "\n")
|
629
|
+
|
630
|
+
print_wrap("For details on input/output flags and options allowed by a converter for this conversion, call:")
|
631
|
+
print(f"{CL_SCRIPT_NAME} -l <converter name> -f {from_name} -t {to_name}")
|
563
632
|
|
564
633
|
|
565
634
|
def get_supported_converters():
|
@@ -612,7 +681,13 @@ def detail_converters_and_formats(args: ConvertArgs):
|
|
612
681
|
list_supported_converters(err=True)
|
613
682
|
exit(1)
|
614
683
|
elif args.from_format and args.to_format:
|
615
|
-
|
684
|
+
detail_formats_and_possible_converters(args.from_format, args.to_format)
|
685
|
+
return
|
686
|
+
elif args.from_format:
|
687
|
+
detail_format(args.from_format)
|
688
|
+
return
|
689
|
+
elif args.to_format:
|
690
|
+
detail_format(args.to_format)
|
616
691
|
return
|
617
692
|
|
618
693
|
list_supported_converters()
|
@@ -623,6 +698,9 @@ def detail_converters_and_formats(args: ConvertArgs):
|
|
623
698
|
print_wrap("For more details on a converter, call:")
|
624
699
|
print(f"{CL_SCRIPT_NAME} -l <converter name>\n")
|
625
700
|
|
701
|
+
print_wrap("For more details on a format, call:")
|
702
|
+
print(f"{CL_SCRIPT_NAME} -l -f <format>\n")
|
703
|
+
|
626
704
|
print_wrap("For a list of converters that can perform a desired conversion, call:")
|
627
705
|
print(f"{CL_SCRIPT_NAME} -l -f <input format> -t <output format>\n")
|
628
706
|
|
@@ -693,12 +771,6 @@ def run_from_args(args: ConvertArgs):
|
|
693
771
|
log_level=args.log_level,
|
694
772
|
delete_input=args.delete_input,
|
695
773
|
refresh_local_log=False)
|
696
|
-
except FileConverterHelpException as e:
|
697
|
-
if not e.logged:
|
698
|
-
print_wrap(f"ERROR: {e}", err=True)
|
699
|
-
e.logged = True
|
700
|
-
success = False
|
701
|
-
continue
|
702
774
|
except FileConverterAbortException as e:
|
703
775
|
if not e.logged:
|
704
776
|
print_wrap(f"ERROR: Attempt to convert file {filename} aborted with status code {e.status_code} and "
|
@@ -706,11 +778,19 @@ def run_from_args(args: ConvertArgs):
|
|
706
778
|
e.logged = True
|
707
779
|
success = False
|
708
780
|
continue
|
709
|
-
except
|
710
|
-
if
|
781
|
+
except FileConverterException as e:
|
782
|
+
if e.help and not e.logged:
|
783
|
+
print_wrap(f"ERROR: {e}", err=True)
|
784
|
+
e.logged = True
|
785
|
+
elif "Conversion from" in str(e) and "is not supported" in str(e):
|
711
786
|
if not e.logged:
|
712
787
|
print_wrap(f"ERROR: {e}", err=True, newline=True)
|
713
|
-
|
788
|
+
detail_formats_and_possible_converters(args.from_format, args.to_format)
|
789
|
+
elif e.help and not e.logged:
|
790
|
+
if e.msg_preformatted:
|
791
|
+
print(e, file=sys.stderr)
|
792
|
+
else:
|
793
|
+
print_wrap(f"ERROR: {e}", err=True)
|
714
794
|
elif not e.logged:
|
715
795
|
print_wrap(f"ERROR: Attempt to convert file {filename} failed at converter initialization with "
|
716
796
|
f"exception type {type(e)} and message: \n{e}\n", err=True)
|
@@ -748,9 +828,11 @@ def main():
|
|
748
828
|
|
749
829
|
try:
|
750
830
|
args = parse_args()
|
751
|
-
except
|
752
|
-
|
753
|
-
|
831
|
+
except FileConverterInputException as e:
|
832
|
+
if not e.help:
|
833
|
+
raise
|
834
|
+
# If we get an exception with the help flag set, it's likely due to user error, so don't bother them with a
|
835
|
+
# traceback and simply print the message to stderr
|
754
836
|
if e.msg_preformatted:
|
755
837
|
print(e, file=sys.stderr)
|
756
838
|
else:
|
@@ -43,6 +43,8 @@
|
|
43
43
|
Python library.
|
44
44
|
</p>
|
45
45
|
|
46
|
+
<h2>Installation</h2>
|
47
|
+
|
46
48
|
<h3>Install via pip</h3>
|
47
49
|
|
48
50
|
<ul>
|
@@ -63,12 +65,6 @@
|
|
63
65
|
Python library.
|
64
66
|
</p>
|
65
67
|
|
66
|
-
<p>
|
67
|
-
If you do wish to run the local version of this webpage, you'll need to create a helper script to set up the
|
68
|
-
proper parameters and start the server. See the README provided on the front page of this project's PyPI page,
|
69
|
-
linked above, for the source of this helper script, which you can paste and use locally.
|
70
|
-
</p>
|
71
|
-
|
72
68
|
<h3>Source Code</h3>
|
73
69
|
|
74
70
|
<ul>
|
@@ -86,11 +82,28 @@
|
|
86
82
|
for other possible optional dependencies sets that can be installed.
|
87
83
|
</p>
|
88
84
|
|
89
|
-
<
|
90
|
-
|
91
|
-
|
85
|
+
<h2>Use</h2>
|
86
|
+
|
87
|
+
<p>
|
88
|
+
Once installed, the project can be used in one of three ways:
|
92
89
|
</p>
|
93
90
|
|
91
|
+
<ul>
|
92
|
+
<li><strong>Local Gui:</strong> Run the script <code class="secondary">psdi-data-convert-gui</code> to start the
|
93
|
+
server. Append the <code class="secondary">--help</code> option for to see optional arguments (generally not
|
94
|
+
required for end-users)
|
95
|
+
</li>
|
96
|
+
<li><strong>Command-Line Application:</strong> Run the script <code class="secondary">psdi-data-convert</code>
|
97
|
+
to use the application at the command-line. Append the <code class="secondary">--help</code> option to see
|
98
|
+
arguments for it, and/or find documentation in the project's README.
|
99
|
+
</li>
|
100
|
+
<li><strong>Python Library:</strong> Within a Python script, library, or terminal, the project can be imported
|
101
|
+
via <code class="secondary">import psdi_data_conversion</code>, with the most useful function being <code
|
102
|
+
class="secondary">psdi_data_conversion.converter.run_converter</code> - see the <code
|
103
|
+
class="secondary">help()</code> of this function and/or find documentation in the project's README.
|
104
|
+
</li>
|
105
|
+
</ul>
|
106
|
+
|
94
107
|
<h2>Documentation</h2>
|
95
108
|
|
96
109
|
<ul>
|
@@ -1,7 +1,21 @@
|
|
1
1
|
// data.js
|
2
2
|
|
3
3
|
const response = await fetch("/static/data/data.json");
|
4
|
-
|
4
|
+
|
5
|
+
let data = null;
|
6
|
+
try {
|
7
|
+
data = JSON.parse(await response.text());
|
8
|
+
} catch (err) {
|
9
|
+
console.log("ERROR: Database could not be loaded, error: " + err)
|
10
|
+
}
|
11
|
+
|
12
|
+
/**
|
13
|
+
* Indicates whether or not the database was successfully loaded
|
14
|
+
* @returns {boolean}
|
15
|
+
*/
|
16
|
+
export function databaseLoaded() {
|
17
|
+
return data !== null;
|
18
|
+
}
|
5
19
|
|
6
20
|
const collator = new Intl.Collator();
|
7
21
|
|
@@ -84,7 +98,7 @@ export async function getConverters(inExtension, inNote, outExtension, outNote)
|
|
84
98
|
const inputFormat = (data.formats.filter(format => (format.extension === inExtension) && (format.note === inNote)))[0];
|
85
99
|
const outputFormat = (data.formats.filter(format => (format.extension === outExtension) && (format.note === outNote)))[0];
|
86
100
|
|
87
|
-
if ((inputFormat === undefined) || (outputFormat === undefined))
|
101
|
+
if ((inputFormat === undefined) || (outputFormat === undefined)) {
|
88
102
|
return [];
|
89
103
|
}
|
90
104
|
|
@@ -96,7 +110,7 @@ export async function getConverters(inExtension, inNote, outExtension, outNote)
|
|
96
110
|
name: convertersById.get(conversion.converters_id).name
|
97
111
|
}));
|
98
112
|
|
99
|
-
return convertersWithDegreeOfSuccess.sort((a, b) => compare(a.name, b.name
|
113
|
+
return convertersWithDegreeOfSuccess.sort((a, b) => compare(a.name, b.name));
|
100
114
|
}
|
101
115
|
|
102
116
|
export async function getConverterByName(name) {
|
@@ -170,7 +184,7 @@ export async function getOutputArgFlags(extension, note) {
|
|
170
184
|
export async function getLevelChemInfo(inExtension, inNote, outExtension, outNote) {
|
171
185
|
|
172
186
|
const inputFormat = (data.formats.filter(format => (format.extension === inExtension) && (format.note === inNote)))[0],
|
173
|
-
|
187
|
+
outputFormat = (data.formats.filter(format => (format.extension === outExtension) && (format.note === outNote)))[0];
|
174
188
|
|
175
189
|
return [inputFormat, outputFormat];
|
176
190
|
}
|
@@ -7,7 +7,7 @@
|
|
7
7
|
|
8
8
|
import { disableDirtyForms, cleanDirtyForms, initDirtyForms, loadServiceMode, loadProductionMode } from "./common.js";
|
9
9
|
import {
|
10
|
-
getInputFormats, getOutputFormats, getOutputFormatsForInputFormat,
|
10
|
+
databaseLoaded, getInputFormats, getOutputFormats, getOutputFormatsForInputFormat,
|
11
11
|
getInputFormatsForOutputFormat, getConverters, getConverterByName, getLevelChemInfo
|
12
12
|
} from "./data.js";
|
13
13
|
|
@@ -18,15 +18,20 @@ var fromList = new Array(),
|
|
18
18
|
|
19
19
|
$(document).ready(function () {
|
20
20
|
|
21
|
-
//
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
// Populate the available formats if the database successfully loaded, otherwise display an error message
|
22
|
+
if (databaseLoaded()) {
|
23
|
+
// Populates the "Convert from" selection list
|
24
|
+
getInputFormats().then((formats) => {
|
25
|
+
populateList(formats, "from");
|
26
|
+
});
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
// Populates the "Convert to" selection list
|
29
|
+
getOutputFormats().then((formats) => {
|
30
|
+
populateList(formats, "to");
|
31
|
+
});
|
32
|
+
} else {
|
33
|
+
displayDatabaseLoadError();;
|
34
|
+
}
|
30
35
|
|
31
36
|
sessionStorage.setItem("token", token);
|
32
37
|
sessionStorage.setItem("max_file_size", max_file_size);
|
@@ -52,6 +57,14 @@ $(document).ready(function () {
|
|
52
57
|
initDirtyForms();
|
53
58
|
});
|
54
59
|
|
60
|
+
/**
|
61
|
+
* Hides the format and converter selection and displays an error message that the database could not be loaded.
|
62
|
+
*/
|
63
|
+
function displayDatabaseLoadError() {
|
64
|
+
$("#format-selection").css({ display: "none" });
|
65
|
+
$("#database-error").css({ display: "block" });
|
66
|
+
}
|
67
|
+
|
55
68
|
/**
|
56
69
|
* Gets the input and output extensions and their notes from what's currently selected in the search boxes.
|
57
70
|
* @returns {Array<str>} Input extension, Input note, Output extension, Output note
|
@@ -228,7 +228,7 @@ body {
|
|
228
228
|
top : 0;
|
229
229
|
left : 0;
|
230
230
|
background: var(--ifm-background-color);
|
231
|
-
z-index :
|
231
|
+
z-index : 99999;
|
232
232
|
}
|
233
233
|
|
234
234
|
select,
|
@@ -412,7 +412,8 @@ h6 {
|
|
412
412
|
}
|
413
413
|
|
414
414
|
p {
|
415
|
-
margin: 0 0 1.25rem 0;
|
415
|
+
margin : 0 0 1.25rem 0;
|
416
|
+
padding-bottom: 0;
|
416
417
|
}
|
417
418
|
|
418
419
|
.text--center {
|
@@ -546,9 +547,9 @@ a svg {
|
|
546
547
|
}
|
547
548
|
|
548
549
|
.navbar__title h5 {
|
549
|
-
display:
|
550
|
+
display: flex;
|
550
551
|
color : var(--ifm-heading-color);
|
551
|
-
margin : 0 0 0.5rem
|
552
|
+
margin : 0 0 0.5rem 1.5rem;
|
552
553
|
}
|
553
554
|
|
554
555
|
.navbar__logo img {
|