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