Source code for SDF.CLI.convert

import argparse
import glob
import logging
import os
import platform
import sys
import textwrap
from enum import Enum
from typing import List, Type

from SDF.file_io import InputFormat, SDFConverter

logging.basicConfig()  # initialize logging system
logger = logging.getLogger(__name__)


IGNORE_SUFFIXES = (
    ".oif.files",
    ".oif.files/",
    ".oif.files\\",
)


def _get_enum_names(enum_class: Type[Enum]) -> List[str]:
    return list(enum_class.__members__.keys())


[docs]def main(): # define args # noinspection PyTypeChecker # Type stubs for formatter_class are wrong # See https://docs.python.org/3/library/argparse.html#argparse.RawDescriptionHelpFormatter for example usage parser = argparse.ArgumentParser( description=textwrap.dedent("Converts files into .sdf and possibly additional formats. " "See details and examples below."), epilog=textwrap.dedent("""\ additional formats: if input is force distance curve (currently supported for .ibw and .jpk-force files) .force.sdf (unless --no-force is set) .mat (if --mat is set) examples: sdf-convert *.lsm converts all .lsm files in the current directory to .sdf results will be placed alongside the original files sdf-convert *.jpk-force -o sdf converts all .jpk-force files to .sdf and .force.sdf results will be placed in directory ./sdf sdf-convert *.jpk-force --no-force --mat converts all .jpk files to .sdf and .mat sdf-convert * converts all files in the current directory to .sdf (and .force.sdf, if possible) infers input type from individual file extension (fails for invalid inputs like .mat files) sdf-convert --input-format OIB oib-file-without-extension reads file `oib-file-without-extension` as .oib file and converts it to .sdf """), formatter_class=argparse.RawDescriptionHelpFormatter, ) parser.add_argument("input_files", metavar="input-files", nargs="+", help="Files to convert") parser.add_argument("-i", "--input-format", help=f"Input format (default: infer for each file)", choices=_get_enum_names(InputFormat)) parser.add_argument("-o", "--output-directory", help=f"The output directory (default: same as input files)", default=None) parser.add_argument("--no-force", help="Generate no additional .force.sdf file (only for force distance curves)", action="store_true") parser.add_argument("--mat", help="Generate an additional .mat file (only for force distance curves)", action="store_true") parser.add_argument("-p", "--progress", help="Show progress", action="store_true") parser.add_argument("-v", "--verbose", help="Set logging level to INFO", action="store_true") parser.add_argument("-d", "--debug", help="Set logging level to DEBUG (implies --verbose)", action="store_true") parser.add_argument("-s", "--silent", help="Set logging level to ERROR (silences warnings)", action="store_true") parser.add_argument("--dry-run", help="Perform conversions without writing the results", action="store_true") # parse args args = parser.parse_args() converter = SDFConverter(input_format=args.input_format, output_directory=args.output_directory, generate_mat=args.mat, generate_force=not args.no_force, dry_run=args.dry_run) filenames = args.input_files # set logging level log_level = logging.WARNING if args.silent: log_level = logging.ERROR if args.debug: log_level = logging.DEBUG elif args.verbose: log_level = logging.INFO logging.getLogger().setLevel(log_level) # set log level of root logger (propagated down to all other loggers) # do conversion try: # check if input is a directory if len(filenames) == 1 and os.path.isdir(filenames[0]): if filenames[0].endswith(os.path.sep): suggestion = filenames[0] + "*" else: suggestion = filenames[0] + os.path.sep + "*" print(f"'{filenames[0]}' is a directory. Did you mean '{suggestion}'?", file=sys.stderr) return 1 # glob-expand patterns if on Windows if platform.system() == "Windows": original_filenames = filenames if isinstance(original_filenames, str): filenames = glob.glob(original_filenames) else: filenames = [] for filename in original_filenames: filenames.extend(glob.glob(filename)) logger.info(f"glob-expanded {original_filenames}") # filter filenames convert_filenames = [] for filename in filenames: if filename.endswith(tuple(IGNORE_SUFFIXES)): logger.info(f"Skipping {filename} because it matches the suffix blacklist") continue convert_filenames.append(filename) # convert for filenum, filename in enumerate(convert_filenames, start=1): if args.progress: print(f"File {filenum}/{len(convert_filenames)}: {filename}") try: converter.convert_file(filename) except KeyboardInterrupt: # do not print exception traceback print("\rInterrupted by keyboard") return 1 return 0 except Exception as exc: if args.debug: raise else: print(f"An error occurred: {exc!r}\n" "If you are sure this should have worked, please contact the maintainers.\n" "To see the full traceback, run again with '--debug'.", file=sys.stderr) return 2