muutils.misc.string
1from __future__ import annotations 2from typing import Any, Callable, TypeVar 3 4 5from muutils.misc.hashing import stable_hash 6 7 8def sanitize_name( 9 name: str | None, 10 additional_allowed_chars: str = "", 11 replace_invalid: str = "", 12 when_none: str | None = "_None_", 13 leading_digit_prefix: str = "", 14) -> str: 15 """sanitize a string, leaving only alphanumerics and `additional_allowed_chars` 16 17 # Parameters: 18 - `name : str | None` 19 input string 20 - `additional_allowed_chars : str` 21 additional characters to allow, none by default 22 (defaults to `""`) 23 - `replace_invalid : str` 24 character to replace invalid characters with 25 (defaults to `""`) 26 - `when_none : str | None` 27 string to return if `name` is `None`. if `None`, raises an exception 28 (defaults to `"_None_"`) 29 - `leading_digit_prefix : str` 30 character to prefix the string with if it starts with a digit 31 (defaults to `""`) 32 33 # Returns: 34 - `str` 35 sanitized string 36 """ 37 38 if name is None: 39 if when_none is None: 40 raise ValueError("name is None") 41 else: 42 return when_none 43 44 sanitized: str = "" 45 for char in name: 46 if char.isalnum(): 47 sanitized += char 48 elif char in additional_allowed_chars: 49 sanitized += char 50 else: 51 sanitized += replace_invalid 52 53 if sanitized[0].isdigit(): 54 sanitized = leading_digit_prefix + sanitized 55 56 return sanitized 57 58 59def sanitize_fname( 60 fname: str | None, 61 replace_invalid: str = "", 62 when_none: str | None = "_None_", 63 leading_digit_prefix: str = "", 64) -> str: 65 """sanitize a filename to posix standards 66 67 - leave only alphanumerics, `_` (underscore), '-' (dash) and `.` (period) 68 """ 69 return sanitize_name( 70 name=fname, 71 additional_allowed_chars="._-", 72 replace_invalid=replace_invalid, 73 when_none=when_none, 74 leading_digit_prefix=leading_digit_prefix, 75 ) 76 77 78def sanitize_identifier( 79 fname: str | None, 80 replace_invalid: str = "", 81 when_none: str | None = "_None_", 82) -> str: 83 """sanitize an identifier (variable or function name) 84 85 - leave only alphanumerics and `_` (underscore) 86 - prefix with `_` if it starts with a digit 87 """ 88 return sanitize_name( 89 name=fname, 90 additional_allowed_chars="_", 91 replace_invalid=replace_invalid, 92 when_none=when_none, 93 leading_digit_prefix="_", 94 ) 95 96 97def dict_to_filename( 98 data: dict[str, Any], 99 format_str: str = "{key}_{val}", 100 separator: str = ".", 101 max_length: int = 255, 102): 103 # Convert the dictionary items to a list of strings using the format string 104 formatted_items: list[str] = [ 105 format_str.format(key=k, val=v) 106 for k, v in data.items() # pyright: ignore[reportAny] 107 ] 108 109 # Join the formatted items using the separator 110 joined_str: str = separator.join(formatted_items) 111 112 # Remove special characters and spaces 113 sanitized_str: str = sanitize_fname(joined_str) 114 115 # Check if the length is within limits 116 if len(sanitized_str) <= max_length: 117 return sanitized_str 118 119 # If the string is too long, generate a hash 120 return f"h_{stable_hash(sanitized_str)}" 121 122 123T_Callable = TypeVar("T_Callable", bound=Callable[..., Any]) 124 125 126def dynamic_docstring(**doc_params: str) -> Callable[[T_Callable], T_Callable]: 127 def decorator(func: T_Callable) -> T_Callable: 128 if func.__doc__: 129 func.__doc__ = getattr(func, "__doc__", "").format(**doc_params) 130 return func 131 132 return decorator
def
sanitize_name( name: str | None, additional_allowed_chars: str = '', replace_invalid: str = '', when_none: str | None = '_None_', leading_digit_prefix: str = '') -> str:
9def sanitize_name( 10 name: str | None, 11 additional_allowed_chars: str = "", 12 replace_invalid: str = "", 13 when_none: str | None = "_None_", 14 leading_digit_prefix: str = "", 15) -> str: 16 """sanitize a string, leaving only alphanumerics and `additional_allowed_chars` 17 18 # Parameters: 19 - `name : str | None` 20 input string 21 - `additional_allowed_chars : str` 22 additional characters to allow, none by default 23 (defaults to `""`) 24 - `replace_invalid : str` 25 character to replace invalid characters with 26 (defaults to `""`) 27 - `when_none : str | None` 28 string to return if `name` is `None`. if `None`, raises an exception 29 (defaults to `"_None_"`) 30 - `leading_digit_prefix : str` 31 character to prefix the string with if it starts with a digit 32 (defaults to `""`) 33 34 # Returns: 35 - `str` 36 sanitized string 37 """ 38 39 if name is None: 40 if when_none is None: 41 raise ValueError("name is None") 42 else: 43 return when_none 44 45 sanitized: str = "" 46 for char in name: 47 if char.isalnum(): 48 sanitized += char 49 elif char in additional_allowed_chars: 50 sanitized += char 51 else: 52 sanitized += replace_invalid 53 54 if sanitized[0].isdigit(): 55 sanitized = leading_digit_prefix + sanitized 56 57 return sanitized
sanitize a string, leaving only alphanumerics and additional_allowed_chars
Parameters:
name : str | Noneinput stringadditional_allowed_chars : stradditional characters to allow, none by default (defaults to"")replace_invalid : strcharacter to replace invalid characters with (defaults to"")when_none : str | Nonestring to return ifnameisNone. ifNone, raises an exception (defaults to"_None_")leading_digit_prefix : strcharacter to prefix the string with if it starts with a digit (defaults to"")
Returns:
strsanitized string
def
sanitize_fname( fname: str | None, replace_invalid: str = '', when_none: str | None = '_None_', leading_digit_prefix: str = '') -> str:
60def sanitize_fname( 61 fname: str | None, 62 replace_invalid: str = "", 63 when_none: str | None = "_None_", 64 leading_digit_prefix: str = "", 65) -> str: 66 """sanitize a filename to posix standards 67 68 - leave only alphanumerics, `_` (underscore), '-' (dash) and `.` (period) 69 """ 70 return sanitize_name( 71 name=fname, 72 additional_allowed_chars="._-", 73 replace_invalid=replace_invalid, 74 when_none=when_none, 75 leading_digit_prefix=leading_digit_prefix, 76 )
sanitize a filename to posix standards
- leave only alphanumerics,
_(underscore), '-' (dash) and.(period)
def
sanitize_identifier( fname: str | None, replace_invalid: str = '', when_none: str | None = '_None_') -> str:
79def sanitize_identifier( 80 fname: str | None, 81 replace_invalid: str = "", 82 when_none: str | None = "_None_", 83) -> str: 84 """sanitize an identifier (variable or function name) 85 86 - leave only alphanumerics and `_` (underscore) 87 - prefix with `_` if it starts with a digit 88 """ 89 return sanitize_name( 90 name=fname, 91 additional_allowed_chars="_", 92 replace_invalid=replace_invalid, 93 when_none=when_none, 94 leading_digit_prefix="_", 95 )
sanitize an identifier (variable or function name)
- leave only alphanumerics and
_(underscore) - prefix with
_if it starts with a digit
def
dict_to_filename( data: dict[str, typing.Any], format_str: str = '{key}_{val}', separator: str = '.', max_length: int = 255):
98def dict_to_filename( 99 data: dict[str, Any], 100 format_str: str = "{key}_{val}", 101 separator: str = ".", 102 max_length: int = 255, 103): 104 # Convert the dictionary items to a list of strings using the format string 105 formatted_items: list[str] = [ 106 format_str.format(key=k, val=v) 107 for k, v in data.items() # pyright: ignore[reportAny] 108 ] 109 110 # Join the formatted items using the separator 111 joined_str: str = separator.join(formatted_items) 112 113 # Remove special characters and spaces 114 sanitized_str: str = sanitize_fname(joined_str) 115 116 # Check if the length is within limits 117 if len(sanitized_str) <= max_length: 118 return sanitized_str 119 120 # If the string is too long, generate a hash 121 return f"h_{stable_hash(sanitized_str)}"
def
dynamic_docstring(**doc_params: str) -> Callable[[~T_Callable], ~T_Callable]: