docs for muutils v0.9.1
View Source on GitHub

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 | None input string
  • additional_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 if name is None. if None, 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, 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]:
127def dynamic_docstring(**doc_params: str) -> Callable[[T_Callable], T_Callable]:
128    def decorator(func: T_Callable) -> T_Callable:
129        if func.__doc__:
130            func.__doc__ = getattr(func, "__doc__", "").format(**doc_params)
131        return func
132
133    return decorator