Skip to content

Utils

sereto.utils

assert_file_size_within_range(file, max_bytes, min_bytes=0, interactive=False)

Evaluates if the file size is within the specified range.

If interactive is True, the user is first prompted whether to continue if the file size is not within the range.

Parameters:

Name Type Description Default
file FilePath

The path to the file.

required
max_bytes int

The maximum file size in bytes.

required
min_bytes int

The minimum file size in bytes. Defaults to 0.

0
interactive bool

If True, the user is prompted whether to continue if the file size is not within the range. Defaults to False.

False

Raises:

Type Description
SeretoPathError

If the file does not exist.

SeretoValueError

If the file size is not within the specified range.

Source code in sereto/utils.py
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
@validate_call
def assert_file_size_within_range(
    file: FilePath, max_bytes: int, min_bytes: int = 0, interactive: bool = False
) -> None:
    """Evaluates if the file size is within the specified range.

    If `interactive` is True, the user is first prompted whether to continue if the file size is not within the range.

    Args:
        file: The path to the file.
        max_bytes: The maximum file size in bytes.
        min_bytes: The minimum file size in bytes. Defaults to 0.
        interactive: If True, the user is prompted whether to continue if the file size is not within the range.
            Defaults to False.

    Raises:
        SeretoPathError: If the file does not exist.
        SeretoValueError: If the file size is not within the specified range.
    """
    # Check the input values
    if not file.is_file():
        raise SeretoPathError(f"File '{file}' does not exist")

    if not 0 <= min_bytes <= max_bytes:
        raise SeretoValueError(f"Invalid size threshold range: {min_bytes} - {max_bytes}")

    # Get the file size in bytes
    size = file.stat().st_size

    # Check if the file size is within the specified range
    if min_bytes <= size <= max_bytes:
        return

    # File size is not within the range

    Console().log(
        f"[yellow]File '{file}' size is {naturalsize(size, binary=True)}, which is not within the allowed range "
        f"{naturalsize(min_bytes, binary=True)} - {naturalsize(max_bytes, binary=True)}"
    )

    # In interactive mode, user can choose to continue
    if interactive and click.confirm("Do you want to continue?", default=False):
        return

    # Otherwise, raise an error
    raise SeretoValueError(f"File '{file}' size is not within the range {min_bytes} - {max_bytes} B")

replace_strings(text, replacements)

replace_strings(text: str, replacements: dict[str, str]) -> str
replace_strings(text: list[str], replacements: dict[str, str]) -> list[str]

One-pass string replacement with values from dictionary.

Parameters:

Name Type Description Default
text str | list[str]

The input text.

required
replacements dict[str, str]

Dictionary with replacements. Key-value in dictionary refers to pattern string and replacement string, respectively.

required

Returns:

Type Description
str | list[str]

String (or list of strings, depending on the input value) obtained by applying the replacements from the replacements dictionary.

Source code in sereto/utils.py
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@validate_call
def replace_strings(text: str | list[str], replacements: dict[str, str]) -> str | list[str]:
    """One-pass string replacement with values from dictionary.

    Args:
        text: The input text.
        replacements: Dictionary with replacements. Key-value in dictionary refers to pattern string and replacement
            string, respectively.

    Returns:
        String (or list of strings, depending on the input value) obtained by applying the replacements from the
            `replacements` dictionary.
    """
    if len(text) == 0 or len(replacements) == 0:
        return text

    pattern = re.compile("|".join([re.escape(rep) for rep in replacements]))

    if isinstance(text, str):
        return pattern.sub(lambda match: replacements[match.group(0)], text)
    else:
        return [pattern.sub(lambda match: replacements[match.group(0)], item) for item in text]

write_if_different(file, content)

Writes content to file only if the content is different from the existing file content.

Parameters:

Name Type Description Default
file Path

The path to the file.

required
content str

The content to write to the file.

required

Returns:

Type Description
bool

True if new content was written to the file, False otherwise.

Source code in sereto/utils.py
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
@validate_call
def write_if_different(file: Path, content: str) -> bool:
    """Writes content to file only if the content is different from the existing file content.

    Args:
        file: The path to the file.
        content: The content to write to the file.

    Returns:
        True if new content was written to the file, False otherwise.
    """
    # Check if the file exists and has the same size
    if file.is_file() and file.stat().st_size == len(content):
        assert_file_size_within_range(file=file, max_bytes=104_857_600)  # 100 MiB
        # Check if the content is the same
        if file.read_text(encoding="utf-8") == content:
            return False

    # Changes detected, write the content to the file
    file.write_text(content, encoding="utf-8")
    return True