potato-util 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,274 @@
1
+ import errno
2
+ import hashlib
3
+ import logging
4
+
5
+ import aioshutil
6
+ import aiofiles.os
7
+ from pydantic import validate_call
8
+
9
+ from ..constants import WarnEnum, HashAlgoEnum, MAX_PATH_LENGTH
10
+
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ @validate_call
16
+ async def async_create_dir(
17
+ create_dir: str, warn_mode: WarnEnum = WarnEnum.DEBUG
18
+ ) -> None:
19
+ """Asynchronous create directory if `create_dir` doesn't exist.
20
+
21
+ Args:
22
+ create_dir (str, required): Create directory path.
23
+ warn_mode (str, optional): Warning message mode, for example: 'ERROR', 'ALWAYS', 'DEBUG', 'IGNORE'.
24
+ Defaults to 'DEBUG'.
25
+
26
+ Raises:
27
+ ValueError: If `create_dir` argument length is out of range.
28
+ OSError : When warning mode is set to ERROR and directory already exists.
29
+ OSError : If failed to create directory.
30
+ """
31
+
32
+ create_dir = create_dir.strip()
33
+ if (len(create_dir) < 1) or (MAX_PATH_LENGTH < len(create_dir)):
34
+ raise ValueError(
35
+ f"`create_dir` argument length {len(create_dir)} is out of range, "
36
+ f"must be between 1 and {MAX_PATH_LENGTH} characters!"
37
+ )
38
+
39
+ if not await aiofiles.os.path.isdir(create_dir):
40
+ try:
41
+ _message = f"Creating '{create_dir}' directory..."
42
+ if warn_mode == WarnEnum.ALWAYS:
43
+ logger.info(_message)
44
+ elif warn_mode == WarnEnum.DEBUG:
45
+ logger.debug(_message)
46
+
47
+ await aiofiles.os.makedirs(create_dir)
48
+ except OSError as err:
49
+ if (err.errno == errno.EEXIST) and (warn_mode == WarnEnum.DEBUG):
50
+ logger.debug(f"'{create_dir}' directory already exists!")
51
+ else:
52
+ logger.error(f"Failed to create '{create_dir}' directory!")
53
+ raise
54
+
55
+ _message = f"Successfully created '{create_dir}' directory."
56
+ if warn_mode == WarnEnum.ALWAYS:
57
+ logger.info(_message)
58
+ elif warn_mode == WarnEnum.DEBUG:
59
+ logger.debug(_message)
60
+
61
+ elif warn_mode == WarnEnum.ERROR:
62
+ raise OSError(errno.EEXIST, f"'{create_dir}' directory already exists!")
63
+
64
+ return
65
+
66
+
67
+ @validate_call
68
+ async def async_remove_dir(
69
+ remove_dir: str, warn_mode: WarnEnum = WarnEnum.DEBUG
70
+ ) -> None:
71
+ """Asynchronous remove directory if `remove_dir` exists.
72
+
73
+ Args:
74
+ remove_dir (str, required): Remove directory path.
75
+ warn_mode (str, optional): Warning message mode, for example: 'ERROR', 'ALWAYS', 'DEBUG', 'IGNORE'.
76
+ Defaults to 'DEBUG'.
77
+
78
+ Raises:
79
+ ValueError: If `remove_dir` argument length is out of range.
80
+ OSError : When warning mode is set to ERROR and directory doesn't exist.
81
+ OSError : If failed to remove directory.
82
+ """
83
+
84
+ remove_dir = remove_dir.strip()
85
+ if (len(remove_dir) < 1) or (MAX_PATH_LENGTH < len(remove_dir)):
86
+ raise ValueError(
87
+ f"`remove_dir` argument length {len(remove_dir)} is out of range, "
88
+ f"must be between 1 and {MAX_PATH_LENGTH} characters!"
89
+ )
90
+
91
+ if await aiofiles.os.path.isdir(remove_dir):
92
+ try:
93
+ _message = f"Removing '{remove_dir}' directory..."
94
+ if warn_mode == WarnEnum.ALWAYS:
95
+ logger.info(_message)
96
+ elif warn_mode == WarnEnum.DEBUG:
97
+ logger.debug(_message)
98
+
99
+ await aioshutil.rmtree(remove_dir)
100
+ except OSError as err:
101
+ if (err.errno == errno.ENOENT) and (warn_mode == WarnEnum.DEBUG):
102
+ logger.debug(f"'{remove_dir}' directory doesn't exist!")
103
+ else:
104
+ logger.error(f"Failed to remove '{remove_dir}' directory!")
105
+ raise
106
+
107
+ _message = f"Successfully removed '{remove_dir}' directory."
108
+ if warn_mode == WarnEnum.ALWAYS:
109
+ logger.info(_message)
110
+ elif warn_mode == WarnEnum.DEBUG:
111
+ logger.debug(_message)
112
+
113
+ elif warn_mode == WarnEnum.ERROR:
114
+ raise OSError(errno.ENOENT, f"'{remove_dir}' directory doesn't exist!")
115
+
116
+ return
117
+
118
+
119
+ @validate_call
120
+ async def async_remove_dirs(
121
+ remove_dirs: list[str], warn_mode: WarnEnum = WarnEnum.DEBUG
122
+ ) -> None:
123
+ """Asynchronous remove directories if `remove_dirs` exists.
124
+
125
+ Args:
126
+ remove_dirs (List[str], required): Remove directories paths as list.
127
+ warn_mode (str , optional): Warning message mode, for example: 'ERROR', 'ALWAYS', 'DEBUG', 'IGNORE'.
128
+ Defaults to 'DEBUG'.
129
+ """
130
+
131
+ for _remove_dir in remove_dirs:
132
+ await async_remove_dir(remove_dir=_remove_dir, warn_mode=warn_mode)
133
+
134
+ return
135
+
136
+
137
+ @validate_call
138
+ async def async_remove_file(
139
+ file_path: str, warn_mode: WarnEnum = WarnEnum.DEBUG
140
+ ) -> None:
141
+ """Asynchronous remove file if `file_path` exists.
142
+
143
+ Args:
144
+ file_path (str, required): Remove file path.
145
+ warn_mode (str, optional): Warning message mode, for example: 'ERROR', 'ALWAYS', 'DEBUG', 'IGNORE'.
146
+ Defaults to 'DEBUG'.
147
+
148
+ Raises:
149
+ ValueError: If `file_path` argument length is out of range.
150
+ OSError : When warning mode is set to ERROR and file doesn't exist.
151
+ OSError : If failed to remove file.
152
+ """
153
+
154
+ file_path = file_path.strip()
155
+ if (len(file_path) < 1) or (MAX_PATH_LENGTH < len(file_path)):
156
+ raise ValueError(
157
+ f"`file_path` argument length {len(file_path)} is out of range, "
158
+ f"must be between 1 and {MAX_PATH_LENGTH} characters!"
159
+ )
160
+
161
+ if await aiofiles.os.path.isfile(file_path):
162
+ try:
163
+ _message = f"Removing '{file_path}' file..."
164
+ if warn_mode == WarnEnum.ALWAYS:
165
+ logger.info(_message)
166
+ elif warn_mode == WarnEnum.DEBUG:
167
+ logger.debug(_message)
168
+
169
+ await aiofiles.os.remove(file_path)
170
+ except OSError as err:
171
+ if (err.errno == errno.ENOENT) and (warn_mode == WarnEnum.DEBUG):
172
+ logger.debug(f"'{file_path}' file doesn't exist!")
173
+ else:
174
+ logger.error(f"Failed to remove '{file_path}' file!")
175
+ raise
176
+
177
+ _message = f"Successfully removed '{file_path}' file."
178
+ if warn_mode == WarnEnum.ALWAYS:
179
+ logger.info(_message)
180
+ elif warn_mode == WarnEnum.DEBUG:
181
+ logger.debug(_message)
182
+
183
+ elif warn_mode == WarnEnum.ERROR:
184
+ raise OSError(errno.ENOENT, f"'{file_path}' file doesn't exist!")
185
+
186
+ return
187
+
188
+
189
+ @validate_call
190
+ async def async_remove_files(
191
+ file_paths: list[str], warn_mode: WarnEnum = WarnEnum.DEBUG
192
+ ) -> None:
193
+ """Asynchronous remove files if `file_paths` exists.
194
+
195
+ Args:
196
+ file_paths (List[str], required): Remove file paths as list.
197
+ warn_mode (str , optional): Warning message mode, for example: 'ERROR', 'ALWAYS', 'DEBUG', 'IGNORE'.
198
+ Defaults to 'DEBUG'.
199
+ """
200
+
201
+ for _file_path in file_paths:
202
+ await async_remove_file(file_path=_file_path, warn_mode=warn_mode)
203
+
204
+ return
205
+
206
+
207
+ @validate_call
208
+ async def async_get_file_checksum(
209
+ file_path: str,
210
+ hash_method: HashAlgoEnum = HashAlgoEnum.md5,
211
+ chunk_size: int = 4096,
212
+ warn_mode: WarnEnum = WarnEnum.DEBUG,
213
+ ) -> str | None:
214
+ """Asynchronous get file checksum.
215
+
216
+ Args:
217
+ file_path (str , required): Target file path.
218
+ hash_method (HashAlgoEnum, optional): Hash method. Defaults to `HashAlgoEnum.md5`.
219
+ chunk_size (int , optional): Chunk size. Defaults to 4096.
220
+ warn_mode (str , optional): Warning message mode, for example: 'ERROR', 'ALWAYS', 'DEBUG', 'IGNORE'.
221
+ Defaults to 'DEBUG'.
222
+
223
+ Raises:
224
+ ValueError: If `file_path` argument length is out of range.
225
+ ValueError: If `chunk_size` argument value is invalid.
226
+ OSError : When warning mode is set to ERROR and file doesn't exist.
227
+
228
+ Returns:
229
+ str | None: File checksum or None if file doesn't exist.
230
+ """
231
+
232
+ file_path = file_path.strip()
233
+ if (len(file_path) < 1) or (MAX_PATH_LENGTH < len(file_path)):
234
+ raise ValueError(
235
+ f"`file_path` argument length {len(file_path)} is out of range, "
236
+ f"must be between 1 and {MAX_PATH_LENGTH} characters!"
237
+ )
238
+
239
+ if chunk_size < 10:
240
+ raise ValueError(
241
+ f"`chunk_size` argument value {chunk_size} is invalid, must be greater than 10!"
242
+ )
243
+
244
+ _file_checksum: str | None = None
245
+ if await aiofiles.os.path.isfile(file_path):
246
+ _file_hash = hashlib.new(hash_method.value)
247
+ async with aiofiles.open(file_path, "rb") as _file:
248
+ while True:
249
+ _file_chunk = await _file.read(chunk_size)
250
+ if not _file_chunk:
251
+ break
252
+ _file_hash.update(_file_chunk)
253
+
254
+ _file_checksum = _file_hash.hexdigest()
255
+ else:
256
+ _message = f"'{file_path}' file doesn't exist!"
257
+ if warn_mode == WarnEnum.ALWAYS:
258
+ logger.warning(_message)
259
+ elif warn_mode == WarnEnum.DEBUG:
260
+ logger.debug(_message)
261
+ elif warn_mode == WarnEnum.ERROR:
262
+ raise OSError(errno.ENOENT, _message)
263
+
264
+ return _file_checksum
265
+
266
+
267
+ __all__ = [
268
+ "async_create_dir",
269
+ "async_remove_dir",
270
+ "async_remove_dirs",
271
+ "async_remove_file",
272
+ "async_remove_files",
273
+ "async_get_file_checksum",
274
+ ]
@@ -0,0 +1,264 @@
1
+ import os
2
+ import errno
3
+ import shutil
4
+ import hashlib
5
+ import logging
6
+
7
+ from pydantic import validate_call
8
+
9
+ from ..constants import WarnEnum, HashAlgoEnum, MAX_PATH_LENGTH
10
+
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ @validate_call
16
+ def create_dir(create_dir: str, warn_mode: WarnEnum = WarnEnum.DEBUG) -> None:
17
+ """Create directory if `create_dir` doesn't exist.
18
+
19
+ Args:
20
+ create_dir (str, required): Create directory path.
21
+ warn_mode (str, optional): Warning message mode, for example: 'ERROR', 'ALWAYS', 'DEBUG', 'IGNORE'.
22
+ Defaults to 'DEBUG'.
23
+
24
+ Raises:
25
+ ValueError: If `create_dir` argument length is out of range.
26
+ OSError : When warning mode is set to ERROR and directory already exists.
27
+ OSError : If failed to create directory.
28
+ """
29
+
30
+ create_dir = create_dir.strip()
31
+ if (len(create_dir) < 1) or (MAX_PATH_LENGTH < len(create_dir)):
32
+ raise ValueError(
33
+ f"`create_dir` argument length {len(create_dir)} is out of range, "
34
+ f"must be between 1 and {MAX_PATH_LENGTH} characters!"
35
+ )
36
+
37
+ if not os.path.isdir(create_dir):
38
+ try:
39
+ _message = f"Creating '{create_dir}' directory..."
40
+ if warn_mode == WarnEnum.ALWAYS:
41
+ logger.info(_message)
42
+ elif warn_mode == WarnEnum.DEBUG:
43
+ logger.debug(_message)
44
+
45
+ os.makedirs(create_dir)
46
+ except OSError as err:
47
+ if (err.errno == errno.EEXIST) and (warn_mode == WarnEnum.DEBUG):
48
+ logger.debug(f"'{create_dir}' directory already exists!")
49
+ else:
50
+ logger.error(f"Failed to create '{create_dir}' directory!")
51
+ raise
52
+
53
+ _message = f"Successfully created '{create_dir}' directory."
54
+ if warn_mode == WarnEnum.ALWAYS:
55
+ logger.info(_message)
56
+ elif warn_mode == WarnEnum.DEBUG:
57
+ logger.debug(_message)
58
+
59
+ elif warn_mode == WarnEnum.ERROR:
60
+ raise OSError(errno.EEXIST, f"'{create_dir}' directory already exists!")
61
+
62
+ return
63
+
64
+
65
+ @validate_call
66
+ def remove_dir(remove_dir: str, warn_mode: WarnEnum = WarnEnum.DEBUG) -> None:
67
+ """Remove directory if `remove_dir` exists.
68
+
69
+ Args:
70
+ remove_dir (str, required): Remove directory path.
71
+ warn_mode (str, optional): Warning message mode, for example: 'ERROR', 'ALWAYS', 'DEBUG', 'IGNORE'.
72
+ Defaults to 'DEBUG'.
73
+
74
+ Raises:
75
+ ValueError: If `remove_dir` argument length is out of range.
76
+ OSError : When warning mode is set to ERROR and directory doesn't exist.
77
+ OSError : If failed to remove directory.
78
+ """
79
+
80
+ remove_dir = remove_dir.strip()
81
+ if (len(remove_dir) < 1) or (MAX_PATH_LENGTH < len(remove_dir)):
82
+ raise ValueError(
83
+ f"`remove_dir` argument length {len(remove_dir)} is out of range, "
84
+ f"must be between 1 and {MAX_PATH_LENGTH} characters!"
85
+ )
86
+
87
+ if os.path.isdir(remove_dir):
88
+ try:
89
+ _message = f"Removing '{remove_dir}' directory..."
90
+ if warn_mode == WarnEnum.ALWAYS:
91
+ logger.info(_message)
92
+ elif warn_mode == WarnEnum.DEBUG:
93
+ logger.debug(_message)
94
+
95
+ shutil.rmtree(remove_dir)
96
+ except OSError as err:
97
+ if (err.errno == errno.ENOENT) and (warn_mode == WarnEnum.DEBUG):
98
+ logger.debug(f"'{remove_dir}' directory doesn't exist!")
99
+ else:
100
+ logger.error(f"Failed to remove '{remove_dir}' directory!")
101
+ raise
102
+
103
+ _message = f"Successfully removed '{remove_dir}' directory."
104
+ if warn_mode == WarnEnum.ALWAYS:
105
+ logger.info(_message)
106
+ elif warn_mode == WarnEnum.DEBUG:
107
+ logger.debug(_message)
108
+
109
+ elif warn_mode == WarnEnum.ERROR:
110
+ raise OSError(errno.ENOENT, f"'{remove_dir}' directory doesn't exist!")
111
+
112
+ return
113
+
114
+
115
+ @validate_call
116
+ def remove_dirs(remove_dirs: list[str], warn_mode: WarnEnum = WarnEnum.DEBUG) -> None:
117
+ """Remove directories if `remove_dirs` exist.
118
+
119
+ Args:
120
+ remove_dirs (List[str], required): Remove directory paths as list.
121
+ warn_mode (str , optional): Warning message mode, for example: 'ERROR', 'ALWAYS', 'DEBUG', 'IGNORE'.
122
+ Defaults to 'DEBUG'.
123
+ """
124
+
125
+ for _remove_dir in remove_dirs:
126
+ remove_dir(remove_dir=_remove_dir, warn_mode=warn_mode)
127
+
128
+ return
129
+
130
+
131
+ @validate_call
132
+ def remove_file(file_path: str, warn_mode: WarnEnum = WarnEnum.DEBUG) -> None:
133
+ """Remove file if `file_path` exists.
134
+
135
+ Args:
136
+ file_path (str, required): Remove file path.
137
+ warn_mode (str, optional): Warning message mode, for example: 'ERROR', 'ALWAYS', 'DEBUG', 'IGNORE'.
138
+ Defaults to 'DEBUG'.
139
+
140
+ Raises:
141
+ ValueError: If `file_path` argument length is out of range.
142
+ OSError : When warning mode is set to ERROR and file doesn't exist.
143
+ OSError : If failed to remove file.
144
+ """
145
+
146
+ file_path = file_path.strip()
147
+ if (len(file_path) < 1) or (MAX_PATH_LENGTH < len(file_path)):
148
+ raise ValueError(
149
+ f"`file_path` argument length {len(file_path)} is out of range, "
150
+ f"must be between 1 and {MAX_PATH_LENGTH} characters!"
151
+ )
152
+
153
+ if os.path.isfile(file_path):
154
+ try:
155
+ _message = f"Removing '{file_path}' file..."
156
+ if warn_mode == WarnEnum.ALWAYS:
157
+ logger.info(_message)
158
+ elif warn_mode == WarnEnum.DEBUG:
159
+ logger.debug(_message)
160
+
161
+ os.remove(file_path)
162
+ except OSError as err:
163
+ if (err.errno == errno.ENOENT) and (warn_mode == WarnEnum.DEBUG):
164
+ logger.debug(f"'{file_path}' file doesn't exist!")
165
+ else:
166
+ logger.error(f"Failed to remove '{file_path}' file!")
167
+ raise
168
+
169
+ _message = f"Successfully removed '{file_path}' file."
170
+ if warn_mode == WarnEnum.ALWAYS:
171
+ logger.info(_message)
172
+ elif warn_mode == WarnEnum.DEBUG:
173
+ logger.debug(_message)
174
+
175
+ elif warn_mode == WarnEnum.ERROR:
176
+ raise OSError(errno.ENOENT, f"'{file_path}' file doesn't exist!")
177
+
178
+ return
179
+
180
+
181
+ @validate_call
182
+ def remove_files(file_paths: list[str], warn_mode: WarnEnum = WarnEnum.DEBUG) -> None:
183
+ """Remove files if `file_paths` exist.
184
+
185
+ Args:
186
+ file_paths (List[str], required): Remove file paths as list.
187
+ warn_mode (str , optional): Warning message mode, for example: 'ERROR', 'ALWAYS', 'DEBUG', 'IGNORE'.
188
+ Defaults to 'DEBUG'.
189
+ """
190
+
191
+ for _file_path in file_paths:
192
+ remove_file(file_path=_file_path, warn_mode=warn_mode)
193
+
194
+ return
195
+
196
+
197
+ @validate_call
198
+ def get_file_checksum(
199
+ file_path: str,
200
+ hash_method: HashAlgoEnum = HashAlgoEnum.md5,
201
+ chunk_size: int = 4096,
202
+ warn_mode: WarnEnum = WarnEnum.DEBUG,
203
+ ) -> str | None:
204
+ """Get file checksum.
205
+
206
+ Args:
207
+ file_path (str , required): Target file path.
208
+ hash_method (HashAlgoEnum, optional): Hash method. Defaults to `HashAlgoEnum.md5`.
209
+ chunk_size (int , optional): Chunk size. Defaults to 4096.
210
+ warn_mode (str , optional): Warning message mode, for example: 'ERROR', 'ALWAYS', 'DEBUG', 'IGNORE'.
211
+ Defaults to 'DEBUG'.
212
+
213
+ Raises:
214
+ ValueError: If `file_path` argument length is out of range.
215
+ ValueError: If `chunk_size` argument value is invalid.
216
+ OSError : When warning mode is set to ERROR and file doesn't exist.
217
+
218
+ Returns:
219
+ str | None: File checksum or None if file doesn't exist.
220
+ """
221
+
222
+ file_path = file_path.strip()
223
+ if (len(file_path) < 1) or (MAX_PATH_LENGTH < len(file_path)):
224
+ raise ValueError(
225
+ f"`file_path` argument length {len(file_path)} is out of range, "
226
+ f"must be between 1 and {MAX_PATH_LENGTH} characters!"
227
+ )
228
+
229
+ if chunk_size < 10:
230
+ raise ValueError(
231
+ f"`chunk_size` argument value {chunk_size} is invalid, must be greater than 10!"
232
+ )
233
+
234
+ _file_checksum: str | None = None
235
+ if os.path.isfile(file_path):
236
+ _file_hash = hashlib.new(hash_method.value)
237
+ with open(file_path, "rb") as _file:
238
+ while True:
239
+ _file_chunk = _file.read(chunk_size)
240
+ if not _file_chunk:
241
+ break
242
+ _file_hash.update(_file_chunk)
243
+
244
+ _file_checksum = _file_hash.hexdigest()
245
+ else:
246
+ _message = f"'{file_path}' file doesn't exist!"
247
+ if warn_mode == WarnEnum.ALWAYS:
248
+ logger.warning(_message)
249
+ elif warn_mode == WarnEnum.DEBUG:
250
+ logger.debug(_message)
251
+ elif warn_mode == WarnEnum.ERROR:
252
+ raise OSError(errno.ENOENT, _message)
253
+
254
+ return _file_checksum
255
+
256
+
257
+ __all__ = [
258
+ "create_dir",
259
+ "remove_dir",
260
+ "remove_dirs",
261
+ "remove_file",
262
+ "remove_files",
263
+ "get_file_checksum",
264
+ ]
@@ -0,0 +1,85 @@
1
+ import re
2
+ import html
3
+ from urllib.parse import quote
4
+
5
+ from pydantic import validate_call, AnyHttpUrl
6
+
7
+ from .constants import (
8
+ SPECIAL_CHARS_BASE_REGEX,
9
+ SPECIAL_CHARS_LOW_REGEX,
10
+ SPECIAL_CHARS_MEDIUM_REGEX,
11
+ SPECIAL_CHARS_HIGH_REGEX,
12
+ SPECIAL_CHARS_STRICT_REGEX,
13
+ )
14
+
15
+
16
+ @validate_call
17
+ def escape_html(val: str) -> str:
18
+ """Escape HTML characters.
19
+
20
+ Args:
21
+ val (str, required): String to escape.
22
+
23
+ Returns:
24
+ str: Escaped string.
25
+ """
26
+
27
+ val = val.strip()
28
+ _escaped = html.escape(val)
29
+ return _escaped
30
+
31
+
32
+ @validate_call
33
+ def escape_url(val: AnyHttpUrl) -> str:
34
+ """Escape URL characters.
35
+
36
+ Args:
37
+ val (AnyHttpUrl, required): String to escape.
38
+
39
+ Returns:
40
+ str: Escaped string.
41
+ """
42
+
43
+ _escaped = quote(str(val))
44
+ return _escaped
45
+
46
+
47
+ @validate_call
48
+ def sanitize_special_chars(val: str, mode: str = "LOW") -> str:
49
+ """Sanitize special characters.
50
+
51
+ Args:
52
+ val (str, required): String to sanitize.
53
+ mode (str, optional): Sanitization mode. Defaults to "LOW".
54
+
55
+ Raises:
56
+ ValueError: If `mode` is unsupported.
57
+
58
+ Returns:
59
+ str: Sanitized string.
60
+ """
61
+
62
+ _pattern = r""
63
+ mode = mode.upper().strip()
64
+ if (mode == "BASE") or (mode == "HTML"):
65
+ _pattern = SPECIAL_CHARS_BASE_REGEX
66
+ elif mode == "LOW":
67
+ _pattern = SPECIAL_CHARS_LOW_REGEX
68
+ elif mode == "MEDIUM":
69
+ _pattern = SPECIAL_CHARS_MEDIUM_REGEX
70
+ elif (mode == "HIGH") or (mode == "SCRIPT") or (mode == "SQL"):
71
+ _pattern = SPECIAL_CHARS_HIGH_REGEX
72
+ elif mode == "STRICT":
73
+ _pattern = SPECIAL_CHARS_STRICT_REGEX
74
+ else:
75
+ raise ValueError(f"Unsupported mode: {mode}")
76
+
77
+ _sanitized = re.sub(pattern=_pattern, repl="", string=val)
78
+ return _sanitized
79
+
80
+
81
+ __all__ = [
82
+ "escape_html",
83
+ "escape_url",
84
+ "sanitize_special_chars",
85
+ ]