Module psdi_data_conversion.utils
utils.py
Miscellaneous utility functions used by this project
Functions
def confirm_editable_mode()-
Expand source code
def confirm_editable_mode(): """Checks if the `psdi_data_conversion` module is installed in editable mode, and exits the program if not """ if not in_editable_mode(): print_wrap(f"{TextColors.RED}ERROR:{TextColors.OFF} To run this script, the package must be installed in " f"editable mode. Please reinstall with:\n") print_wrap("pip install --editable .\n", color=TextColors.WARNING) print_wrap("and re-run this script.") exit(1)Checks if the
psdi_data_conversionmodule is installed in editable mode, and exits the program if not def disable_colors()-
Expand source code
def disable_colors(): """Globally disable color formatting in output text""" tc.disable()Globally disable color formatting in output text
def displaylen(s: str)-
Expand source code
def displaylen(s: str): """Get the length of a string as it would be displayed in the terminal - this is, stripping out control codes""" return len(strip_control_codes(s))Get the length of a string as it would be displayed in the terminal - this is, stripping out control codes
def enable_colors()-
Expand source code
def enable_colors(): """Globally (re)enable color formatting in output text""" tc.enable()Globally (re)enable color formatting in output text
def get_project_path() ‑> pathlib.Path-
Expand source code
@lru_cache(maxsize=1) def get_project_path() -> Path: """Gets the absolute path to where the project is on disk, using the package path to find it and checking that it contains the expected files """ project_path = (get_package_path() / "..").resolve() # Check that the project path contains the expected test_data folder if not (project_path / "pyproject.toml").is_file(): raise FileNotFoundError(f"Project path was expected to be '{project_path}', but this does not contain the " f"expected file 'pyproject.toml'") return project_pathGets the absolute path to where the project is on disk, using the package path to find it and checking that it contains the expected files
def get_wrapped_str(s: str, color: str | None = None, **kwargs)-
Expand source code
def get_wrapped_str(s: str, color: str | None = None, **kwargs): """Get a string wrapped to the terminal width""" if color: s_colored = color+s+TextColors.OFF else: s_colored = s return wraptext.fill(s_colored, width=TERM_WIDTH, **kwargs)Get a string wrapped to the terminal width
def in_editable_mode()-
Expand source code
def in_editable_mode(): """Checks if the `psdi_data_conversion` module is installed in editable mode """ direct_url = Distribution.from_name("psdi_data_conversion").read_text("direct_url.json") is_editable: bool = json.loads(direct_url).get("dir_info", {}).get("editable", False) return is_editableChecks if the
psdi_data_conversionmodule is installed in editable mode def print_header(s: str, **kwargs)-
Expand source code
def print_header(s: str, **kwargs): """Print a string formatted as a header""" print_wrap(f"\n{tc.HEADER}{s}{tc.OFF}", newline=True, initial_indent=" "*2, subsequent_indent=" "*2, **kwargs)Print a string formatted as a header
def print_wrap(s: str, newline=False, err=False, **kwargs)-
Expand source code
def print_wrap(s: str, newline=False, err=False, **kwargs): """Print a string wrapped to the terminal width """ code_re = re.compile("(" + tc.CODE.replace('[', r'\[') + "`.*?`" + tc.OFF.replace('[', r'\[') + ")") if err: file = sys.stderr else: file = sys.stdout for line in s.split("\n"): # Check for any code segments in the line l_segments = code_re.split(line) if len(l_segments) == 1: print(get_wrapped_str(line, **kwargs), file=file) else: # Make all code segments non-breaking while determining the wrap, then undo it when printing non_breaking_line = "" for i, segment in enumerate(l_segments): if i % 2 == 0: non_breaking_line += segment else: non_breaking_line += segment.replace(" ", "\u00a0").replace("-", "\u2011") wrapped_line = get_wrapped_str(non_breaking_line, break_long_words=False, **kwargs).replace("\u00a0", " ").replace("\u2011", "-") print(wrapped_line, file=file) if newline: print("")Print a string wrapped to the terminal width
def regularize_name(name: str)-
Expand source code
def regularize_name(name: str): """Regularizes a name for comparisons, making it lowercase and stripping spaces Parameters ---------- name : str The name, e.g. "Open Babel" Returns ------- str The regularized name, e.g. "openbabel" """ return name.lower().replace(" ", "")Regularizes a name for comparisons, making it lowercase and stripping spaces
Parameters
name:str- The name, e.g. "Open Babel"
Returns
str- The regularized name, e.g. "openbabel"
def replace_extension(filename: str, new_ext: str)-
Expand source code
def replace_extension(filename: str, new_ext: str): """Replace the extension of a filename with a new extension""" # Get the extension with a full-stop at the beginning if new_ext.startswith("."): ext = new_ext else: ext = "." + new_ext return strip_extension(filename) + extReplace the extension of a filename with a new extension
def strip_control_codes(s: str)-
Expand source code
def strip_control_codes(s: str): """Strip all control codes from a string""" return CONTROL_CODE_RE.sub("", str(s))Strip all control codes from a string
def strip_extension(filename: str)-
Expand source code
def strip_extension(filename: str): """Strip all extensions from a filename""" last_stripped_filename = filename stripped_filename, _ = os.path.splitext(filename) while stripped_filename != last_stripped_filename: last_stripped_filename = stripped_filename stripped_filename, _ = os.path.splitext(stripped_filename) return stripped_filenameStrip all extensions from a filename
Classes
class CustomHelpFormatter (prog, indent_increment=2, max_help_position=24, width=None)-
Expand source code
class CustomHelpFormatter(argparse.HelpFormatter): """Custom formatter for argparse """ def _format_action(self, action): return super()._format_action(action) + "\n"Custom formatter for argparse
Ancestors
- argparse.HelpFormatter
class TextColors-
Expand source code
class TextColors: """ANSI escape codes that can be used to color text printed to the terminal. E.g. to give text the header color, you could do `print(f"{TextColors.MAGENTA}Header text{TextColors.OFF}")` """ # Text color codes RED = ERROR = FAIL = "\033[91m" """Start coloring red""" DARKRED = "\033[31m" """Start coloring dark red""" GREEN = SUCCESS = "\033[92m" """Start coloring green""" DARKGREEN = "\033[32m" """Start coloring dark green""" YELLOW = CODE = "\033[93m" """Start coloring yellow""" DARKYELLOW = WARNING = "\033[33m" """Start coloring dark yellow""" BLUE = PATH = ID = "\033[94m" """Start coloring blue""" DARKBLUE = "\033[34m" """Start coloring dark blue""" MAGENTA = "\033[95m" """Start coloring magenta""" DARKMAGENTA = "\033[35m" """Start coloring dark magenta""" CYAN = MESSAGE = NUMBER = "\033[96m" """Start coloring cyan""" DARKCYAN = DARKNUMBER = "\033[36m" """Start coloring dark cyan""" # Text formatting codes BOLD = "\033[1m" """Start formatting bold - NOT compatible with coloring""" DIM = "\033[2m" """Start formatting dim (opposite of bold) - NOT compatible with coloring""" UNDERLINE = "\033[4m" """Start underlining - compatible with coloring""" # Combined codes HEADER = "\033[95m\033[4m" """Start header section - magenta underlined""" LINK = "\033[96m\033[4m" """Start link - cyan underlined""" # Other codes OFF = "\033[0m" """End all coloring and formatting""" @classmethod def _get_codes(cls): return [x for x in dir(cls) if not x.startswith("_") and x.upper() == x] def display(self): """Displays all color codes""" l_codes_and_vals = [(x, getattr(self, x)) for x in self._get_codes()] l_codes_and_vals.sort(key=lambda x: int(x[1].replace("\033[", "").replace("m", "")) if x[1] else x[0]) for code, val in l_codes_and_vals: print(f"{val}{code}{self.OFF}") def enable(self): """Enable colors""" l_codes = self._get_codes() for code in l_codes: setattr(self, code, getattr(type(self), code)) def disable(self): """Disable colors""" l_codes = self._get_codes() for code in l_codes: setattr(self, code, "")ANSI escape codes that can be used to color text printed to the terminal. E.g. to give text the header color, you could do
print(f"{TextColors.MAGENTA}Header text{TextColors.OFF}")Class variables
var BLUEvar BOLD-
Start formatting bold - NOT compatible with coloring
var CODEvar CYANvar DARKBLUE-
Start coloring dark blue
var DARKCYANvar DARKGREEN-
Start coloring dark green
var DARKMAGENTA-
Start coloring dark magenta
var DARKNUMBERvar DARKRED-
Start coloring dark red
var DARKYELLOWvar DIM-
Start formatting dim (opposite of bold) - NOT compatible with coloring
var ERRORvar FAILvar GREENvar HEADER-
Start header section - magenta underlined
var IDvar LINK-
Start link - cyan underlined
var MAGENTA-
Start coloring magenta
var MESSAGEvar NUMBERvar OFF-
End all coloring and formatting
var PATHvar REDvar SUCCESSvar UNDERLINE-
Start underlining - compatible with coloring
var WARNINGvar YELLOW
Methods
def disable(self)-
Expand source code
def disable(self): """Disable colors""" l_codes = self._get_codes() for code in l_codes: setattr(self, code, "")Disable colors
def display(self)-
Expand source code
def display(self): """Displays all color codes""" l_codes_and_vals = [(x, getattr(self, x)) for x in self._get_codes()] l_codes_and_vals.sort(key=lambda x: int(x[1].replace("\033[", "").replace("m", "")) if x[1] else x[0]) for code, val in l_codes_and_vals: print(f"{val}{code}{self.OFF}")Displays all color codes
def enable(self)-
Expand source code
def enable(self): """Enable colors""" l_codes = self._get_codes() for code in l_codes: setattr(self, code, getattr(type(self), code))Enable colors