diff --git a/namer/__main__.py b/namer/__main__.py
index e9637e65..2d133ad1 100644
--- a/namer/__main__.py
+++ b/namer/__main__.py
@@ -74,7 +74,7 @@ def main():
arg1 = None if len(arg_list) == 0 else arg_list[0]
if arg1 == 'watchdog':
- namer.watchdog.create_watcher(config).run()
+ namer.watchdog.main(config)
elif arg1 == 'rename':
namer.namer.main(arg_list[1:])
elif arg1 == 'suggest':
diff --git a/namer/configuration.py b/namer/configuration.py
index b55c0a7a..66d10a5d 100644
--- a/namer/configuration.py
+++ b/namer/configuration.py
@@ -245,7 +245,7 @@ class NamerConfig:
a set of tags that indicates an individual video is vr.
"""
- database_path: Path = Path(tempfile.gettempdir()) / 'namer'
+ database_path: Path = Path(tempfile.gettemp_dir()) / 'namer'
"""
Path where stores namer system data.
"""
@@ -510,6 +510,15 @@ def __init__(self):
self.re_cleanup = [re.compile(rf'\b{regex}\b', re.IGNORECASE) for regex in database.re_cleanup]
+ if hasattr(self, 'watch_dir'):
+ self.watch_dir = self.watch_dir.resolve()
+ if hasattr(self, 'work_dir'):
+ self.work_dir = self.work_dir.resolve()
+ if hasattr(self, 'dest_dir'):
+ self.dest_dir = self.dest_dir.resolve()
+ if hasattr(self, 'failed_dir'):
+ self.failed_dir = self.failed_dir.resolve()
+
def __str__(self):
config = self.to_dict()
diff --git a/namer/metadataapi.py b/namer/metadataapi.py
index 01979265..09008c64 100644
--- a/namer/metadataapi.py
+++ b/namer/metadataapi.py
@@ -472,7 +472,7 @@ def __get_metadataapi_net_info(url: str, name_parts: Optional[FileInfo], namer_c
if json_response and json_response.strip() != '':
# logger.debug("json_response: \n{}", json_response)
json_obj = orjson.loads(json_response)
- formatted = orjson.dumps(orjson.loads(json_response), option=orjson.OPT_INDENT_2 | orjson.OPT_SORT_KEYS).decode('UTF-8')
+ formatted = orjson.dumps(json_obj, option=orjson.OPT_INDENT_2 | orjson.OPT_SORT_KEYS).decode('UTF-8')
file_infos = __metadataapi_response_to_data(json_obj, url, formatted, name_parts, namer_config)
return file_infos
diff --git a/namer/watchdog.py b/namer/watchdog.py
index 24a2ae40..3292231f 100644
--- a/namer/watchdog.py
+++ b/namer/watchdog.py
@@ -103,7 +103,11 @@ def on_any_event(self, event: FileSystemEvent):
file_path = event.src_path
if file_path:
- path = Path(file_path)
+ path = Path(file_path).resolve()
+ if not path.is_relative_to(self.__namer_config.watch_dir):
+ logger.error('file should be in watch dir {}', path)
+ return
+
relative_path = str(path.relative_to(self.__namer_config.watch_dir))
if not self.__namer_config.ignored_dir_regex.search(relative_path) and done_copying(path) and is_interesting_movie(path, self.__namer_config):
logger.info('watchdog process called for {}', relative_path)
@@ -249,10 +253,14 @@ def start(self):
# touch all existing movie files.
with suppress(FileNotFoundError):
for file in self.__namer_config.watch_dir.rglob('**/*.*'):
- if file.is_file() and file.suffix.lower()[1:] in self.__namer_config.target_extensions:
- relative_path = str(file.relative_to(self.__namer_config.watch_dir))
- if not config.ignored_dir_regex.search(relative_path) and done_copying(file) and is_interesting_movie(file, self.__namer_config):
- self.__event_handler.prepare_file_for_processing(file)
+ file = file.resolve()
+ if not file.is_relative_to(self.__namer_config.watch_dir):
+ logger.error('file should be in watch dir {}', file)
+ return
+
+ relative_path = str(file.relative_to(self.__namer_config.watch_dir))
+ if not self.__namer_config.ignored_dir_regex.search(relative_path) and done_copying(file) and is_interesting_movie(file, self.__namer_config):
+ self.__event_handler.prepare_file_for_processing(file)
def stop(self):
"""
@@ -302,9 +310,6 @@ def create_watcher(namer_watchdog_config: NamerConfig) -> MovieWatcher:
"""
Configure and start a watchdog looking for new Movies.
"""
- level = 'DEBUG' if namer_watchdog_config.debug else 'INFO'
- logger.add(sys.stdout, format=namer_watchdog_config.console_format, level=level, diagnose=namer_watchdog_config.diagnose_errors)
-
logger.info(namer_watchdog_config)
if not verify_configuration(namer_watchdog_config, PartialFormatter()):
@@ -322,3 +327,11 @@ def create_watcher(namer_watchdog_config: NamerConfig) -> MovieWatcher:
movie_watcher = MovieWatcher(namer_watchdog_config)
return movie_watcher
+
+
+def main(config: NamerConfig):
+ level = 'DEBUG' if config.debug else 'INFO'
+ logger.add(sys.stdout, format=config.console_format, level=level, diagnose=config.diagnose_errors)
+
+ create_watcher(config).run()
+
diff --git a/package.json b/package.json
index ad5c627e..dece2eca 100644
--- a/package.json
+++ b/package.json
@@ -13,14 +13,14 @@
},
"dependencies": {
"@popperjs/core": "^2.11.8",
- "bootstrap": "^5.3.5",
- "bootstrap-icons": "^1.11.3",
+ "bootstrap": "^5.3.6",
+ "bootstrap-icons": "^1.13.1",
"datatables.net": "^2.3.0",
"datatables.net-bs5": "^2.3.0",
"datatables.net-buttons": "^3.2.3",
"datatables.net-buttons-bs5": "^3.2.3",
- "datatables.net-colreorder": "^2.0.4",
- "datatables.net-colreorder-bs5": "^2.0.4",
+ "datatables.net-colreorder": "^2.1.0",
+ "datatables.net-colreorder-bs5": "^2.1.0",
"datatables.net-fixedheader": "^4.0.1",
"datatables.net-fixedheader-bs5": "^4.0.1",
"datatables.net-responsive": "^3.0.4",
@@ -30,7 +30,7 @@
},
"devDependencies": {
"@babel/core": "^7.27.1",
- "@babel/preset-env": "^7.27.1",
+ "@babel/preset-env": "^7.27.2",
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.26.0",
"babel-loader": "^10.0.0",
@@ -40,10 +40,10 @@
"eslint": "^9.26.0",
"eslint-config-standard": "^17.1.0",
"file-loader": "^6.2.0",
- "globals": "^16.0.0",
+ "globals": "^16.1.0",
"html-minimizer-webpack-plugin": "^5.0.2",
"husky": "^9.1.7",
- "lint-staged": "^15.5.1",
+ "lint-staged": "^15.5.2",
"mini-css-extract-plugin": "^2.9.2",
"postcss": "^8.5.3",
"postcss-loader": "^8.1.1",
@@ -51,7 +51,7 @@
"sass": "^1.87.0",
"sass-loader": "^16.0.5",
"terser-webpack-plugin": "^5.3.14",
- "webpack": "^5.99.7",
+ "webpack": "^5.99.8",
"webpack-cli": "^6.0.1"
},
"engines": {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 13604524..6101031e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -12,11 +12,11 @@ importers:
specifier: ^2.11.8
version: 2.11.8
bootstrap:
- specifier: ^5.3.5
- version: 5.3.5(@popperjs/core@2.11.8)
+ specifier: ^5.3.6
+ version: 5.3.6(@popperjs/core@2.11.8)
bootstrap-icons:
- specifier: ^1.11.3
- version: 1.11.3
+ specifier: ^1.13.1
+ version: 1.13.1
datatables.net:
specifier: ^2.3.0
version: 2.3.0
@@ -30,11 +30,11 @@ importers:
specifier: ^3.2.3
version: 3.2.3
datatables.net-colreorder:
- specifier: ^2.0.4
- version: 2.0.4
+ specifier: ^2.1.0
+ version: 2.1.0
datatables.net-colreorder-bs5:
- specifier: ^2.0.4
- version: 2.0.4
+ specifier: ^2.1.0
+ version: 2.1.0
datatables.net-fixedheader:
specifier: ^4.0.1
version: 4.0.1
@@ -58,8 +58,8 @@ importers:
specifier: ^7.27.1
version: 7.27.1
'@babel/preset-env':
- specifier: ^7.27.1
- version: 7.27.1(@babel/core@7.27.1)
+ specifier: ^7.27.2
+ version: 7.27.2(@babel/core@7.27.1)
'@eslint/eslintrc':
specifier: ^3.3.1
version: 3.3.1
@@ -68,16 +68,16 @@ importers:
version: 9.26.0
babel-loader:
specifier: ^10.0.0
- version: 10.0.0(@babel/core@7.27.1)(webpack@5.99.7)
+ version: 10.0.0(@babel/core@7.27.1)(webpack@5.99.8)
copy-webpack-plugin:
specifier: ^13.0.0
- version: 13.0.0(webpack@5.99.7)
+ version: 13.0.0(webpack@5.99.8)
css-loader:
specifier: ^7.1.2
- version: 7.1.2(webpack@5.99.7)
+ version: 7.1.2(webpack@5.99.8)
css-minimizer-webpack-plugin:
specifier: ^7.0.2
- version: 7.0.2(webpack@5.99.7)
+ version: 7.0.2(webpack@5.99.8)
eslint:
specifier: ^9.26.0
version: 9.26.0(jiti@1.21.7)
@@ -86,28 +86,28 @@ importers:
version: 17.1.0(eslint-plugin-import@2.31.0(eslint@9.26.0(jiti@1.21.7)))(eslint-plugin-n@16.6.2(eslint@9.26.0(jiti@1.21.7)))(eslint-plugin-promise@6.6.0(eslint@9.26.0(jiti@1.21.7)))(eslint@9.26.0(jiti@1.21.7))
file-loader:
specifier: ^6.2.0
- version: 6.2.0(webpack@5.99.7)
+ version: 6.2.0(webpack@5.99.8)
globals:
- specifier: ^16.0.0
- version: 16.0.0
+ specifier: ^16.1.0
+ version: 16.1.0
html-minimizer-webpack-plugin:
specifier: ^5.0.2
- version: 5.0.2(webpack@5.99.7)
+ version: 5.0.2(webpack@5.99.8)
husky:
specifier: ^9.1.7
version: 9.1.7
lint-staged:
- specifier: ^15.5.1
- version: 15.5.1
+ specifier: ^15.5.2
+ version: 15.5.2
mini-css-extract-plugin:
specifier: ^2.9.2
- version: 2.9.2(webpack@5.99.7)
+ version: 2.9.2(webpack@5.99.8)
postcss:
specifier: ^8.5.3
version: 8.5.3
postcss-loader:
specifier: ^8.1.1
- version: 8.1.1(postcss@8.5.3)(typescript@5.6.2)(webpack@5.99.7)
+ version: 8.1.1(postcss@8.5.3)(typescript@5.6.2)(webpack@5.99.8)
postcss-preset-env:
specifier: ^10.1.6
version: 10.1.6(postcss@8.5.3)
@@ -116,16 +116,16 @@ importers:
version: 1.87.0
sass-loader:
specifier: ^16.0.5
- version: 16.0.5(sass@1.87.0)(webpack@5.99.7)
+ version: 16.0.5(sass@1.87.0)(webpack@5.99.8)
terser-webpack-plugin:
specifier: ^5.3.14
- version: 5.3.14(webpack@5.99.7)
+ version: 5.3.14(webpack@5.99.8)
webpack:
- specifier: ^5.99.7
- version: 5.99.7(webpack-cli@6.0.1)
+ specifier: ^5.99.8
+ version: 5.99.8(webpack-cli@6.0.1)
webpack-cli:
specifier: ^6.0.1
- version: 6.0.1(webpack@5.99.7)
+ version: 6.0.1(webpack@5.99.8)
packages:
@@ -137,8 +137,8 @@ packages:
resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
engines: {node: '>=6.9.0'}
- '@babel/compat-data@7.27.1':
- resolution: {integrity: sha512-Q+E+rd/yBzNQhXkG+zQnF58e4zoZfBedaxwzPmicKsiK3nt8iJYrSrDbjwFFDGC4f+rPafqRaPH6TsDoSvMf7A==}
+ '@babel/compat-data@7.27.2':
+ resolution: {integrity: sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==}
engines: {node: '>=6.9.0'}
'@babel/core@7.27.1':
@@ -153,8 +153,8 @@ packages:
resolution: {integrity: sha512-WnuuDILl9oOBbKnb4L+DyODx7iC47XfzmNCpTttFsSp6hTG7XZxu60+4IO+2/hPfcGOoKbFiwoI/+zwARbNQow==}
engines: {node: '>=6.9.0'}
- '@babel/helper-compilation-targets@7.27.1':
- resolution: {integrity: sha512-2YaDd/Rd9E598B5+WIc8wJPmWETiiJXFYVE60oX8FDohv7rAUU3CQj+A1MgeEmcsk2+dQuEjIe/GDvig0SqL4g==}
+ '@babel/helper-compilation-targets@7.27.2':
+ resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==}
engines: {node: '>=6.9.0'}
'@babel/helper-create-class-features-plugin@7.27.1':
@@ -232,8 +232,8 @@ packages:
resolution: {integrity: sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==}
engines: {node: '>=6.9.0'}
- '@babel/parser@7.27.1':
- resolution: {integrity: sha512-I0dZ3ZpCrJ1c04OqlNsQcKiZlsrXf/kkE4FXzID9rIOYICsAbA8mMDzhW/luRNAHdCNt7os/u8wenklZDlUVUQ==}
+ '@babel/parser@7.27.2':
+ resolution: {integrity: sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==}
engines: {node: '>=6.0.0'}
hasBin: true
@@ -471,8 +471,8 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0
- '@babel/plugin-transform-object-rest-spread@7.27.1':
- resolution: {integrity: sha512-/sSliVc9gHE20/7D5qsdGlq7RG5NCDTWsAhyqzGuq174EtWJoGzIu1BQ7G56eDsTcy1jseBZwv50olSdXOlGuA==}
+ '@babel/plugin-transform-object-rest-spread@7.27.2':
+ resolution: {integrity: sha512-AIUHD7xJ1mCrj3uPozvtngY3s0xpv7Nu7DoUSnzNY6Xam1Cy4rUznR//pvMHOhQ4AvbCexhbqXCtpxGHOGOO6g==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
@@ -591,8 +591,8 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0
- '@babel/preset-env@7.27.1':
- resolution: {integrity: sha512-TZ5USxFpLgKDpdEt8YWBR7p6g+bZo6sHaXLqP2BY/U0acaoI8FTVflcYCr/v94twM1C5IWFdZ/hscq9WjUeLXA==}
+ '@babel/preset-env@7.27.2':
+ resolution: {integrity: sha512-Ma4zSuYSlGNRlCLO+EAzLnCmJK2vdstgv+n7aUP+/IKZrOfWHOJVdSJtuub8RzHTj3ahD37k5OKJWvzf16TQyQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
@@ -602,8 +602,8 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0
- '@babel/template@7.27.1':
- resolution: {integrity: sha512-Fyo3ghWMqkHHpHQCoBs2VnYjR4iWFFjguTDEqA5WgZDOrFesVjMhMM2FSqTKSoUSDO1VQtavj8NFpdRBEvJTtg==}
+ '@babel/template@7.27.2':
+ resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
engines: {node: '>=6.9.0'}
'@babel/traverse@7.27.1':
@@ -924,8 +924,8 @@ packages:
resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==}
engines: {node: '>=18.18'}
- '@humanwhocodes/retry@0.4.2':
- resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==}
+ '@humanwhocodes/retry@0.4.3':
+ resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
engines: {node: '>=18.18'}
'@jest/schemas@29.6.3':
@@ -957,8 +957,8 @@ packages:
'@jridgewell/trace-mapping@0.3.25':
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
- '@modelcontextprotocol/sdk@1.11.0':
- resolution: {integrity: sha512-k/1pb70eD638anoi0e8wUGAlbMJXyvdV4p62Ko+EZ7eBe1xMx8Uhak1R5DgfoofsK5IBBnRwsYGTaLZl+6/+RQ==}
+ '@modelcontextprotocol/sdk@1.11.1':
+ resolution: {integrity: sha512-9LfmxKTb1v+vUS1/emSk1f5ePmTLkb9Le9AxOB5T0XM59EUumwcS45z05h7aiZx3GI0Bl7mjb3FMEglYj+acuQ==}
engines: {node: '>=18'}
'@parcel/watcher-android-arm64@2.5.1':
@@ -1083,8 +1083,8 @@ packages:
'@types/json5@0.0.29':
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
- '@types/node@22.15.3':
- resolution: {integrity: sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==}
+ '@types/node@22.15.17':
+ resolution: {integrity: sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==}
'@types/yargs-parser@21.0.3':
resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==}
@@ -1299,11 +1299,11 @@ packages:
boolbase@1.0.0:
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
- bootstrap-icons@1.11.3:
- resolution: {integrity: sha512-+3lpHrCw/it2/7lBL15VR0HEumaBss0+f/Lb6ZvHISn1mlK83jjFpooTLsMWbIjJMDjDjOExMsTxnXSIT4k4ww==}
+ bootstrap-icons@1.13.1:
+ resolution: {integrity: sha512-ijombt4v6bv5CLeXvRWKy7CuM3TRTuPEuGaGKvTV5cz65rQSY8RQ2JcHt6b90cBBAC7s8fsf2EkQDldzCoXUjw==}
- bootstrap@5.3.5:
- resolution: {integrity: sha512-ct1CHKtiobRimyGzmsSldEtM03E8fcEX4Tb3dGXz1V8faRwM50+vfHwTzOxB3IlKO7m+9vTH3s/3C6T2EAPeTA==}
+ bootstrap@5.3.6:
+ resolution: {integrity: sha512-jX0GAcRzvdwISuvArXn3m7KZscWWFAf1MKBcnzaN02qWMb3jpMoUX4/qgeiGzqyIb4ojulRzs89UCUmGcFSzTA==}
peerDependencies:
'@popperjs/core': ^2.11.8
@@ -1355,8 +1355,8 @@ packages:
caniuse-api@3.0.0:
resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==}
- caniuse-lite@1.0.30001716:
- resolution: {integrity: sha512-49/c1+x3Kwz7ZIWt+4DvK3aMJy9oYXXG6/97JKsnjdCk/6n9vVyWL8NAwVt95Lwt9eigI10Hl782kDfZUUlRXw==}
+ caniuse-lite@1.0.30001717:
+ resolution: {integrity: sha512-auPpttCq6BDEG8ZAuHJIplGw6GODhjw+/11e7IjpnYCxZcW/ONgPs0KVBJ0d1bY3e2+7PRe5RCLyP+PfwVgkYw==}
chalk@4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
@@ -1558,23 +1558,23 @@ packages:
engines: {node: '>=4'}
hasBin: true
- cssnano-preset-default@7.0.6:
- resolution: {integrity: sha512-ZzrgYupYxEvdGGuqL+JKOY70s7+saoNlHSCK/OGn1vB2pQK8KSET8jvenzItcY+kA7NoWvfbb/YhlzuzNKjOhQ==}
+ cssnano-preset-default@7.0.7:
+ resolution: {integrity: sha512-jW6CG/7PNB6MufOrlovs1TvBTEVmhY45yz+bd0h6nw3h6d+1e+/TX+0fflZ+LzvZombbT5f+KC063w9VoHeHow==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- cssnano-utils@5.0.0:
- resolution: {integrity: sha512-Uij0Xdxc24L6SirFr25MlwC2rCFX6scyUmuKpzI+JQ7cyqDEwD42fJ0xfB3yLfOnRDU5LKGgjQ9FA6LYh76GWQ==}
+ cssnano-utils@5.0.1:
+ resolution: {integrity: sha512-ZIP71eQgG9JwjVZsTPSqhc6GHgEr53uJ7tK5///VfyWj6Xp2DBmixWHqJgPno+PqATzn48pL42ww9x5SSGmhZg==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- cssnano@7.0.6:
- resolution: {integrity: sha512-54woqx8SCbp8HwvNZYn68ZFAepuouZW4lTwiMVnBErM3VkO7/Sd4oTOt3Zz3bPx3kxQ36aISppyXj2Md4lg8bw==}
+ cssnano@7.0.7:
+ resolution: {integrity: sha512-evKu7yiDIF7oS+EIpwFlMF730ijRyLFaM2o5cTxRGJR9OKHKkc+qP443ZEVR9kZG0syaAJJCPJyfv5pbrxlSng==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
csso@5.0.5:
resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==}
@@ -1601,11 +1601,11 @@ packages:
datatables.net-buttons@3.2.3:
resolution: {integrity: sha512-K+WeQWUYVGe5c3Gwb8Gfi7YpUXbJEerik3B2vynnVKpBlYBF5AHTGbrK1Psek2q/mjxeIVNHafQ9eX2otLhJVw==}
- datatables.net-colreorder-bs5@2.0.4:
- resolution: {integrity: sha512-FRMADJ3FU8W5d5KiYV2eJIqi3+JDKBrRDpn45JRt6584M2Z+UBftxFGQ0EtbY+tPsCxLr7Y3j7f43d2xcUKTYQ==}
+ datatables.net-colreorder-bs5@2.1.0:
+ resolution: {integrity: sha512-s7ekoFwsj/NqyxnWQoGTQh8QbDvejM7dDSqLoAjfQDOgKpv3t0eZvzXIvufsZZhKPEJEw3Yof/tpN8+CHwDVxA==}
- datatables.net-colreorder@2.0.4:
- resolution: {integrity: sha512-j2d2uObivMaMLX+VTsIu9XEfucMPuS+OYurezQtPNHo0LgdXdgKvouEAUghVtlkTxW+jX7tjiSbagH2YWIS5Jg==}
+ datatables.net-colreorder@2.1.0:
+ resolution: {integrity: sha512-VMZkrR6cPzaCdlXnFmkM/oZS/TFY6NMusE7km3M3pYFVcmTyooQL/zDhEbhcCJrvNvuQkskruFYxwPK8+MzFPA==}
datatables.net-fixedheader-bs5@4.0.1:
resolution: {integrity: sha512-rA02QKEDvzj9dtwoUDl8hdSFDi4THpZeqCpCne0sVul1AM4OBy0O4zcx2WMSiEc5yEjFVZwKHmkvcDyhioV5IQ==}
@@ -1686,8 +1686,8 @@ packages:
ee-first@1.1.1:
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
- electron-to-chromium@1.5.149:
- resolution: {integrity: sha512-UyiO82eb9dVOx8YO3ajDf9jz2kKyt98DEITRdeLPstOEuTlLzDA4Gyq5K9he71TQziU5jUVu2OAu5N48HmQiyQ==}
+ electron-to-chromium@1.5.151:
+ resolution: {integrity: sha512-Rl6uugut2l9sLojjS4H4SAr3A4IgACMLgpuEMPYCVcKydzfyPrn5absNRju38IhQOf/NwjJY8OGWjlteqYeBCA==}
emoji-regex@10.4.0:
resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==}
@@ -1898,8 +1898,8 @@ packages:
resolution: {integrity: sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==}
engines: {node: '>=18.0.0'}
- eventsource@3.0.6:
- resolution: {integrity: sha512-l19WpE2m9hSuyP06+FbuUUf1G+R0SFLrtQfbRb9PRr+oimOfxQhgGCbVaXg5IvZyyTThJsxh6L/srkMiCeBPDA==}
+ eventsource@3.0.7:
+ resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==}
engines: {node: '>=18.0.0'}
execa@8.0.1:
@@ -2048,8 +2048,8 @@ packages:
resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
engines: {node: '>=18'}
- globals@16.0.0:
- resolution: {integrity: sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A==}
+ globals@16.1.0:
+ resolution: {integrity: sha512-aibexHNbb/jiUSObBgpHLj+sIuUmJnYcgXBlrfsiDZ9rt4aF2TFRbyLgZ2iFQuVZ1K5Mx3FVkbKRSgKrbK3K2g==}
engines: {node: '>=18'}
globalthis@1.0.4:
@@ -2132,8 +2132,8 @@ packages:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'}
- immutable@5.1.1:
- resolution: {integrity: sha512-3jatXi9ObIsPGr3N5hGw/vWWcTkq6hUYhpQz4k0wLC+owqWi/LiugIw9x0EdNZ2yGedKN/HzePiBvaJRXa0Ujg==}
+ immutable@5.1.2:
+ resolution: {integrity: sha512-qHKXW1q6liAk1Oys6umoaZbDRqjcjgSrbnrifHsfsttza7zcvRAsL7mMV6xWcyhwQy7Xj5v4hhbr6b+iDYwlmQ==}
import-fresh@3.3.1:
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
@@ -2373,13 +2373,13 @@ packages:
lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
- lint-staged@15.5.1:
- resolution: {integrity: sha512-6m7u8mue4Xn6wK6gZvSCQwBvMBR36xfY24nF5bMTf2MHDYG6S3yhJuOgdYVw99hsjyDt2d4z168b3naI8+NWtQ==}
+ lint-staged@15.5.2:
+ resolution: {integrity: sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==}
engines: {node: '>=18.12.0'}
hasBin: true
- listr2@8.3.2:
- resolution: {integrity: sha512-vsBzcU4oE+v0lj4FhVLzr9dBTv4/fHIa57l+GCwovP8MoFNZJTOhGU8PXd4v2VJCbECAaijBiHntiekFMLvo0g==}
+ listr2@8.3.3:
+ resolution: {integrity: sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==}
engines: {node: '>=18.0.0'}
loader-runner@4.3.0:
@@ -2698,17 +2698,17 @@ packages:
peerDependencies:
postcss: ^8.4
- postcss-colormin@7.0.2:
- resolution: {integrity: sha512-YntRXNngcvEvDbEjTdRWGU606eZvB5prmHG4BF0yLmVpamXbpsRJzevyy6MZVyuecgzI2AWAlvFi8DAeCqwpvA==}
+ postcss-colormin@7.0.3:
+ resolution: {integrity: sha512-xZxQcSyIVZbSsl1vjoqZAcMYYdnJsIyG8OvqShuuqf12S88qQboxxEy0ohNCOLwVPXTU+hFHvJPACRL2B5ohTA==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- postcss-convert-values@7.0.4:
- resolution: {integrity: sha512-e2LSXPqEHVW6aoGbjV9RsSSNDO3A0rZLCBxN24zvxF25WknMPpX8Dm9UxxThyEbaytzggRuZxaGXqaOhxQ514Q==}
+ postcss-convert-values@7.0.5:
+ resolution: {integrity: sha512-0VFhH8nElpIs3uXKnVtotDJJNX0OGYSZmdt4XfSfvOMrFw1jKfpwpZxfC4iN73CTM/MWakDEmsHQXkISYj4BXw==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
postcss-custom-media@11.0.5:
resolution: {integrity: sha512-SQHhayVNgDvSAdX9NQ/ygcDQGEY+aSF4b/96z7QUX6mqL5yl/JgG/DywcF6fW9XbnCRE+aVYk+9/nqGuzOPWeQ==}
@@ -2734,29 +2734,29 @@ packages:
peerDependencies:
postcss: ^8.4
- postcss-discard-comments@7.0.3:
- resolution: {integrity: sha512-q6fjd4WU4afNhWOA2WltHgCbkRhZPgQe7cXF74fuVB/ge4QbM9HEaOIzGSiMvM+g/cOsNAUGdf2JDzqA2F8iLA==}
+ postcss-discard-comments@7.0.4:
+ resolution: {integrity: sha512-6tCUoql/ipWwKtVP/xYiFf1U9QgJ0PUvxN7pTcsQ8Ns3Fnwq1pU5D5s1MhT/XySeLq6GXNvn37U46Ded0TckWg==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- postcss-discard-duplicates@7.0.1:
- resolution: {integrity: sha512-oZA+v8Jkpu1ct/xbbrntHRsfLGuzoP+cpt0nJe5ED2FQF8n8bJtn7Bo28jSmBYwqgqnqkuSXJfSUEE7if4nClQ==}
+ postcss-discard-duplicates@7.0.2:
+ resolution: {integrity: sha512-eTonaQvPZ/3i1ASDHOKkYwAybiM45zFIc7KXils4mQmHLqIswXD9XNOKEVxtTFnsmwYzF66u4LMgSr0abDlh5w==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- postcss-discard-empty@7.0.0:
- resolution: {integrity: sha512-e+QzoReTZ8IAwhnSdp/++7gBZ/F+nBq9y6PomfwORfP7q9nBpK5AMP64kOt0bA+lShBFbBDcgpJ3X4etHg4lzA==}
+ postcss-discard-empty@7.0.1:
+ resolution: {integrity: sha512-cFrJKZvcg/uxB6Ijr4l6qmn3pXQBna9zyrPC+sK0zjbkDUZew+6xDltSF7OeB7rAtzaaMVYSdbod+sZOCWnMOg==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- postcss-discard-overridden@7.0.0:
- resolution: {integrity: sha512-GmNAzx88u3k2+sBTZrJSDauR0ccpE24omTQCVmaTTZFz1du6AasspjaUPMJ2ud4RslZpoFKyf+6MSPETLojc6w==}
+ postcss-discard-overridden@7.0.1:
+ resolution: {integrity: sha512-7c3MMjjSZ/qYrx3uc1940GSOzN1Iqjtlqe8uoSg+qdVPYyRb0TILSqqmtlSFuE4mTDECwsm397Ya7iXGzfF7lg==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
postcss-double-position-gradients@6.0.1:
resolution: {integrity: sha512-ZitCwmvOR4JzXmKw6sZblTgwV1dcfLvClcyjADuqZ5hU0Uk4SVNpvSN9w8NcJ7XuxhRYxVA8m8AB3gy+HNBQOA==}
@@ -2818,41 +2818,41 @@ packages:
peerDependencies:
postcss: ^8.4
- postcss-merge-longhand@7.0.4:
- resolution: {integrity: sha512-zer1KoZA54Q8RVHKOY5vMke0cCdNxMP3KBfDerjH/BYHh4nCIh+1Yy0t1pAEQF18ac/4z3OFclO+ZVH8azjR4A==}
+ postcss-merge-longhand@7.0.5:
+ resolution: {integrity: sha512-Kpu5v4Ys6QI59FxmxtNB/iHUVDn9Y9sYw66D6+SZoIk4QTz1prC4aYkhIESu+ieG1iylod1f8MILMs1Em3mmIw==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- postcss-merge-rules@7.0.4:
- resolution: {integrity: sha512-ZsaamiMVu7uBYsIdGtKJ64PkcQt6Pcpep/uO90EpLS3dxJi6OXamIobTYcImyXGoW0Wpugh7DSD3XzxZS9JCPg==}
+ postcss-merge-rules@7.0.5:
+ resolution: {integrity: sha512-ZonhuSwEaWA3+xYbOdJoEReKIBs5eDiBVLAGpYZpNFPzXZcEE5VKR7/qBEQvTZpiwjqhhqEQ+ax5O3VShBj9Wg==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- postcss-minify-font-values@7.0.0:
- resolution: {integrity: sha512-2ckkZtgT0zG8SMc5aoNwtm5234eUx1GGFJKf2b1bSp8UflqaeFzR50lid4PfqVI9NtGqJ2J4Y7fwvnP/u1cQog==}
+ postcss-minify-font-values@7.0.1:
+ resolution: {integrity: sha512-2m1uiuJeTplll+tq4ENOQSzB8LRnSUChBv7oSyFLsJRtUgAAJGP6LLz0/8lkinTgxrmJSPOEhgY1bMXOQ4ZXhQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- postcss-minify-gradients@7.0.0:
- resolution: {integrity: sha512-pdUIIdj/C93ryCHew0UgBnL2DtUS3hfFa5XtERrs4x+hmpMYGhbzo6l/Ir5de41O0GaKVpK1ZbDNXSY6GkXvtg==}
+ postcss-minify-gradients@7.0.1:
+ resolution: {integrity: sha512-X9JjaysZJwlqNkJbUDgOclyG3jZEpAMOfof6PUZjPnPrePnPG62pS17CjdM32uT1Uq1jFvNSff9l7kNbmMSL2A==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- postcss-minify-params@7.0.2:
- resolution: {integrity: sha512-nyqVLu4MFl9df32zTsdcLqCFfE/z2+f8GE1KHPxWOAmegSo6lpV2GNy5XQvrzwbLmiU7d+fYay4cwto1oNdAaQ==}
+ postcss-minify-params@7.0.3:
+ resolution: {integrity: sha512-vUKV2+f5mtjewYieanLX0xemxIp1t0W0H/D11u+kQV/MWdygOO7xPMkbK+r9P6Lhms8MgzKARF/g5OPXhb8tgg==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- postcss-minify-selectors@7.0.4:
- resolution: {integrity: sha512-JG55VADcNb4xFCf75hXkzc1rNeURhlo7ugf6JjiiKRfMsKlDzN9CXHZDyiG6x/zGchpjQS+UAgb1d4nqXqOpmA==}
+ postcss-minify-selectors@7.0.5:
+ resolution: {integrity: sha512-x2/IvofHcdIrAm9Q+p06ZD1h6FPcQ32WtCRVodJLDR+WMn8EVHI1kvLxZuGKz/9EY5nAmI6lIQIrpo4tBy5+ug==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
postcss-modules-extract-imports@3.1.0:
resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==}
@@ -2884,59 +2884,59 @@ packages:
peerDependencies:
postcss: ^8.4
- postcss-normalize-charset@7.0.0:
- resolution: {integrity: sha512-ABisNUXMeZeDNzCQxPxBCkXexvBrUHV+p7/BXOY+ulxkcjUZO0cp8ekGBwvIh2LbCwnWbyMPNJVtBSdyhM2zYQ==}
+ postcss-normalize-charset@7.0.1:
+ resolution: {integrity: sha512-sn413ofhSQHlZFae//m9FTOfkmiZ+YQXsbosqOWRiVQncU2BA3daX3n0VF3cG6rGLSFVc5Di/yns0dFfh8NFgQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- postcss-normalize-display-values@7.0.0:
- resolution: {integrity: sha512-lnFZzNPeDf5uGMPYgGOw7v0BfB45+irSRz9gHQStdkkhiM0gTfvWkWB5BMxpn0OqgOQuZG/mRlZyJxp0EImr2Q==}
+ postcss-normalize-display-values@7.0.1:
+ resolution: {integrity: sha512-E5nnB26XjSYz/mGITm6JgiDpAbVuAkzXwLzRZtts19jHDUBFxZ0BkXAehy0uimrOjYJbocby4FVswA/5noOxrQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- postcss-normalize-positions@7.0.0:
- resolution: {integrity: sha512-I0yt8wX529UKIGs2y/9Ybs2CelSvItfmvg/DBIjTnoUSrPxSV7Z0yZ8ShSVtKNaV/wAY+m7bgtyVQLhB00A1NQ==}
+ postcss-normalize-positions@7.0.1:
+ resolution: {integrity: sha512-pB/SzrIP2l50ZIYu+yQZyMNmnAcwyYb9R1fVWPRxm4zcUFCY2ign7rcntGFuMXDdd9L2pPNUgoODDk91PzRZuQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- postcss-normalize-repeat-style@7.0.0:
- resolution: {integrity: sha512-o3uSGYH+2q30ieM3ppu9GTjSXIzOrRdCUn8UOMGNw7Af61bmurHTWI87hRybrP6xDHvOe5WlAj3XzN6vEO8jLw==}
+ postcss-normalize-repeat-style@7.0.1:
+ resolution: {integrity: sha512-NsSQJ8zj8TIDiF0ig44Byo3Jk9e4gNt9x2VIlJudnQQ5DhWAHJPF4Tr1ITwyHio2BUi/I6Iv0HRO7beHYOloYQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- postcss-normalize-string@7.0.0:
- resolution: {integrity: sha512-w/qzL212DFVOpMy3UGyxrND+Kb0fvCiBBujiaONIihq7VvtC7bswjWgKQU/w4VcRyDD8gpfqUiBQ4DUOwEJ6Qg==}
+ postcss-normalize-string@7.0.1:
+ resolution: {integrity: sha512-QByrI7hAhsoze992kpbMlJSbZ8FuCEc1OT9EFbZ6HldXNpsdpZr+YXC5di3UEv0+jeZlHbZcoCADgb7a+lPmmQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- postcss-normalize-timing-functions@7.0.0:
- resolution: {integrity: sha512-tNgw3YV0LYoRwg43N3lTe3AEWZ66W7Dh7lVEpJbHoKOuHc1sLrzMLMFjP8SNULHaykzsonUEDbKedv8C+7ej6g==}
+ postcss-normalize-timing-functions@7.0.1:
+ resolution: {integrity: sha512-bHifyuuSNdKKsnNJ0s8fmfLMlvsQwYVxIoUBnowIVl2ZAdrkYQNGVB4RxjfpvkMjipqvbz0u7feBZybkl/6NJg==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- postcss-normalize-unicode@7.0.2:
- resolution: {integrity: sha512-ztisabK5C/+ZWBdYC+Y9JCkp3M9qBv/XFvDtSw0d/XwfT3UaKeW/YTm/MD/QrPNxuecia46vkfEhewjwcYFjkg==}
+ postcss-normalize-unicode@7.0.3:
+ resolution: {integrity: sha512-EcoA29LvG3F+EpOh03iqu+tJY3uYYKzArqKJHxDhUYLa2u58aqGq16K6/AOsXD9yqLN8O6y9mmePKN5cx6krOw==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- postcss-normalize-url@7.0.0:
- resolution: {integrity: sha512-+d7+PpE+jyPX1hDQZYG+NaFD+Nd2ris6r8fPTBAjE8z/U41n/bib3vze8x7rKs5H1uEw5ppe9IojewouHk0klQ==}
+ postcss-normalize-url@7.0.1:
+ resolution: {integrity: sha512-sUcD2cWtyK1AOL/82Fwy1aIVm/wwj5SdZkgZ3QiUzSzQQofrbq15jWJ3BA7Z+yVRwamCjJgZJN0I9IS7c6tgeQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- postcss-normalize-whitespace@7.0.0:
- resolution: {integrity: sha512-37/toN4wwZErqohedXYqWgvcHUGlT8O/m2jVkAfAe9Bd4MzRqlBmXrJRePH0e9Wgnz2X7KymTgTOaaFizQe3AQ==}
+ postcss-normalize-whitespace@7.0.1:
+ resolution: {integrity: sha512-vsbgFHMFQrJBJKrUFJNZ2pgBeBkC2IvvoHjz1to0/0Xk7sII24T0qFOiJzG6Fu3zJoq/0yI4rKWi7WhApW+EFA==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
postcss-opacity-percentage@3.0.0:
resolution: {integrity: sha512-K6HGVzyxUxd/VgZdX04DCtdwWJ4NGLG212US4/LA1TLAbHgmAsTWVR86o+gGIbFtnTkfOpb9sCRBx8K7HO66qQ==}
@@ -2944,11 +2944,11 @@ packages:
peerDependencies:
postcss: ^8.4
- postcss-ordered-values@7.0.1:
- resolution: {integrity: sha512-irWScWRL6nRzYmBOXReIKch75RRhNS86UPUAxXdmW/l0FcAsg0lvAXQCby/1lymxn/o0gVa6Rv/0f03eJOwHxw==}
+ postcss-ordered-values@7.0.2:
+ resolution: {integrity: sha512-AMJjt1ECBffF7CEON/Y0rekRLS6KsePU6PRP08UqYW4UGFRnTXNrByUzYK1h8AC7UWTZdQ9O3Oq9kFIhm0SFEw==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
postcss-overflow-shorthand@6.0.0:
resolution: {integrity: sha512-BdDl/AbVkDjoTofzDQnwDdm/Ym6oS9KgmO7Gr+LHYjNWJ6ExORe4+3pcLQsLA9gIROMkiGVjjwZNoL/mpXHd5Q==}
@@ -2979,17 +2979,17 @@ packages:
peerDependencies:
postcss: ^8.4
- postcss-reduce-initial@7.0.2:
- resolution: {integrity: sha512-pOnu9zqQww7dEKf62Nuju6JgsW2V0KRNBHxeKohU+JkHd/GAH5uvoObqFLqkeB2n20mr6yrlWDvo5UBU5GnkfA==}
+ postcss-reduce-initial@7.0.3:
+ resolution: {integrity: sha512-RFvkZaqiWtGMlVjlUHpaxGqEL27lgt+Q2Ixjf83CRAzqdo+TsDyGPtJUbPx2MuYIJ+sCQc2TrOvRnhcXQfgIVA==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- postcss-reduce-transforms@7.0.0:
- resolution: {integrity: sha512-pnt1HKKZ07/idH8cpATX/ujMbtOGhUfE+m8gbqwJE05aTaNw8gbo34a2e3if0xc0dlu75sUOiqvwCGY3fzOHew==}
+ postcss-reduce-transforms@7.0.1:
+ resolution: {integrity: sha512-MhyEbfrm+Mlp/36hvZ9mT9DaO7dbncU0CvWI8V93LRkY6IYlu38OPg3FObnuKTUxJ4qA8HpurdQOo5CyqqO76g==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
postcss-replace-overflow-wrap@4.0.0:
resolution: {integrity: sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==}
@@ -3002,25 +3002,21 @@ packages:
peerDependencies:
postcss: ^8.4
- postcss-selector-parser@6.1.2:
- resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
- engines: {node: '>=4'}
-
postcss-selector-parser@7.1.0:
resolution: {integrity: sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==}
engines: {node: '>=4'}
- postcss-svgo@7.0.1:
- resolution: {integrity: sha512-0WBUlSL4lhD9rA5k1e5D8EN5wCEyZD6HJk0jIvRxl+FDVOMlJ7DePHYWGGVc5QRqrJ3/06FTXM0bxjmJpmTPSA==}
+ postcss-svgo@7.0.2:
+ resolution: {integrity: sha512-5Dzy66JlnRM6pkdOTF8+cGsB1fnERTE8Nc+Eed++fOWo1hdsBptCsbG8UuJkgtZt75bRtMJIrPeZmtfANixdFA==}
engines: {node: ^18.12.0 || ^20.9.0 || >= 18}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
- postcss-unique-selectors@7.0.3:
- resolution: {integrity: sha512-J+58u5Ic5T1QjP/LDV9g3Cx4CNOgB5vz+kM6+OxHHhFACdcDeKhBXjQmB7fnIZM12YSTvsL0Opwco83DmacW2g==}
+ postcss-unique-selectors@7.0.4:
+ resolution: {integrity: sha512-pmlZjsmEAG7cHd7uK3ZiNSW6otSZ13RHuZ/4cDN/bVglS5EpF2r2oxY99SuOHa8m7AWoBCelTS3JPpzsIs8skQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
postcss-value-parser@4.2.0:
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
@@ -3307,11 +3303,11 @@ packages:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
- stylehacks@7.0.4:
- resolution: {integrity: sha512-i4zfNrGMt9SB4xRK9L83rlsFCgdGANfeDAYacO1pkqcE7cRHPdWHwnKZVz7WY17Veq/FvyYsRAU++Ga+qDFIww==}
+ stylehacks@7.0.5:
+ resolution: {integrity: sha512-5kNb7V37BNf0Q3w+1pxfa+oiNPS++/b4Jil9e/kPDgrk1zjEd6uR7SZeJiYaLYH6RRSC1XX2/37OTeU/4FvuIA==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
- postcss: ^8.4.31
+ postcss: ^8.4.32
supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
@@ -3475,8 +3471,8 @@ packages:
resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==}
engines: {node: '>=10.13.0'}
- webpack@5.99.7:
- resolution: {integrity: sha512-CNqKBRMQjwcmKR0idID5va1qlhrqVUKpovi+Ec79ksW8ux7iS1+A6VqzfZXgVYCFRKl7XL5ap3ZoMpwBJxcg0w==}
+ webpack@5.99.8:
+ resolution: {integrity: sha512-lQ3CPiSTpfOnrEGeXDwoq5hIGzSjmwD72GdfVzF7CQAI7t47rJG9eDWvcEkEn3CUQymAElVvDg3YNTlCYj+qUQ==}
engines: {node: '>=10.13.0'}
hasBin: true
peerDependencies:
@@ -3537,8 +3533,8 @@ packages:
peerDependencies:
zod: ^3.24.1
- zod@3.24.3:
- resolution: {integrity: sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==}
+ zod@3.24.4:
+ resolution: {integrity: sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==}
snapshots:
@@ -3553,18 +3549,18 @@ snapshots:
js-tokens: 4.0.0
picocolors: 1.1.1
- '@babel/compat-data@7.27.1': {}
+ '@babel/compat-data@7.27.2': {}
'@babel/core@7.27.1':
dependencies:
'@ampproject/remapping': 2.3.0
'@babel/code-frame': 7.27.1
'@babel/generator': 7.27.1
- '@babel/helper-compilation-targets': 7.27.1
+ '@babel/helper-compilation-targets': 7.27.2
'@babel/helper-module-transforms': 7.27.1(@babel/core@7.27.1)
'@babel/helpers': 7.27.1
- '@babel/parser': 7.27.1
- '@babel/template': 7.27.1
+ '@babel/parser': 7.27.2
+ '@babel/template': 7.27.2
'@babel/traverse': 7.27.1
'@babel/types': 7.27.1
convert-source-map: 2.0.0
@@ -3577,7 +3573,7 @@ snapshots:
'@babel/generator@7.27.1':
dependencies:
- '@babel/parser': 7.27.1
+ '@babel/parser': 7.27.2
'@babel/types': 7.27.1
'@jridgewell/gen-mapping': 0.3.8
'@jridgewell/trace-mapping': 0.3.25
@@ -3587,9 +3583,9 @@ snapshots:
dependencies:
'@babel/types': 7.27.1
- '@babel/helper-compilation-targets@7.27.1':
+ '@babel/helper-compilation-targets@7.27.2':
dependencies:
- '@babel/compat-data': 7.27.1
+ '@babel/compat-data': 7.27.2
'@babel/helper-validator-option': 7.27.1
browserslist: 4.24.5
lru-cache: 5.1.1
@@ -3618,7 +3614,7 @@ snapshots:
'@babel/helper-define-polyfill-provider@0.6.4(@babel/core@7.27.1)':
dependencies:
'@babel/core': 7.27.1
- '@babel/helper-compilation-targets': 7.27.1
+ '@babel/helper-compilation-targets': 7.27.2
'@babel/helper-plugin-utils': 7.27.1
debug: 4.4.0
lodash.debounce: 4.0.8
@@ -3688,7 +3684,7 @@ snapshots:
'@babel/helper-wrap-function@7.27.1':
dependencies:
- '@babel/template': 7.27.1
+ '@babel/template': 7.27.2
'@babel/traverse': 7.27.1
'@babel/types': 7.27.1
transitivePeerDependencies:
@@ -3696,10 +3692,10 @@ snapshots:
'@babel/helpers@7.27.1':
dependencies:
- '@babel/template': 7.27.1
+ '@babel/template': 7.27.2
'@babel/types': 7.27.1
- '@babel/parser@7.27.1':
+ '@babel/parser@7.27.2':
dependencies:
'@babel/types': 7.27.1
@@ -3811,7 +3807,7 @@ snapshots:
dependencies:
'@babel/core': 7.27.1
'@babel/helper-annotate-as-pure': 7.27.1
- '@babel/helper-compilation-targets': 7.27.1
+ '@babel/helper-compilation-targets': 7.27.2
'@babel/helper-plugin-utils': 7.27.1
'@babel/helper-replace-supers': 7.27.1(@babel/core@7.27.1)
'@babel/traverse': 7.27.1
@@ -3823,7 +3819,7 @@ snapshots:
dependencies:
'@babel/core': 7.27.1
'@babel/helper-plugin-utils': 7.27.1
- '@babel/template': 7.27.1
+ '@babel/template': 7.27.2
'@babel/plugin-transform-destructuring@7.27.1(@babel/core@7.27.1)':
dependencies:
@@ -3873,7 +3869,7 @@ snapshots:
'@babel/plugin-transform-function-name@7.27.1(@babel/core@7.27.1)':
dependencies:
'@babel/core': 7.27.1
- '@babel/helper-compilation-targets': 7.27.1
+ '@babel/helper-compilation-targets': 7.27.2
'@babel/helper-plugin-utils': 7.27.1
'@babel/traverse': 7.27.1
transitivePeerDependencies:
@@ -3954,11 +3950,12 @@ snapshots:
'@babel/core': 7.27.1
'@babel/helper-plugin-utils': 7.27.1
- '@babel/plugin-transform-object-rest-spread@7.27.1(@babel/core@7.27.1)':
+ '@babel/plugin-transform-object-rest-spread@7.27.2(@babel/core@7.27.1)':
dependencies:
'@babel/core': 7.27.1
- '@babel/helper-compilation-targets': 7.27.1
+ '@babel/helper-compilation-targets': 7.27.2
'@babel/helper-plugin-utils': 7.27.1
+ '@babel/plugin-transform-destructuring': 7.27.1(@babel/core@7.27.1)
'@babel/plugin-transform-parameters': 7.27.1(@babel/core@7.27.1)
'@babel/plugin-transform-object-super@7.27.1(@babel/core@7.27.1)':
@@ -4076,11 +4073,11 @@ snapshots:
'@babel/helper-create-regexp-features-plugin': 7.27.1(@babel/core@7.27.1)
'@babel/helper-plugin-utils': 7.27.1
- '@babel/preset-env@7.27.1(@babel/core@7.27.1)':
+ '@babel/preset-env@7.27.2(@babel/core@7.27.1)':
dependencies:
- '@babel/compat-data': 7.27.1
+ '@babel/compat-data': 7.27.2
'@babel/core': 7.27.1
- '@babel/helper-compilation-targets': 7.27.1
+ '@babel/helper-compilation-targets': 7.27.2
'@babel/helper-plugin-utils': 7.27.1
'@babel/helper-validator-option': 7.27.1
'@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.27.1(@babel/core@7.27.1)
@@ -4122,7 +4119,7 @@ snapshots:
'@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.27.1)
'@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.27.1)
'@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.27.1)
- '@babel/plugin-transform-object-rest-spread': 7.27.1(@babel/core@7.27.1)
+ '@babel/plugin-transform-object-rest-spread': 7.27.2(@babel/core@7.27.1)
'@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.27.1)
'@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.27.1)
'@babel/plugin-transform-optional-chaining': 7.27.1(@babel/core@7.27.1)
@@ -4158,18 +4155,18 @@ snapshots:
'@babel/types': 7.27.1
esutils: 2.0.3
- '@babel/template@7.27.1':
+ '@babel/template@7.27.2':
dependencies:
'@babel/code-frame': 7.27.1
- '@babel/parser': 7.27.1
+ '@babel/parser': 7.27.2
'@babel/types': 7.27.1
'@babel/traverse@7.27.1':
dependencies:
'@babel/code-frame': 7.27.1
'@babel/generator': 7.27.1
- '@babel/parser': 7.27.1
- '@babel/template': 7.27.1
+ '@babel/parser': 7.27.2
+ '@babel/template': 7.27.2
'@babel/types': 7.27.1
debug: 4.4.0
globals: 11.12.0
@@ -4490,7 +4487,7 @@ snapshots:
'@humanwhocodes/retry@0.3.1': {}
- '@humanwhocodes/retry@0.4.2': {}
+ '@humanwhocodes/retry@0.4.3': {}
'@jest/schemas@29.6.3':
dependencies:
@@ -4501,7 +4498,7 @@ snapshots:
'@jest/schemas': 29.6.3
'@types/istanbul-lib-coverage': 2.0.6
'@types/istanbul-reports': 3.0.4
- '@types/node': 22.15.3
+ '@types/node': 22.15.17
'@types/yargs': 17.0.33
chalk: 4.1.2
@@ -4527,18 +4524,18 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.0
- '@modelcontextprotocol/sdk@1.11.0':
+ '@modelcontextprotocol/sdk@1.11.1':
dependencies:
content-type: 1.0.5
cors: 2.8.5
cross-spawn: 7.0.6
- eventsource: 3.0.6
+ eventsource: 3.0.7
express: 5.1.0
express-rate-limit: 7.5.0(express@5.1.0)
pkce-challenge: 5.0.0
raw-body: 3.0.0
- zod: 3.24.3
- zod-to-json-schema: 3.24.5(zod@3.24.3)
+ zod: 3.24.4
+ zod-to-json-schema: 3.24.5(zod@3.24.4)
transitivePeerDependencies:
- supports-color
@@ -4639,7 +4636,7 @@ snapshots:
'@types/json5@0.0.29': {}
- '@types/node@22.15.3':
+ '@types/node@22.15.17':
dependencies:
undici-types: 6.21.0
@@ -4725,20 +4722,20 @@ snapshots:
'@webassemblyjs/ast': 1.14.1
'@xtuc/long': 4.2.2
- '@webpack-cli/configtest@3.0.1(webpack-cli@6.0.1)(webpack@5.99.7)':
+ '@webpack-cli/configtest@3.0.1(webpack-cli@6.0.1)(webpack@5.99.8)':
dependencies:
- webpack: 5.99.7(webpack-cli@6.0.1)
- webpack-cli: 6.0.1(webpack@5.99.7)
+ webpack: 5.99.8(webpack-cli@6.0.1)
+ webpack-cli: 6.0.1(webpack@5.99.8)
- '@webpack-cli/info@3.0.1(webpack-cli@6.0.1)(webpack@5.99.7)':
+ '@webpack-cli/info@3.0.1(webpack-cli@6.0.1)(webpack@5.99.8)':
dependencies:
- webpack: 5.99.7(webpack-cli@6.0.1)
- webpack-cli: 6.0.1(webpack@5.99.7)
+ webpack: 5.99.8(webpack-cli@6.0.1)
+ webpack-cli: 6.0.1(webpack@5.99.8)
- '@webpack-cli/serve@3.0.1(webpack-cli@6.0.1)(webpack@5.99.7)':
+ '@webpack-cli/serve@3.0.1(webpack-cli@6.0.1)(webpack@5.99.8)':
dependencies:
- webpack: 5.99.7(webpack-cli@6.0.1)
- webpack-cli: 6.0.1(webpack@5.99.7)
+ webpack: 5.99.8(webpack-cli@6.0.1)
+ webpack-cli: 6.0.1(webpack@5.99.8)
'@xtuc/ieee754@1.2.0': {}
@@ -4849,7 +4846,7 @@ snapshots:
autoprefixer@10.4.21(postcss@8.5.3):
dependencies:
browserslist: 4.24.5
- caniuse-lite: 1.0.30001716
+ caniuse-lite: 1.0.30001717
fraction.js: 4.3.7
normalize-range: 0.1.2
picocolors: 1.1.1
@@ -4860,15 +4857,15 @@ snapshots:
dependencies:
possible-typed-array-names: 1.1.0
- babel-loader@10.0.0(@babel/core@7.27.1)(webpack@5.99.7):
+ babel-loader@10.0.0(@babel/core@7.27.1)(webpack@5.99.8):
dependencies:
'@babel/core': 7.27.1
find-up: 5.0.0
- webpack: 5.99.7(webpack-cli@6.0.1)
+ webpack: 5.99.8(webpack-cli@6.0.1)
babel-plugin-polyfill-corejs2@0.4.13(@babel/core@7.27.1):
dependencies:
- '@babel/compat-data': 7.27.1
+ '@babel/compat-data': 7.27.2
'@babel/core': 7.27.1
'@babel/helper-define-polyfill-provider': 0.6.4(@babel/core@7.27.1)
semver: 6.3.1
@@ -4910,9 +4907,9 @@ snapshots:
boolbase@1.0.0: {}
- bootstrap-icons@1.11.3: {}
+ bootstrap-icons@1.13.1: {}
- bootstrap@5.3.5(@popperjs/core@2.11.8):
+ bootstrap@5.3.6(@popperjs/core@2.11.8):
dependencies:
'@popperjs/core': 2.11.8
@@ -4927,8 +4924,8 @@ snapshots:
browserslist@4.24.5:
dependencies:
- caniuse-lite: 1.0.30001716
- electron-to-chromium: 1.5.149
+ caniuse-lite: 1.0.30001717
+ electron-to-chromium: 1.5.151
node-releases: 2.0.19
update-browserslist-db: 1.1.3(browserslist@4.24.5)
@@ -4969,11 +4966,11 @@ snapshots:
caniuse-api@3.0.0:
dependencies:
browserslist: 4.24.5
- caniuse-lite: 1.0.30001716
+ caniuse-lite: 1.0.30001717
lodash.memoize: 4.1.2
lodash.uniq: 4.5.0
- caniuse-lite@1.0.30001716: {}
+ caniuse-lite@1.0.30001717: {}
chalk@4.1.2:
dependencies:
@@ -5043,14 +5040,14 @@ snapshots:
cookie@0.7.2: {}
- copy-webpack-plugin@13.0.0(webpack@5.99.7):
+ copy-webpack-plugin@13.0.0(webpack@5.99.8):
dependencies:
glob-parent: 6.0.2
normalize-path: 3.0.0
schema-utils: 4.3.2
serialize-javascript: 6.0.2
tinyglobby: 0.2.13
- webpack: 5.99.7(webpack-cli@6.0.1)
+ webpack: 5.99.8(webpack-cli@6.0.1)
core-js-compat@3.42.0:
dependencies:
@@ -5092,7 +5089,7 @@ snapshots:
postcss-selector-parser: 7.1.0
postcss-value-parser: 4.2.0
- css-loader@7.1.2(webpack@5.99.7):
+ css-loader@7.1.2(webpack@5.99.8):
dependencies:
icss-utils: 5.1.0(postcss@8.5.3)
postcss: 8.5.3
@@ -5103,17 +5100,17 @@ snapshots:
postcss-value-parser: 4.2.0
semver: 7.7.1
optionalDependencies:
- webpack: 5.99.7(webpack-cli@6.0.1)
+ webpack: 5.99.8(webpack-cli@6.0.1)
- css-minimizer-webpack-plugin@7.0.2(webpack@5.99.7):
+ css-minimizer-webpack-plugin@7.0.2(webpack@5.99.8):
dependencies:
'@jridgewell/trace-mapping': 0.3.25
- cssnano: 7.0.6(postcss@8.5.3)
+ cssnano: 7.0.7(postcss@8.5.3)
jest-worker: 29.7.0
postcss: 8.5.3
schema-utils: 4.3.2
serialize-javascript: 6.0.2
- webpack: 5.99.7(webpack-cli@6.0.1)
+ webpack: 5.99.8(webpack-cli@6.0.1)
css-prefers-color-scheme@10.0.0(postcss@8.5.3):
dependencies:
@@ -5143,47 +5140,47 @@ snapshots:
cssesc@3.0.0: {}
- cssnano-preset-default@7.0.6(postcss@8.5.3):
+ cssnano-preset-default@7.0.7(postcss@8.5.3):
dependencies:
browserslist: 4.24.5
css-declaration-sorter: 7.2.0(postcss@8.5.3)
- cssnano-utils: 5.0.0(postcss@8.5.3)
+ cssnano-utils: 5.0.1(postcss@8.5.3)
postcss: 8.5.3
postcss-calc: 10.1.1(postcss@8.5.3)
- postcss-colormin: 7.0.2(postcss@8.5.3)
- postcss-convert-values: 7.0.4(postcss@8.5.3)
- postcss-discard-comments: 7.0.3(postcss@8.5.3)
- postcss-discard-duplicates: 7.0.1(postcss@8.5.3)
- postcss-discard-empty: 7.0.0(postcss@8.5.3)
- postcss-discard-overridden: 7.0.0(postcss@8.5.3)
- postcss-merge-longhand: 7.0.4(postcss@8.5.3)
- postcss-merge-rules: 7.0.4(postcss@8.5.3)
- postcss-minify-font-values: 7.0.0(postcss@8.5.3)
- postcss-minify-gradients: 7.0.0(postcss@8.5.3)
- postcss-minify-params: 7.0.2(postcss@8.5.3)
- postcss-minify-selectors: 7.0.4(postcss@8.5.3)
- postcss-normalize-charset: 7.0.0(postcss@8.5.3)
- postcss-normalize-display-values: 7.0.0(postcss@8.5.3)
- postcss-normalize-positions: 7.0.0(postcss@8.5.3)
- postcss-normalize-repeat-style: 7.0.0(postcss@8.5.3)
- postcss-normalize-string: 7.0.0(postcss@8.5.3)
- postcss-normalize-timing-functions: 7.0.0(postcss@8.5.3)
- postcss-normalize-unicode: 7.0.2(postcss@8.5.3)
- postcss-normalize-url: 7.0.0(postcss@8.5.3)
- postcss-normalize-whitespace: 7.0.0(postcss@8.5.3)
- postcss-ordered-values: 7.0.1(postcss@8.5.3)
- postcss-reduce-initial: 7.0.2(postcss@8.5.3)
- postcss-reduce-transforms: 7.0.0(postcss@8.5.3)
- postcss-svgo: 7.0.1(postcss@8.5.3)
- postcss-unique-selectors: 7.0.3(postcss@8.5.3)
-
- cssnano-utils@5.0.0(postcss@8.5.3):
+ postcss-colormin: 7.0.3(postcss@8.5.3)
+ postcss-convert-values: 7.0.5(postcss@8.5.3)
+ postcss-discard-comments: 7.0.4(postcss@8.5.3)
+ postcss-discard-duplicates: 7.0.2(postcss@8.5.3)
+ postcss-discard-empty: 7.0.1(postcss@8.5.3)
+ postcss-discard-overridden: 7.0.1(postcss@8.5.3)
+ postcss-merge-longhand: 7.0.5(postcss@8.5.3)
+ postcss-merge-rules: 7.0.5(postcss@8.5.3)
+ postcss-minify-font-values: 7.0.1(postcss@8.5.3)
+ postcss-minify-gradients: 7.0.1(postcss@8.5.3)
+ postcss-minify-params: 7.0.3(postcss@8.5.3)
+ postcss-minify-selectors: 7.0.5(postcss@8.5.3)
+ postcss-normalize-charset: 7.0.1(postcss@8.5.3)
+ postcss-normalize-display-values: 7.0.1(postcss@8.5.3)
+ postcss-normalize-positions: 7.0.1(postcss@8.5.3)
+ postcss-normalize-repeat-style: 7.0.1(postcss@8.5.3)
+ postcss-normalize-string: 7.0.1(postcss@8.5.3)
+ postcss-normalize-timing-functions: 7.0.1(postcss@8.5.3)
+ postcss-normalize-unicode: 7.0.3(postcss@8.5.3)
+ postcss-normalize-url: 7.0.1(postcss@8.5.3)
+ postcss-normalize-whitespace: 7.0.1(postcss@8.5.3)
+ postcss-ordered-values: 7.0.2(postcss@8.5.3)
+ postcss-reduce-initial: 7.0.3(postcss@8.5.3)
+ postcss-reduce-transforms: 7.0.1(postcss@8.5.3)
+ postcss-svgo: 7.0.2(postcss@8.5.3)
+ postcss-unique-selectors: 7.0.4(postcss@8.5.3)
+
+ cssnano-utils@5.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
- cssnano@7.0.6(postcss@8.5.3):
+ cssnano@7.0.7(postcss@8.5.3):
dependencies:
- cssnano-preset-default: 7.0.6(postcss@8.5.3)
+ cssnano-preset-default: 7.0.7(postcss@8.5.3)
lilconfig: 3.1.3
postcss: 8.5.3
@@ -5225,13 +5222,13 @@ snapshots:
datatables.net: 2.3.0
jquery: 3.7.1
- datatables.net-colreorder-bs5@2.0.4:
+ datatables.net-colreorder-bs5@2.1.0:
dependencies:
datatables.net-bs5: 2.3.0
- datatables.net-colreorder: 2.0.4
+ datatables.net-colreorder: 2.1.0
jquery: 3.7.1
- datatables.net-colreorder@2.0.4:
+ datatables.net-colreorder@2.1.0:
dependencies:
datatables.net: 2.3.0
jquery: 3.7.1
@@ -5324,7 +5321,7 @@ snapshots:
ee-first@1.1.1: {}
- electron-to-chromium@1.5.149: {}
+ electron-to-chromium@1.5.151: {}
emoji-regex@10.4.0: {}
@@ -5544,8 +5541,8 @@ snapshots:
'@eslint/plugin-kit': 0.2.8
'@humanfs/node': 0.16.6
'@humanwhocodes/module-importer': 1.0.1
- '@humanwhocodes/retry': 0.4.2
- '@modelcontextprotocol/sdk': 1.11.0
+ '@humanwhocodes/retry': 0.4.3
+ '@modelcontextprotocol/sdk': 1.11.1
'@types/estree': 1.0.7
'@types/json-schema': 7.0.15
ajv: 6.12.6
@@ -5570,7 +5567,7 @@ snapshots:
minimatch: 3.1.2
natural-compare: 1.4.0
optionator: 0.9.4
- zod: 3.24.3
+ zod: 3.24.4
optionalDependencies:
jiti: 1.21.7
transitivePeerDependencies:
@@ -5604,7 +5601,7 @@ snapshots:
eventsource-parser@3.0.1: {}
- eventsource@3.0.6:
+ eventsource@3.0.7:
dependencies:
eventsource-parser: 3.0.1
@@ -5674,11 +5671,11 @@ snapshots:
dependencies:
flat-cache: 4.0.1
- file-loader@6.2.0(webpack@5.99.7):
+ file-loader@6.2.0(webpack@5.99.8):
dependencies:
loader-utils: 2.0.4
schema-utils: 3.3.0
- webpack: 5.99.7(webpack-cli@6.0.1)
+ webpack: 5.99.8(webpack-cli@6.0.1)
fill-range@7.1.1:
dependencies:
@@ -5785,7 +5782,7 @@ snapshots:
globals@14.0.0: {}
- globals@16.0.0: {}
+ globals@16.1.0: {}
globalthis@1.0.4:
dependencies:
@@ -5828,14 +5825,14 @@ snapshots:
relateurl: 0.2.7
terser: 5.39.0
- html-minimizer-webpack-plugin@5.0.2(webpack@5.99.7):
+ html-minimizer-webpack-plugin@5.0.2(webpack@5.99.8):
dependencies:
'@types/html-minifier-terser': 7.0.2
html-minifier-terser: 7.2.0
jest-worker: 29.7.0
schema-utils: 4.3.2
serialize-javascript: 6.0.2
- webpack: 5.99.7(webpack-cli@6.0.1)
+ webpack: 5.99.8(webpack-cli@6.0.1)
http-errors@2.0.0:
dependencies:
@@ -5859,7 +5856,7 @@ snapshots:
ignore@5.3.2: {}
- immutable@5.1.1: {}
+ immutable@5.1.2: {}
import-fresh@3.3.1:
dependencies:
@@ -6019,7 +6016,7 @@ snapshots:
jest-util@29.7.0:
dependencies:
'@jest/types': 29.6.3
- '@types/node': 22.15.3
+ '@types/node': 22.15.17
chalk: 4.1.2
ci-info: 3.9.0
graceful-fs: 4.2.11
@@ -6027,13 +6024,13 @@ snapshots:
jest-worker@27.5.1:
dependencies:
- '@types/node': 22.15.3
+ '@types/node': 22.15.17
merge-stream: 2.0.0
supports-color: 8.1.1
jest-worker@29.7.0:
dependencies:
- '@types/node': 22.15.3
+ '@types/node': 22.15.17
jest-util: 29.7.0
merge-stream: 2.0.0
supports-color: 8.1.1
@@ -6083,14 +6080,14 @@ snapshots:
lines-and-columns@1.2.4: {}
- lint-staged@15.5.1:
+ lint-staged@15.5.2:
dependencies:
chalk: 5.4.1
commander: 13.1.0
debug: 4.4.0
execa: 8.0.1
lilconfig: 3.1.3
- listr2: 8.3.2
+ listr2: 8.3.3
micromatch: 4.0.8
pidtree: 0.6.0
string-argv: 0.3.2
@@ -6098,7 +6095,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- listr2@8.3.2:
+ listr2@8.3.3:
dependencies:
cli-truncate: 4.0.0
colorette: 2.0.20
@@ -6182,11 +6179,11 @@ snapshots:
mimic-function@5.0.1: {}
- mini-css-extract-plugin@2.9.2(webpack@5.99.7):
+ mini-css-extract-plugin@2.9.2(webpack@5.99.8):
dependencies:
schema-utils: 4.3.2
tapable: 2.2.1
- webpack: 5.99.7(webpack-cli@6.0.1)
+ webpack: 5.99.8(webpack-cli@6.0.1)
minimatch@3.1.2:
dependencies:
@@ -6396,7 +6393,7 @@ snapshots:
postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-colormin@7.0.2(postcss@8.5.3):
+ postcss-colormin@7.0.3(postcss@8.5.3):
dependencies:
browserslist: 4.24.5
caniuse-api: 3.0.0
@@ -6404,7 +6401,7 @@ snapshots:
postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-convert-values@7.0.4(postcss@8.5.3):
+ postcss-convert-values@7.0.5(postcss@8.5.3):
dependencies:
browserslist: 4.24.5
postcss: 8.5.3
@@ -6440,20 +6437,20 @@ snapshots:
postcss: 8.5.3
postcss-selector-parser: 7.1.0
- postcss-discard-comments@7.0.3(postcss@8.5.3):
+ postcss-discard-comments@7.0.4(postcss@8.5.3):
dependencies:
postcss: 8.5.3
- postcss-selector-parser: 6.1.2
+ postcss-selector-parser: 7.1.0
- postcss-discard-duplicates@7.0.1(postcss@8.5.3):
+ postcss-discard-duplicates@7.0.2(postcss@8.5.3):
dependencies:
postcss: 8.5.3
- postcss-discard-empty@7.0.0(postcss@8.5.3):
+ postcss-discard-empty@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
- postcss-discard-overridden@7.0.0(postcss@8.5.3):
+ postcss-discard-overridden@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
@@ -6497,14 +6494,14 @@ snapshots:
'@csstools/utilities': 2.0.0(postcss@8.5.3)
postcss: 8.5.3
- postcss-loader@8.1.1(postcss@8.5.3)(typescript@5.6.2)(webpack@5.99.7):
+ postcss-loader@8.1.1(postcss@8.5.3)(typescript@5.6.2)(webpack@5.99.8):
dependencies:
cosmiconfig: 9.0.0(typescript@5.6.2)
jiti: 1.21.7
postcss: 8.5.3
semver: 7.7.1
optionalDependencies:
- webpack: 5.99.7(webpack-cli@6.0.1)
+ webpack: 5.99.8(webpack-cli@6.0.1)
transitivePeerDependencies:
- typescript
@@ -6513,44 +6510,44 @@ snapshots:
postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-merge-longhand@7.0.4(postcss@8.5.3):
+ postcss-merge-longhand@7.0.5(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
- stylehacks: 7.0.4(postcss@8.5.3)
+ stylehacks: 7.0.5(postcss@8.5.3)
- postcss-merge-rules@7.0.4(postcss@8.5.3):
+ postcss-merge-rules@7.0.5(postcss@8.5.3):
dependencies:
browserslist: 4.24.5
caniuse-api: 3.0.0
- cssnano-utils: 5.0.0(postcss@8.5.3)
+ cssnano-utils: 5.0.1(postcss@8.5.3)
postcss: 8.5.3
- postcss-selector-parser: 6.1.2
+ postcss-selector-parser: 7.1.0
- postcss-minify-font-values@7.0.0(postcss@8.5.3):
+ postcss-minify-font-values@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-minify-gradients@7.0.0(postcss@8.5.3):
+ postcss-minify-gradients@7.0.1(postcss@8.5.3):
dependencies:
colord: 2.9.3
- cssnano-utils: 5.0.0(postcss@8.5.3)
+ cssnano-utils: 5.0.1(postcss@8.5.3)
postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-minify-params@7.0.2(postcss@8.5.3):
+ postcss-minify-params@7.0.3(postcss@8.5.3):
dependencies:
browserslist: 4.24.5
- cssnano-utils: 5.0.0(postcss@8.5.3)
+ cssnano-utils: 5.0.1(postcss@8.5.3)
postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-minify-selectors@7.0.4(postcss@8.5.3):
+ postcss-minify-selectors@7.0.5(postcss@8.5.3):
dependencies:
cssesc: 3.0.0
postcss: 8.5.3
- postcss-selector-parser: 6.1.2
+ postcss-selector-parser: 7.1.0
postcss-modules-extract-imports@3.1.0(postcss@8.5.3):
dependencies:
@@ -6580,47 +6577,47 @@ snapshots:
postcss: 8.5.3
postcss-selector-parser: 7.1.0
- postcss-normalize-charset@7.0.0(postcss@8.5.3):
+ postcss-normalize-charset@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
- postcss-normalize-display-values@7.0.0(postcss@8.5.3):
+ postcss-normalize-display-values@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-normalize-positions@7.0.0(postcss@8.5.3):
+ postcss-normalize-positions@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-normalize-repeat-style@7.0.0(postcss@8.5.3):
+ postcss-normalize-repeat-style@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-normalize-string@7.0.0(postcss@8.5.3):
+ postcss-normalize-string@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-normalize-timing-functions@7.0.0(postcss@8.5.3):
+ postcss-normalize-timing-functions@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-normalize-unicode@7.0.2(postcss@8.5.3):
+ postcss-normalize-unicode@7.0.3(postcss@8.5.3):
dependencies:
browserslist: 4.24.5
postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-normalize-url@7.0.0(postcss@8.5.3):
+ postcss-normalize-url@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
- postcss-normalize-whitespace@7.0.0(postcss@8.5.3):
+ postcss-normalize-whitespace@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
@@ -6629,9 +6626,9 @@ snapshots:
dependencies:
postcss: 8.5.3
- postcss-ordered-values@7.0.1(postcss@8.5.3):
+ postcss-ordered-values@7.0.2(postcss@8.5.3):
dependencies:
- cssnano-utils: 5.0.0(postcss@8.5.3)
+ cssnano-utils: 5.0.1(postcss@8.5.3)
postcss: 8.5.3
postcss-value-parser: 4.2.0
@@ -6721,13 +6718,13 @@ snapshots:
postcss: 8.5.3
postcss-selector-parser: 7.1.0
- postcss-reduce-initial@7.0.2(postcss@8.5.3):
+ postcss-reduce-initial@7.0.3(postcss@8.5.3):
dependencies:
browserslist: 4.24.5
caniuse-api: 3.0.0
postcss: 8.5.3
- postcss-reduce-transforms@7.0.0(postcss@8.5.3):
+ postcss-reduce-transforms@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
@@ -6741,26 +6738,21 @@ snapshots:
postcss: 8.5.3
postcss-selector-parser: 7.1.0
- postcss-selector-parser@6.1.2:
- dependencies:
- cssesc: 3.0.0
- util-deprecate: 1.0.2
-
postcss-selector-parser@7.1.0:
dependencies:
cssesc: 3.0.0
util-deprecate: 1.0.2
- postcss-svgo@7.0.1(postcss@8.5.3):
+ postcss-svgo@7.0.2(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
svgo: 3.3.2
- postcss-unique-selectors@7.0.3(postcss@8.5.3):
+ postcss-unique-selectors@7.0.4(postcss@8.5.3):
dependencies:
postcss: 8.5.3
- postcss-selector-parser: 6.1.2
+ postcss-selector-parser: 7.1.0
postcss-value-parser@4.2.0: {}
@@ -6903,17 +6895,17 @@ snapshots:
safer-buffer@2.1.2: {}
- sass-loader@16.0.5(sass@1.87.0)(webpack@5.99.7):
+ sass-loader@16.0.5(sass@1.87.0)(webpack@5.99.8):
dependencies:
neo-async: 2.6.2
optionalDependencies:
sass: 1.87.0
- webpack: 5.99.7(webpack-cli@6.0.1)
+ webpack: 5.99.8(webpack-cli@6.0.1)
sass@1.87.0:
dependencies:
chokidar: 4.0.3
- immutable: 5.1.1
+ immutable: 5.1.2
source-map-js: 1.2.1
optionalDependencies:
'@parcel/watcher': 2.5.1
@@ -7090,11 +7082,11 @@ snapshots:
strip-json-comments@3.1.1: {}
- stylehacks@7.0.4(postcss@8.5.3):
+ stylehacks@7.0.5(postcss@8.5.3):
dependencies:
browserslist: 4.24.5
postcss: 8.5.3
- postcss-selector-parser: 6.1.2
+ postcss-selector-parser: 7.1.0
supports-color@7.2.0:
dependencies:
@@ -7118,14 +7110,14 @@ snapshots:
tapable@2.2.1: {}
- terser-webpack-plugin@5.3.14(webpack@5.99.7):
+ terser-webpack-plugin@5.3.14(webpack@5.99.8):
dependencies:
'@jridgewell/trace-mapping': 0.3.25
jest-worker: 27.5.1
schema-utils: 4.3.2
serialize-javascript: 6.0.2
terser: 5.39.0
- webpack: 5.99.7(webpack-cli@6.0.1)
+ webpack: 5.99.8(webpack-cli@6.0.1)
terser@5.39.0:
dependencies:
@@ -7243,12 +7235,12 @@ snapshots:
glob-to-regexp: 0.4.1
graceful-fs: 4.2.11
- webpack-cli@6.0.1(webpack@5.99.7):
+ webpack-cli@6.0.1(webpack@5.99.8):
dependencies:
'@discoveryjs/json-ext': 0.6.3
- '@webpack-cli/configtest': 3.0.1(webpack-cli@6.0.1)(webpack@5.99.7)
- '@webpack-cli/info': 3.0.1(webpack-cli@6.0.1)(webpack@5.99.7)
- '@webpack-cli/serve': 3.0.1(webpack-cli@6.0.1)(webpack@5.99.7)
+ '@webpack-cli/configtest': 3.0.1(webpack-cli@6.0.1)(webpack@5.99.8)
+ '@webpack-cli/info': 3.0.1(webpack-cli@6.0.1)(webpack@5.99.8)
+ '@webpack-cli/serve': 3.0.1(webpack-cli@6.0.1)(webpack@5.99.8)
colorette: 2.0.20
commander: 12.1.0
cross-spawn: 7.0.6
@@ -7257,7 +7249,7 @@ snapshots:
import-local: 3.2.0
interpret: 3.1.1
rechoir: 0.8.0
- webpack: 5.99.7(webpack-cli@6.0.1)
+ webpack: 5.99.8(webpack-cli@6.0.1)
webpack-merge: 6.0.1
webpack-merge@6.0.1:
@@ -7268,7 +7260,7 @@ snapshots:
webpack-sources@3.2.3: {}
- webpack@5.99.7(webpack-cli@6.0.1):
+ webpack@5.99.8(webpack-cli@6.0.1):
dependencies:
'@types/eslint-scope': 3.7.7
'@types/estree': 1.0.7
@@ -7291,11 +7283,11 @@ snapshots:
neo-async: 2.6.2
schema-utils: 4.3.2
tapable: 2.2.1
- terser-webpack-plugin: 5.3.14(webpack@5.99.7)
+ terser-webpack-plugin: 5.3.14(webpack@5.99.8)
watchpack: 2.4.2
webpack-sources: 3.2.3
optionalDependencies:
- webpack-cli: 6.0.1(webpack@5.99.7)
+ webpack-cli: 6.0.1(webpack@5.99.8)
transitivePeerDependencies:
- '@swc/core'
- esbuild
@@ -7364,8 +7356,8 @@ snapshots:
yocto-queue@0.1.0: {}
- zod-to-json-schema@3.24.5(zod@3.24.3):
+ zod-to-json-schema@3.24.5(zod@3.24.4):
dependencies:
- zod: 3.24.3
+ zod: 3.24.4
- zod@3.24.3: {}
+ zod@3.24.4: {}
diff --git a/poetry.lock b/poetry.lock
index 47dbebce..e82df588 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand.
+# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand.
[[package]]
name = "assertpy"
@@ -1160,14 +1160,14 @@ xmp = ["defusedxml"]
[[package]]
name = "platformdirs"
-version = "4.3.7"
+version = "4.3.8"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
- {file = "platformdirs-4.3.7-py3-none-any.whl", hash = "sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94"},
- {file = "platformdirs-4.3.7.tar.gz", hash = "sha256:eb437d586b6a0986388f0d6f74aa0cde27b48d0e3d66843640bfb6bdcdb6e351"},
+ {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"},
+ {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"},
]
[package.extras]
@@ -1528,30 +1528,30 @@ yaml = ["pyyaml (>=6.0.1)"]
[[package]]
name = "ruff"
-version = "0.11.8"
+version = "0.11.9"
description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false
python-versions = ">=3.7"
groups = ["dev"]
files = [
- {file = "ruff-0.11.8-py3-none-linux_armv6l.whl", hash = "sha256:896a37516c594805e34020c4a7546c8f8a234b679a7716a3f08197f38913e1a3"},
- {file = "ruff-0.11.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ab86d22d3d721a40dd3ecbb5e86ab03b2e053bc93c700dc68d1c3346b36ce835"},
- {file = "ruff-0.11.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:258f3585057508d317610e8a412788cf726efeefa2fec4dba4001d9e6f90d46c"},
- {file = "ruff-0.11.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:727d01702f7c30baed3fc3a34901a640001a2828c793525043c29f7614994a8c"},
- {file = "ruff-0.11.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3dca977cc4fc8f66e89900fa415ffe4dbc2e969da9d7a54bfca81a128c5ac219"},
- {file = "ruff-0.11.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c657fa987d60b104d2be8b052d66da0a2a88f9bd1d66b2254333e84ea2720c7f"},
- {file = "ruff-0.11.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f2e74b021d0de5eceb8bd32919f6ff8a9b40ee62ed97becd44993ae5b9949474"},
- {file = "ruff-0.11.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f9b5ef39820abc0f2c62111f7045009e46b275f5b99d5e59dda113c39b7f4f38"},
- {file = "ruff-0.11.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1dba3135ca503727aa4648152c0fa67c3b1385d3dc81c75cd8a229c4b2a1458"},
- {file = "ruff-0.11.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f024d32e62faad0f76b2d6afd141b8c171515e4fb91ce9fd6464335c81244e5"},
- {file = "ruff-0.11.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d365618d3ad747432e1ae50d61775b78c055fee5936d77fb4d92c6f559741948"},
- {file = "ruff-0.11.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:4d9aaa91035bdf612c8ee7266153bcf16005c7c7e2f5878406911c92a31633cb"},
- {file = "ruff-0.11.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:0eba551324733efc76116d9f3a0d52946bc2751f0cd30661564117d6fd60897c"},
- {file = "ruff-0.11.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:161eb4cff5cfefdb6c9b8b3671d09f7def2f960cee33481dd898caf2bcd02304"},
- {file = "ruff-0.11.8-py3-none-win32.whl", hash = "sha256:5b18caa297a786465cc511d7f8be19226acf9c0a1127e06e736cd4e1878c3ea2"},
- {file = "ruff-0.11.8-py3-none-win_amd64.whl", hash = "sha256:6e70d11043bef637c5617297bdedec9632af15d53ac1e1ba29c448da9341b0c4"},
- {file = "ruff-0.11.8-py3-none-win_arm64.whl", hash = "sha256:304432e4c4a792e3da85b7699feb3426a0908ab98bf29df22a31b0cdd098fac2"},
- {file = "ruff-0.11.8.tar.gz", hash = "sha256:6d742d10626f9004b781f4558154bb226620a7242080e11caeffab1a40e99df8"},
+ {file = "ruff-0.11.9-py3-none-linux_armv6l.whl", hash = "sha256:a31a1d143a5e6f499d1fb480f8e1e780b4dfdd580f86e05e87b835d22c5c6f8c"},
+ {file = "ruff-0.11.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:66bc18ca783b97186a1f3100e91e492615767ae0a3be584e1266aa9051990722"},
+ {file = "ruff-0.11.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:bd576cd06962825de8aece49f28707662ada6a1ff2db848d1348e12c580acbf1"},
+ {file = "ruff-0.11.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b1d18b4be8182cc6fddf859ce432cc9631556e9f371ada52f3eaefc10d878de"},
+ {file = "ruff-0.11.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0f3f46f759ac623e94824b1e5a687a0df5cd7f5b00718ff9c24f0a894a683be7"},
+ {file = "ruff-0.11.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f34847eea11932d97b521450cf3e1d17863cfa5a94f21a056b93fb86f3f3dba2"},
+ {file = "ruff-0.11.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f33b15e00435773df97cddcd263578aa83af996b913721d86f47f4e0ee0ff271"},
+ {file = "ruff-0.11.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7b27613a683b086f2aca8996f63cb3dd7bc49e6eccf590563221f7b43ded3f65"},
+ {file = "ruff-0.11.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e0d88756e63e8302e630cee3ce2ffb77859797cc84a830a24473939e6da3ca6"},
+ {file = "ruff-0.11.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:537c82c9829d7811e3aa680205f94c81a2958a122ac391c0eb60336ace741a70"},
+ {file = "ruff-0.11.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:440ac6a7029f3dee7d46ab7de6f54b19e34c2b090bb4f2480d0a2d635228f381"},
+ {file = "ruff-0.11.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:71c539bac63d0788a30227ed4d43b81353c89437d355fdc52e0cda4ce5651787"},
+ {file = "ruff-0.11.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c67117bc82457e4501473c5f5217d49d9222a360794bfb63968e09e70f340abd"},
+ {file = "ruff-0.11.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e4b78454f97aa454586e8a5557facb40d683e74246c97372af3c2d76901d697b"},
+ {file = "ruff-0.11.9-py3-none-win32.whl", hash = "sha256:7fe1bc950e7d7b42caaee2a8a3bc27410547cc032c9558ee2e0f6d3b209e845a"},
+ {file = "ruff-0.11.9-py3-none-win_amd64.whl", hash = "sha256:52edaa4a6d70f8180343a5b7f030c7edd36ad180c9f4d224959c2d689962d964"},
+ {file = "ruff-0.11.9-py3-none-win_arm64.whl", hash = "sha256:bcf42689c22f2e240f496d0c183ef2c6f7b35e809f12c1db58f75d9aa8d630ca"},
+ {file = "ruff-0.11.9.tar.gz", hash = "sha256:ebd58d4f67a00afb3a30bf7d383e52d0e036e6195143c6db7019604a05335517"},
]
[[package]]
@@ -1571,58 +1571,58 @@ timezone = ["pytz"]
[[package]]
name = "scipy"
-version = "1.15.2"
+version = "1.15.3"
description = "Fundamental algorithms for scientific computing in Python"
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
- {file = "scipy-1.15.2-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:a2ec871edaa863e8213ea5df811cd600734f6400b4af272e1c011e69401218e9"},
- {file = "scipy-1.15.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:6f223753c6ea76983af380787611ae1291e3ceb23917393079dcc746ba60cfb5"},
- {file = "scipy-1.15.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:ecf797d2d798cf7c838c6d98321061eb3e72a74710e6c40540f0e8087e3b499e"},
- {file = "scipy-1.15.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:9b18aa747da280664642997e65aab1dd19d0c3d17068a04b3fe34e2559196cb9"},
- {file = "scipy-1.15.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87994da02e73549dfecaed9e09a4f9d58a045a053865679aeb8d6d43747d4df3"},
- {file = "scipy-1.15.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69ea6e56d00977f355c0f84eba69877b6df084516c602d93a33812aa04d90a3d"},
- {file = "scipy-1.15.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:888307125ea0c4466287191e5606a2c910963405ce9671448ff9c81c53f85f58"},
- {file = "scipy-1.15.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9412f5e408b397ff5641080ed1e798623dbe1ec0d78e72c9eca8992976fa65aa"},
- {file = "scipy-1.15.2-cp310-cp310-win_amd64.whl", hash = "sha256:b5e025e903b4f166ea03b109bb241355b9c42c279ea694d8864d033727205e65"},
- {file = "scipy-1.15.2-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:92233b2df6938147be6fa8824b8136f29a18f016ecde986666be5f4d686a91a4"},
- {file = "scipy-1.15.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:62ca1ff3eb513e09ed17a5736929429189adf16d2d740f44e53270cc800ecff1"},
- {file = "scipy-1.15.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:4c6676490ad76d1c2894d77f976144b41bd1a4052107902238047fb6a473e971"},
- {file = "scipy-1.15.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:a8bf5cb4a25046ac61d38f8d3c3426ec11ebc350246a4642f2f315fe95bda655"},
- {file = "scipy-1.15.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a8e34cf4c188b6dd004654f88586d78f95639e48a25dfae9c5e34a6dc34547e"},
- {file = "scipy-1.15.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28a0d2c2075946346e4408b211240764759e0fabaeb08d871639b5f3b1aca8a0"},
- {file = "scipy-1.15.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:42dabaaa798e987c425ed76062794e93a243be8f0f20fff6e7a89f4d61cb3d40"},
- {file = "scipy-1.15.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6f5e296ec63c5da6ba6fa0343ea73fd51b8b3e1a300b0a8cae3ed4b1122c7462"},
- {file = "scipy-1.15.2-cp311-cp311-win_amd64.whl", hash = "sha256:597a0c7008b21c035831c39927406c6181bcf8f60a73f36219b69d010aa04737"},
- {file = "scipy-1.15.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c4697a10da8f8765bb7c83e24a470da5797e37041edfd77fd95ba3811a47c4fd"},
- {file = "scipy-1.15.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:869269b767d5ee7ea6991ed7e22b3ca1f22de73ab9a49c44bad338b725603301"},
- {file = "scipy-1.15.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:bad78d580270a4d32470563ea86c6590b465cb98f83d760ff5b0990cb5518a93"},
- {file = "scipy-1.15.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:b09ae80010f52efddb15551025f9016c910296cf70adbf03ce2a8704f3a5ad20"},
- {file = "scipy-1.15.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a6fd6eac1ce74a9f77a7fc724080d507c5812d61e72bd5e4c489b042455865e"},
- {file = "scipy-1.15.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b871df1fe1a3ba85d90e22742b93584f8d2b8e6124f8372ab15c71b73e428b8"},
- {file = "scipy-1.15.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:03205d57a28e18dfd39f0377d5002725bf1f19a46f444108c29bdb246b6c8a11"},
- {file = "scipy-1.15.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:601881dfb761311045b03114c5fe718a12634e5608c3b403737ae463c9885d53"},
- {file = "scipy-1.15.2-cp312-cp312-win_amd64.whl", hash = "sha256:e7c68b6a43259ba0aab737237876e5c2c549a031ddb7abc28c7b47f22e202ded"},
- {file = "scipy-1.15.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01edfac9f0798ad6b46d9c4c9ca0e0ad23dbf0b1eb70e96adb9fa7f525eff0bf"},
- {file = "scipy-1.15.2-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:08b57a9336b8e79b305a143c3655cc5bdbe6d5ece3378578888d2afbb51c4e37"},
- {file = "scipy-1.15.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:54c462098484e7466362a9f1672d20888f724911a74c22ae35b61f9c5919183d"},
- {file = "scipy-1.15.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:cf72ff559a53a6a6d77bd8eefd12a17995ffa44ad86c77a5df96f533d4e6c6bb"},
- {file = "scipy-1.15.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9de9d1416b3d9e7df9923ab23cd2fe714244af10b763975bea9e4f2e81cebd27"},
- {file = "scipy-1.15.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb530e4794fc8ea76a4a21ccb67dea33e5e0e60f07fc38a49e821e1eae3b71a0"},
- {file = "scipy-1.15.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5ea7ed46d437fc52350b028b1d44e002646e28f3e8ddc714011aaf87330f2f32"},
- {file = "scipy-1.15.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:11e7ad32cf184b74380f43d3c0a706f49358b904fa7d5345f16ddf993609184d"},
- {file = "scipy-1.15.2-cp313-cp313-win_amd64.whl", hash = "sha256:a5080a79dfb9b78b768cebf3c9dcbc7b665c5875793569f48bf0e2b1d7f68f6f"},
- {file = "scipy-1.15.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:447ce30cee6a9d5d1379087c9e474628dab3db4a67484be1b7dc3196bfb2fac9"},
- {file = "scipy-1.15.2-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:c90ebe8aaa4397eaefa8455a8182b164a6cc1d59ad53f79943f266d99f68687f"},
- {file = "scipy-1.15.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:def751dd08243934c884a3221156d63e15234a3155cf25978b0a668409d45eb6"},
- {file = "scipy-1.15.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:302093e7dfb120e55515936cb55618ee0b895f8bcaf18ff81eca086c17bd80af"},
- {file = "scipy-1.15.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7cd5b77413e1855351cdde594eca99c1f4a588c2d63711388b6a1f1c01f62274"},
- {file = "scipy-1.15.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d0194c37037707b2afa7a2f2a924cf7bac3dc292d51b6a925e5fcb89bc5c776"},
- {file = "scipy-1.15.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:bae43364d600fdc3ac327db99659dcb79e6e7ecd279a75fe1266669d9a652828"},
- {file = "scipy-1.15.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f031846580d9acccd0044efd1a90e6f4df3a6e12b4b6bd694a7bc03a89892b28"},
- {file = "scipy-1.15.2-cp313-cp313t-win_amd64.whl", hash = "sha256:fe8a9eb875d430d81755472c5ba75e84acc980e4a8f6204d402849234d3017db"},
- {file = "scipy-1.15.2.tar.gz", hash = "sha256:cd58a314d92838f7e6f755c8a2167ead4f27e1fd5c1251fd54289569ef3495ec"},
+ {file = "scipy-1.15.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:a345928c86d535060c9c2b25e71e87c39ab2f22fc96e9636bd74d1dbf9de448c"},
+ {file = "scipy-1.15.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:ad3432cb0f9ed87477a8d97f03b763fd1d57709f1bbde3c9369b1dff5503b253"},
+ {file = "scipy-1.15.3-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:aef683a9ae6eb00728a542b796f52a5477b78252edede72b8327a886ab63293f"},
+ {file = "scipy-1.15.3-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:1c832e1bd78dea67d5c16f786681b28dd695a8cb1fb90af2e27580d3d0967e92"},
+ {file = "scipy-1.15.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:263961f658ce2165bbd7b99fa5135195c3a12d9bef045345016b8b50c315cb82"},
+ {file = "scipy-1.15.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e2abc762b0811e09a0d3258abee2d98e0c703eee49464ce0069590846f31d40"},
+ {file = "scipy-1.15.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ed7284b21a7a0c8f1b6e5977ac05396c0d008b89e05498c8b7e8f4a1423bba0e"},
+ {file = "scipy-1.15.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5380741e53df2c566f4d234b100a484b420af85deb39ea35a1cc1be84ff53a5c"},
+ {file = "scipy-1.15.3-cp310-cp310-win_amd64.whl", hash = "sha256:9d61e97b186a57350f6d6fd72640f9e99d5a4a2b8fbf4b9ee9a841eab327dc13"},
+ {file = "scipy-1.15.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:993439ce220d25e3696d1b23b233dd010169b62f6456488567e830654ee37a6b"},
+ {file = "scipy-1.15.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:34716e281f181a02341ddeaad584205bd2fd3c242063bd3423d61ac259ca7eba"},
+ {file = "scipy-1.15.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3b0334816afb8b91dab859281b1b9786934392aa3d527cd847e41bb6f45bee65"},
+ {file = "scipy-1.15.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:6db907c7368e3092e24919b5e31c76998b0ce1684d51a90943cb0ed1b4ffd6c1"},
+ {file = "scipy-1.15.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:721d6b4ef5dc82ca8968c25b111e307083d7ca9091bc38163fb89243e85e3889"},
+ {file = "scipy-1.15.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39cb9c62e471b1bb3750066ecc3a3f3052b37751c7c3dfd0fd7e48900ed52982"},
+ {file = "scipy-1.15.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:795c46999bae845966368a3c013e0e00947932d68e235702b5c3f6ea799aa8c9"},
+ {file = "scipy-1.15.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:18aaacb735ab38b38db42cb01f6b92a2d0d4b6aabefeb07f02849e47f8fb3594"},
+ {file = "scipy-1.15.3-cp311-cp311-win_amd64.whl", hash = "sha256:ae48a786a28412d744c62fd7816a4118ef97e5be0bee968ce8f0a2fba7acf3bb"},
+ {file = "scipy-1.15.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6ac6310fdbfb7aa6612408bd2f07295bcbd3fda00d2d702178434751fe48e019"},
+ {file = "scipy-1.15.3-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:185cd3d6d05ca4b44a8f1595af87f9c372bb6acf9c808e99aa3e9aa03bd98cf6"},
+ {file = "scipy-1.15.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:05dc6abcd105e1a29f95eada46d4a3f251743cfd7d3ae8ddb4088047f24ea477"},
+ {file = "scipy-1.15.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:06efcba926324df1696931a57a176c80848ccd67ce6ad020c810736bfd58eb1c"},
+ {file = "scipy-1.15.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c05045d8b9bfd807ee1b9f38761993297b10b245f012b11b13b91ba8945f7e45"},
+ {file = "scipy-1.15.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271e3713e645149ea5ea3e97b57fdab61ce61333f97cfae392c28ba786f9bb49"},
+ {file = "scipy-1.15.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6cfd56fc1a8e53f6e89ba3a7a7251f7396412d655bca2aa5611c8ec9a6784a1e"},
+ {file = "scipy-1.15.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0ff17c0bb1cb32952c09217d8d1eed9b53d1463e5f1dd6052c7857f83127d539"},
+ {file = "scipy-1.15.3-cp312-cp312-win_amd64.whl", hash = "sha256:52092bc0472cfd17df49ff17e70624345efece4e1a12b23783a1ac59a1b728ed"},
+ {file = "scipy-1.15.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c620736bcc334782e24d173c0fdbb7590a0a436d2fdf39310a8902505008759"},
+ {file = "scipy-1.15.3-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:7e11270a000969409d37ed399585ee530b9ef6aa99d50c019de4cb01e8e54e62"},
+ {file = "scipy-1.15.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8c9ed3ba2c8a2ce098163a9bdb26f891746d02136995df25227a20e71c396ebb"},
+ {file = "scipy-1.15.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:0bdd905264c0c9cfa74a4772cdb2070171790381a5c4d312c973382fc6eaf730"},
+ {file = "scipy-1.15.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79167bba085c31f38603e11a267d862957cbb3ce018d8b38f79ac043bc92d825"},
+ {file = "scipy-1.15.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9deabd6d547aee2c9a81dee6cc96c6d7e9a9b1953f74850c179f91fdc729cb7"},
+ {file = "scipy-1.15.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dde4fc32993071ac0c7dd2d82569e544f0bdaff66269cb475e0f369adad13f11"},
+ {file = "scipy-1.15.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f77f853d584e72e874d87357ad70f44b437331507d1c311457bed8ed2b956126"},
+ {file = "scipy-1.15.3-cp313-cp313-win_amd64.whl", hash = "sha256:b90ab29d0c37ec9bf55424c064312930ca5f4bde15ee8619ee44e69319aab163"},
+ {file = "scipy-1.15.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3ac07623267feb3ae308487c260ac684b32ea35fd81e12845039952f558047b8"},
+ {file = "scipy-1.15.3-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:6487aa99c2a3d509a5227d9a5e889ff05830a06b2ce08ec30df6d79db5fcd5c5"},
+ {file = "scipy-1.15.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:50f9e62461c95d933d5c5ef4a1f2ebf9a2b4e83b0db374cb3f1de104d935922e"},
+ {file = "scipy-1.15.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:14ed70039d182f411ffc74789a16df3835e05dc469b898233a245cdfd7f162cb"},
+ {file = "scipy-1.15.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a769105537aa07a69468a0eefcd121be52006db61cdd8cac8a0e68980bbb723"},
+ {file = "scipy-1.15.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db984639887e3dffb3928d118145ffe40eff2fa40cb241a306ec57c219ebbbb"},
+ {file = "scipy-1.15.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:40e54d5c7e7ebf1aa596c374c49fa3135f04648a0caabcb66c52884b943f02b4"},
+ {file = "scipy-1.15.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5e721fed53187e71d0ccf382b6bf977644c533e506c4d33c3fb24de89f5c3ed5"},
+ {file = "scipy-1.15.3-cp313-cp313t-win_amd64.whl", hash = "sha256:76ad1fb5f8752eabf0fa02e4cc0336b4e8f021e2d5f061ed37d6d264db35e3ca"},
+ {file = "scipy-1.15.3.tar.gz", hash = "sha256:eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf"},
]
[package.dependencies]
@@ -1630,7 +1630,7 @@ numpy = ">=1.23.5,<2.5"
[package.extras]
dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy (==1.10.0)", "pycodestyle", "pydevtool", "rich-click", "ruff (>=0.0.292)", "types-psutil", "typing_extensions"]
-doc = ["intersphinx_registry", "jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.16.5)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<8.0.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0)"]
+doc = ["intersphinx_registry", "jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.19.1)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<8.0.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0)"]
test = ["Cython", "array-api-strict (>=2.0,<2.1.1)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja ; sys_platform != \"emscripten\"", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"]
[[package]]
diff --git a/test/namer_configparser_test.py b/test/namer_configparser_test.py
index be458a89..3bfdf0b3 100644
--- a/test/namer_configparser_test.py
+++ b/test/namer_configparser_test.py
@@ -5,8 +5,12 @@
from configupdater import ConfigUpdater
import unittest
from importlib import resources
+
+from loguru import logger
+
from namer.configuration import NamerConfig
from namer.configuration_utils import from_config, to_ini
+from test import utils
class UnitTestAsTheDefaultExecution(unittest.TestCase):
@@ -14,6 +18,12 @@ class UnitTestAsTheDefaultExecution(unittest.TestCase):
Always test first.
"""
+ def __init__(self, method_name='runTest'):
+ super().__init__(method_name)
+
+ if not utils.is_debugging():
+ logger.remove()
+
def test_configuration(self) -> None:
updater = ConfigUpdater(allow_no_value=True)
config_str = ''
@@ -44,6 +54,3 @@ def test_configuration(self) -> None:
updated.read_string(files_no_sites_with_no_date_info)
double_read = from_config(updated, double_read)
self.assertIn('badsite', double_read.sites_with_no_date_info)
-
- print(namer_config)
- print(to_ini(namer_config))
diff --git a/test/namer_ffmpeg_test.py b/test/namer_ffmpeg_test.py
index 0e28ac13..fc562c26 100644
--- a/test/namer_ffmpeg_test.py
+++ b/test/namer_ffmpeg_test.py
@@ -7,22 +7,30 @@
import unittest
from pathlib import Path
+from loguru import logger
+
from namer.ffmpeg import FFMpeg
+from test import utils
class UnitTestAsTheDefaultExecution(unittest.TestCase):
"""
Always test first.
"""
+ def __init__(self, method_name='runTest'):
+ super().__init__(method_name)
+
+ if not utils.is_debugging():
+ logger.remove()
def test_get_resolution(self):
"""
Verifies we can resolutions from mp4 files.
"""
with tempfile.TemporaryDirectory(prefix='test') as tmpdir:
- tempdir = Path(tmpdir)
- shutil.copytree(Path(__file__).resolve().parent, tempdir / 'test')
- file = tempdir / 'test' / 'Site.22.01.01.painful.pun.XXX.720p.xpost.mp4'
+ temp_dir = Path(tmpdir)
+ shutil.copytree(Path(__file__).resolve().parent, temp_dir / 'test')
+ file = temp_dir / 'test' / 'Site.22.01.01.painful.pun.XXX.720p.xpost.mp4'
results = FFMpeg().ffprobe(file)
self.assertIsNotNone(results)
if results:
@@ -34,9 +42,9 @@ def test_get_audio_stream(self):
Verifies we can get audio stream language names from files.
"""
with tempfile.TemporaryDirectory(prefix='test') as tmpdir:
- tempdir = Path(tmpdir)
- shutil.copytree(Path(__file__).resolve().parent, tempdir / 'test')
- file = tempdir / 'test' / 'Site.22.01.01.painful.pun.XXX.720p.xpost.mp4'
+ temp_dir = Path(tmpdir)
+ shutil.copytree(Path(__file__).resolve().parent, temp_dir / 'test')
+ file = temp_dir / 'test' / 'Site.22.01.01.painful.pun.XXX.720p.xpost.mp4'
stream_number = FFMpeg().get_audio_stream_for_lang(file, 'und')
self.assertEqual(stream_number, -1)
stream_number = FFMpeg().get_audio_stream_for_lang(file, 'eng')
@@ -47,9 +55,9 @@ def test_ffprobe(self) -> None:
read stream info.
"""
with tempfile.TemporaryDirectory(prefix='test') as tmpdir:
- tempdir = Path(tmpdir)
- shutil.copytree(Path(__file__).resolve().parent, tempdir / 'test')
- file = tempdir / 'test' / 'Site.22.01.01.painful.pun.XXX.720p.xpost_wrong.mp4'
+ temp_dir = Path(tmpdir)
+ shutil.copytree(Path(__file__).resolve().parent, temp_dir / 'test')
+ file = temp_dir / 'test' / 'Site.22.01.01.painful.pun.XXX.720p.xpost_wrong.mp4'
results = FFMpeg().ffprobe(file)
self.assertIsNotNone(results)
if results:
@@ -76,9 +84,9 @@ def test_update_audio_stream(self):
Verifies we can change default audio stream languages for mp4's.
"""
with tempfile.TemporaryDirectory(prefix='test') as tmpdir:
- tempdir = Path(tmpdir)
- shutil.copytree(Path(__file__).resolve().parent, tempdir / 'test')
- file = tempdir / 'test' / 'Site.22.01.01.painful.pun.XXX.720p.xpost_wrong.mp4'
+ temp_dir = Path(tmpdir)
+ shutil.copytree(Path(__file__).resolve().parent, temp_dir / 'test')
+ file = temp_dir / 'test' / 'Site.22.01.01.painful.pun.XXX.720p.xpost_wrong.mp4'
stream_number = FFMpeg().get_audio_stream_for_lang(file, 'und')
self.assertEqual(stream_number, -1)
stream_number = FFMpeg().get_audio_stream_for_lang(file, 'eng')
diff --git a/test/namer_file_parser_test.py b/test/namer_file_parser_test.py
index 82047fd4..60e74892 100644
--- a/test/namer_file_parser_test.py
+++ b/test/namer_file_parser_test.py
@@ -8,8 +8,11 @@
from pathlib import Path
from unittest.mock import patch
+from loguru import logger
+
from namer.fileinfo import parse_file_name
from namer.command import make_command
+from test import utils
from test.utils import environment, sample_config
REGEX_TOKEN = '{_site}{_sep}{_optional_date}{_ts}{_name}{_dot}{_ext}'
@@ -20,6 +23,12 @@ class UnitTestAsTheDefaultExecution(unittest.TestCase):
Always test first.
"""
+ def __init__(self, method_name='runTest'):
+ super().__init__(method_name)
+
+ if not utils.is_debugging():
+ logger.remove()
+
def test_parse_file_name(self):
"""
Test standard name parsing.
@@ -124,10 +133,10 @@ def test_parse_file(self, mock_stdout):
"""
Test the main method.
"""
- with environment() as (tmpdir, _parrot, config):
- tempdir = Path(tmpdir)
+ with environment() as (tmp_dir, _parrot, config):
+ temp_dir = Path(tmp_dir)
test_dir = Path(__file__).resolve().parent
- target_file = tempdir / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
+ target_file = temp_dir / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
shutil.copy(test_dir / 'Site.22.01.01.painful.pun.XXX.720p.xpost.mp4', target_file)
config.min_file_size = 0
command = make_command(target_file, config)
@@ -146,10 +155,10 @@ def test_parse_dir_name(self, mock_stdout):
"""
Test the main method.
"""
- with environment() as (tmpdir, _parrot, config):
- tempdir = Path(tmpdir)
+ with environment() as (tmp_dir, _parrot, config):
+ temp_dir = Path(tmp_dir)
test_dir = Path(__file__).resolve().parent
- target_file = tempdir / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.1080p.HEVC.x265.PRT[XvX]-xpost' / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
+ target_file = temp_dir / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.1080p.HEVC.x265.PRT[XvX]-xpost' / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
target_file.parent.mkdir()
shutil.copy(test_dir / 'Site.22.01.01.painful.pun.XXX.720p.xpost.mp4', target_file)
config.min_file_size = 0
diff --git a/test/namer_fileutils_test.py b/test/namer_fileutils_test.py
index db0d0f39..e1c3fffb 100644
--- a/test/namer_fileutils_test.py
+++ b/test/namer_fileutils_test.py
@@ -10,7 +10,10 @@
from platform import system
from unittest.mock import patch
+from loguru import logger
+
from namer.command import main, set_permissions
+from test import utils
from test.utils import environment, sample_config
REGEX_TOKEN = '{_site}{_sep}{_optional_date}{_ts}{_name}{_dot}{_ext}'
@@ -21,6 +24,12 @@ class UnitTestAsTheDefaultExecution(unittest.TestCase):
Always test first.
"""
+ def __init__(self, method_name='runTest'):
+ super().__init__(method_name)
+
+ if not utils.is_debugging():
+ logger.remove()
+
@patch('sys.stdout', new_callable=io.StringIO)
def test_main_method(self, mock_stdout):
"""
@@ -28,9 +37,9 @@ def test_main_method(self, mock_stdout):
"""
config = sample_config()
config.min_file_size = 0
- with environment(config) as (tempdir, _parrot, config):
+ with environment(config) as (temp_dir, _parrot, config):
test_dir = Path(__file__).resolve().parent
- target_file = tempdir / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
+ target_file = temp_dir / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
shutil.copy(test_dir / 'Site.22.01.01.painful.pun.XXX.720p.xpost.mp4', target_file)
main(arg_list=['-f', str(target_file), '-c', str(config.config_file)])
self.assertIn('site: EvilAngel', mock_stdout.getvalue())
@@ -41,8 +50,8 @@ def test_set_permission(self):
"""
if system() != 'Windows':
with tempfile.TemporaryDirectory(prefix='test') as tmpdir:
- tempdir = Path(tmpdir)
- target_dir = tempdir / 'target_dir'
+ temp_dir = Path(tmpdir)
+ target_dir = temp_dir / 'target_dir'
target_dir.mkdir()
testfile = target_dir / 'test_file.txt'
with open(testfile, 'w', encoding='utf-8') as file:
diff --git a/test/namer_metadataapi_test.py b/test/namer_metadataapi_test.py
index 464ecb3b..b1690509 100644
--- a/test/namer_metadataapi_test.py
+++ b/test/namer_metadataapi_test.py
@@ -6,10 +6,13 @@
import unittest
from unittest import mock
+from loguru import logger
+
from namer.comparison_results import SceneType
from namer.fileinfo import parse_file_name
from namer.command import make_command
from namer.metadataapi import main, match
+from test import utils
from test.utils import environment, sample_config
@@ -18,6 +21,12 @@ class UnitTestAsTheDefaultExecution(unittest.TestCase):
Always test first.
"""
+ def __init__(self, method_name='runTest'):
+ super().__init__(method_name)
+
+ if not utils.is_debugging():
+ logger.remove()
+
def test_parse_response_metadataapi_net_dorcel(self):
"""
Test parsing a stored response as a LookedUpFileInfo
@@ -163,11 +172,11 @@ def test_call_metadataapi_net_no_data(self):
"""
verify an empty response from porndb is properly handled.
"""
- with environment() as (tempdir, _parrot, config):
+ with environment() as (temp_dir, _parrot, config):
filename: str = 'GoodAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
- with open((tempdir / filename), 'w'):
+ with open((temp_dir / filename), 'w'):
pass
- command = make_command((tempdir / filename), config)
+ command = make_command((temp_dir / filename), config)
self.assertIsNotNone(command)
if command is not None:
results = match(command.parsed_file, config)
@@ -179,11 +188,11 @@ def test_call_metadataapi_net_no_message(self):
"""
config = sample_config()
config.min_file_size = 0
- with environment() as (tempdir, _parrot, config):
+ with environment() as (temp_dir, _parrot, config):
filename: str = 'OkAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
- with open((tempdir / filename), 'w'):
+ with open((temp_dir / filename), 'w'):
pass
- command = make_command((tempdir / filename), config)
+ command = make_command((temp_dir / filename), config)
self.assertIsNotNone(command)
if command is not None:
results = match(command.parsed_file, config)
@@ -194,9 +203,9 @@ def test_main_metadataapi_net(self, mock_stdout):
"""
Test parsing a full stored response (with tags) as a LookedUpFileInfo
"""
- with environment() as (tempdir, _parrot, config):
+ with environment() as (temp_dir, _parrot, config):
filename: str = 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
- tmp_file = tempdir / filename
+ tmp_file = temp_dir / filename
with open(tmp_file, 'w'):
pass
main(['-f', str(tmp_file), '-c', str(config.config_file)])
diff --git a/test/namer_moviexml_test.py b/test/namer_moviexml_test.py
index 5ce9fb3a..2ae7c5f4 100644
--- a/test/namer_moviexml_test.py
+++ b/test/namer_moviexml_test.py
@@ -8,10 +8,13 @@
from pathlib import Path
from shutil import copytree
+from loguru import logger
+
from namer.fileinfo import parse_file_name
from namer.metadataapi import match
from namer.moviexml import parse_movie_xml_file, write_movie_xml_file
from namer.comparison_results import Performer
+from test import utils
from test.utils import environment
@@ -20,16 +23,22 @@ class UnitTestAsTheDefaultExecution(unittest.TestCase):
Always test first.
"""
+ def __init__(self, method_name='runTest'):
+ super().__init__(method_name)
+
+ if not utils.is_debugging():
+ logger.remove()
+
def test_parsing_xml_metadata(self):
"""
verify tag in place functions.
"""
with tempfile.TemporaryDirectory(prefix='test') as tmpdir:
- tempdir = Path(tmpdir)
- copytree(Path(__file__).resolve().parent, tempdir / 'test')
- xmlfile = tempdir / 'test' / 'ea.nfo'
- info = parse_movie_xml_file(xmlfile)
+ temp_dir = Path(tmpdir)
+ copytree(Path(__file__).resolve().parent, temp_dir / 'test')
+ xml_file = temp_dir / 'test' / 'ea.nfo'
+ info = parse_movie_xml_file(xml_file)
self.assertEqual(info.site, 'Evil Angel')
self.assertEqual(info.date, '2022-01-03')
self.assertIsNotNone(info.description)
@@ -47,7 +56,7 @@ def test_writing_xml_metadata_genre_flag(self):
Test parsing a stored response as a LookedUpFileInfo
"""
- with environment() as (_path, fakeTPDB, config):
+ with environment() as (_path, fake_tpdb, config):
name = parse_file_name('EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4', config)
config.enable_metadataapi_genres = True
results = match(name, config)
@@ -66,8 +75,8 @@ def test_writing_xml_metadata_genre_flag(self):
2022-01-03
XXX
- {fakeTPDB.get_url()}qWAUIAUpBsoqKUwozc4NOTR1tPI=/1000x1500/smart/filters:sharpen():upscale():watermark(https%3A%2F%2Fcdn.metadataapi.net%2Fsites%2F3f%2F9f%2F51%2Fcf3828d65425bca2890d53ef242d8cf%2Flogo%2Fevil-angel_dark%5B1%5D.png,-10,-10,25,50)/https%3A%2F%2Fcdn.metadataapi.net%2Fscene%2Ff4%2Fab%2F3e%2Fa91d31d6dee223f4f30a57bfd83b151%2Fbackground%2Fbg-evil-angel-carmela-clutch-fabulous-anal-3-way.webp
- {fakeTPDB.get_url()}gAu-1j1ZP4f6gNMPibgAyGKoa_c=/fit-in/3000x3000/smart/filters:sharpen():upscale()/https%3A%2F%2Fcdn.metadataapi.net%2Fscene%2Ff4%2Fab%2F3e%2Fa91d31d6dee223f4f30a57bfd83b151%2Fbackground%2Fbg-evil-angel-carmela-clutch-fabulous-anal-3-way.webp
+ {fake_tpdb.get_url()}qWAUIAUpBsoqKUwozc4NOTR1tPI=/1000x1500/smart/filters:sharpen():upscale():watermark(https%3A%2F%2Fcdn.metadataapi.net%2Fsites%2F3f%2F9f%2F51%2Fcf3828d65425bca2890d53ef242d8cf%2Flogo%2Fevil-angel_dark%5B1%5D.png,-10,-10,25,50)/https%3A%2F%2Fcdn.metadataapi.net%2Fscene%2Ff4%2Fab%2F3e%2Fa91d31d6dee223f4f30a57bfd83b151%2Fbackground%2Fbg-evil-angel-carmela-clutch-fabulous-anal-3-way.webp
+ {fake_tpdb.get_url()}gAu-1j1ZP4f6gNMPibgAyGKoa_c=/fit-in/3000x3000/smart/filters:sharpen():upscale()/https%3A%2F%2Fcdn.metadataapi.net%2Fscene%2Ff4%2Fab%2F3e%2Fa91d31d6dee223f4f30a57bfd83b151%2Fbackground%2Fbg-evil-angel-carmela-clutch-fabulous-anal-3-way.webp
Anal
Ass
@@ -103,7 +112,7 @@ def test_writing_xml_metadata_genre_flag(self):
Carmela Clutch
Carmela Clutch
Female
- {fakeTPDB.get_url()}flLf1pecTlKcpJCki30l5iWXNdQ=/1000x1500/smart/filters:sharpen():upscale()/https%3A%2F%2Fcdn.metadataapi.net%2Fperformer%2Fd3%2F47%2Fcd%2Fde8cbe2fd9f73dec8c985d2d69b67ac%2Fposter%2Fcarmela-clutch.webp
+ {fake_tpdb.get_url()}flLf1pecTlKcpJCki30l5iWXNdQ=/1000x1500/smart/filters:sharpen():upscale()/https%3A%2F%2Fcdn.metadataapi.net%2Fperformer%2Fd3%2F47%2Fcd%2Fde8cbe2fd9f73dec8c985d2d69b67ac%2Fposter%2Fcarmela-clutch.webp
@@ -111,7 +120,7 @@ def test_writing_xml_metadata_genre_flag(self):
Francesca Le
Francesca Le
Female
- {fakeTPDB.get_url()}r8g92zymZ6SduikMTwcXMojRxik=/1000x1500/smart/filters:sharpen():upscale()/https%3A%2F%2Fcdn.metadataapi.net%2Fperformer%2F71%2F51%2Fdc%2F4b09a05007ba30c041e474c2b398a51%2Fposter%2Ffrancesca-le.png
+ {fake_tpdb.get_url()}r8g92zymZ6SduikMTwcXMojRxik=/1000x1500/smart/filters:sharpen():upscale()/https%3A%2F%2Fcdn.metadataapi.net%2Fperformer%2F71%2F51%2Fdc%2F4b09a05007ba30c041e474c2b398a51%2Fposter%2Ffrancesca-le.png
@@ -119,7 +128,7 @@ def test_writing_xml_metadata_genre_flag(self):
Mark Wood
Mark Wood
Male
- {fakeTPDB.get_url()}V7F3bvj0YDEr3_qrKqyaJ5fKxd0=/1000x1500/smart/filters:sharpen():upscale()/https%3A%2F%2Fcdn.metadataapi.net%2Fperformer%2Fa3%2F48%2Fcd%2Ffcd5cd6cecf1f7ae3af587286e9fccf%2Fposter%2Fmark-wood.webp
+ {fake_tpdb.get_url()}V7F3bvj0YDEr3_qrKqyaJ5fKxd0=/1000x1500/smart/filters:sharpen():upscale()/https%3A%2F%2Fcdn.metadataapi.net%2Fperformer%2Fa3%2F48%2Fcd%2Ffcd5cd6cecf1f7ae3af587286e9fccf%2Fposter%2Fmark-wood.webp
@@ -131,13 +140,12 @@ def test_writing_xml_metadata(self):
"""
Test parsing a stored response as a LookedUpFileInfo
"""
- with environment() as (_path, fakeTPDB, config):
+ with environment() as (_path, fake_tpdb, config):
name = parse_file_name('EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4', config)
results = match(name, config)
self.assertEqual(len(results.results), 1)
result = results.results[0]
output = write_movie_xml_file(result.looked_up, config)
- print(output)
expected = f"""
Cute brunette Carmela Clutch positions her big, juicy ass for famed director/cocksman Mark Wood's camera to ogle. The well-endowed babe teases, flaunting her voluptuous jugs and derriere. Mark's sexy MILF partner, Francesca Le, finds a 'nice warm place' for her tongue and serves Carmela a lesbian rim job. Francesca takes a labia-licking face ride from the busty babe. Francesca takes over the camera as Mark takes over Carmela's hairy snatch, his big cock ram-fucking her twat. Carmela sucks Mark's meat in a lewd blowjob. Carmela jerks her clit as Mark delivers a vigorous anal pounding! With Mark's prick shoved up her ass, off-screen Francesca orders, 'Keep that pussy busy!' Carmela's huge boobs jiggle as she takes a rectal reaming and buzzes a vibrator on her clit at the same time. Francesca jumps in to make it a threesome, trading ass-to-mouth flavor with the young tramp. This ribald romp reaches its climax as Mark drops a messy, open-mouth cum facial onto Carmela. She lets the jizz drip from her lips, licking the mess from her fingers and rubbing it onto her robust melons.
@@ -150,8 +158,8 @@ def test_writing_xml_metadata(self):
2022-01-03
XXX
- {fakeTPDB.get_url()}qWAUIAUpBsoqKUwozc4NOTR1tPI=/1000x1500/smart/filters:sharpen():upscale():watermark(https%3A%2F%2Fcdn.metadataapi.net%2Fsites%2F3f%2F9f%2F51%2Fcf3828d65425bca2890d53ef242d8cf%2Flogo%2Fevil-angel_dark%5B1%5D.png,-10,-10,25,50)/https%3A%2F%2Fcdn.metadataapi.net%2Fscene%2Ff4%2Fab%2F3e%2Fa91d31d6dee223f4f30a57bfd83b151%2Fbackground%2Fbg-evil-angel-carmela-clutch-fabulous-anal-3-way.webp
- {fakeTPDB.get_url()}gAu-1j1ZP4f6gNMPibgAyGKoa_c=/fit-in/3000x3000/smart/filters:sharpen():upscale()/https%3A%2F%2Fcdn.metadataapi.net%2Fscene%2Ff4%2Fab%2F3e%2Fa91d31d6dee223f4f30a57bfd83b151%2Fbackground%2Fbg-evil-angel-carmela-clutch-fabulous-anal-3-way.webp
+ {fake_tpdb.get_url()}qWAUIAUpBsoqKUwozc4NOTR1tPI=/1000x1500/smart/filters:sharpen():upscale():watermark(https%3A%2F%2Fcdn.metadataapi.net%2Fsites%2F3f%2F9f%2F51%2Fcf3828d65425bca2890d53ef242d8cf%2Flogo%2Fevil-angel_dark%5B1%5D.png,-10,-10,25,50)/https%3A%2F%2Fcdn.metadataapi.net%2Fscene%2Ff4%2Fab%2F3e%2Fa91d31d6dee223f4f30a57bfd83b151%2Fbackground%2Fbg-evil-angel-carmela-clutch-fabulous-anal-3-way.webp
+ {fake_tpdb.get_url()}gAu-1j1ZP4f6gNMPibgAyGKoa_c=/fit-in/3000x3000/smart/filters:sharpen():upscale()/https%3A%2F%2Fcdn.metadataapi.net%2Fscene%2Ff4%2Fab%2F3e%2Fa91d31d6dee223f4f30a57bfd83b151%2Fbackground%2Fbg-evil-angel-carmela-clutch-fabulous-anal-3-way.webp
Anal
Ass
@@ -188,7 +196,7 @@ def test_writing_xml_metadata(self):
Carmela Clutch
Carmela Clutch
Female
- {fakeTPDB.get_url()}flLf1pecTlKcpJCki30l5iWXNdQ=/1000x1500/smart/filters:sharpen():upscale()/https%3A%2F%2Fcdn.metadataapi.net%2Fperformer%2Fd3%2F47%2Fcd%2Fde8cbe2fd9f73dec8c985d2d69b67ac%2Fposter%2Fcarmela-clutch.webp
+ {fake_tpdb.get_url()}flLf1pecTlKcpJCki30l5iWXNdQ=/1000x1500/smart/filters:sharpen():upscale()/https%3A%2F%2Fcdn.metadataapi.net%2Fperformer%2Fd3%2F47%2Fcd%2Fde8cbe2fd9f73dec8c985d2d69b67ac%2Fposter%2Fcarmela-clutch.webp
@@ -196,7 +204,7 @@ def test_writing_xml_metadata(self):
Francesca Le
Francesca Le
Female
- {fakeTPDB.get_url()}r8g92zymZ6SduikMTwcXMojRxik=/1000x1500/smart/filters:sharpen():upscale()/https%3A%2F%2Fcdn.metadataapi.net%2Fperformer%2F71%2F51%2Fdc%2F4b09a05007ba30c041e474c2b398a51%2Fposter%2Ffrancesca-le.png
+ {fake_tpdb.get_url()}r8g92zymZ6SduikMTwcXMojRxik=/1000x1500/smart/filters:sharpen():upscale()/https%3A%2F%2Fcdn.metadataapi.net%2Fperformer%2F71%2F51%2Fdc%2F4b09a05007ba30c041e474c2b398a51%2Fposter%2Ffrancesca-le.png
@@ -204,7 +212,7 @@ def test_writing_xml_metadata(self):
Mark Wood
Mark Wood
Male
- {fakeTPDB.get_url()}V7F3bvj0YDEr3_qrKqyaJ5fKxd0=/1000x1500/smart/filters:sharpen():upscale()/https%3A%2F%2Fcdn.metadataapi.net%2Fperformer%2Fa3%2F48%2Fcd%2Ffcd5cd6cecf1f7ae3af587286e9fccf%2Fposter%2Fmark-wood.webp
+ {fake_tpdb.get_url()}V7F3bvj0YDEr3_qrKqyaJ5fKxd0=/1000x1500/smart/filters:sharpen():upscale()/https%3A%2F%2Fcdn.metadataapi.net%2Fperformer%2Fa3%2F48%2Fcd%2Ffcd5cd6cecf1f7ae3af587286e9fccf%2Fposter%2Fmark-wood.webp
diff --git a/test/namer_mutagen_test.py b/test/namer_mutagen_test.py
index f7c0400e..f4152844 100644
--- a/test/namer_mutagen_test.py
+++ b/test/namer_mutagen_test.py
@@ -8,6 +8,7 @@
from pathlib import Path
import hashlib
+from loguru import logger
from mutagen.mp4 import MP4
from namer.configuration import NamerConfig
@@ -16,6 +17,7 @@
from namer.metadataapi import match
from namer.mutagen import resolution_to_hdv_setting, update_mp4_file
from namer.comparison_results import LookedUpFileInfo
+from test import utils
from test.utils import validate_mp4_tags
from test.namer_metadataapi_test import environment
@@ -25,6 +27,12 @@ class UnitTestAsTheDefaultExecution(unittest.TestCase):
Always test first.
"""
+ def __init__(self, method_name='runTest'):
+ super().__init__(method_name)
+
+ if not utils.is_debugging():
+ logger.remove()
+
def test_video_size(self):
"""
Test resolution.
@@ -40,11 +48,11 @@ def test_writing_metadata(self):
"""
verify tag in place functions.
"""
- with environment() as (tempdir, _parrot, config):
+ with environment() as (temp_dir, _parrot, config):
test_dir = Path(__file__).resolve().parent
- poster = tempdir / 'poster.png'
+ poster = temp_dir / 'poster.png'
shutil.copy(test_dir / 'poster.png', poster)
- target_file = tempdir / 'DorcelClub - 2021-12-23 - Aya.Benetti.Megane.Lopez.And.Bella.Tina.XXX.1080p.mp4'
+ target_file = temp_dir / 'DorcelClub - 2021-12-23 - Aya.Benetti.Megane.Lopez.And.Bella.Tina.XXX.1080p.mp4'
shutil.copy(test_dir / 'Site.22.01.01.painful.pun.XXX.720p.xpost.mp4', target_file)
name_parts = parse_file_name(target_file.name, config)
info = match(name_parts, config)
@@ -58,11 +66,11 @@ def test_writing_full_metadata(self):
Test writing metadata to a mp4, including tag information, which is only
available on scene requests to the porndb using uuid to request scene information.
"""
- with environment() as (tempdir, _parrot, config):
+ with environment() as (temp_dir, _parrot, config):
test_dir = Path(__file__).resolve().parent
- target_file = tempdir / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
+ target_file = temp_dir / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
shutil.copy(test_dir / 'Site.22.01.01.painful.pun.XXX.720p.xpost.mp4', target_file)
- poster = tempdir / 'poster.png'
+ poster = temp_dir / 'poster.png'
shutil.copy(test_dir / 'poster.png', poster)
name_parts = parse_file_name(target_file.name, config)
info = match(name_parts, config)
@@ -80,11 +88,11 @@ def test_sha_sum_two_identical_transformations(self):
sha_1 = None
sha_2 = None
- with environment() as (tempdir, _parrot, config):
+ with environment() as (temp_dir, _parrot, config):
test_dir = Path(__file__).resolve().parent
- target_file = tempdir / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
+ target_file = temp_dir / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
shutil.copy(test_dir / 'Site.22.01.01.painful.pun.XXX.720p.xpost.mp4', target_file)
- poster = tempdir / 'poster.png'
+ poster = temp_dir / 'poster.png'
shutil.copy(test_dir / 'poster.png', poster)
name_parts = parse_file_name(target_file.name, config)
info = match(name_parts, config)
@@ -92,11 +100,11 @@ def test_sha_sum_two_identical_transformations(self):
update_mp4_file(target_file, info.results[0].looked_up, poster, ffprobe_results, NamerConfig())
validate_mp4_tags(self, target_file)
sha_1 = hashlib.sha256(target_file.read_bytes()).digest().hex()
- with environment() as (tempdir, _parrot, config):
+ with environment() as (temp_dir, _parrot, config):
test_dir = Path(__file__).resolve().parent
- target_file = tempdir / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
+ target_file = temp_dir / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
shutil.copy(test_dir / 'Site.22.01.01.painful.pun.XXX.720p.xpost.mp4', target_file)
- poster = tempdir / 'poster.png'
+ poster = temp_dir / 'poster.png'
shutil.copy(test_dir / 'poster.png', poster)
name_parts = parse_file_name(target_file.name, config)
info = match(name_parts, config)
@@ -112,9 +120,9 @@ def test_non_existent_poster(self):
Test writing metadata to an mp4, including tag information, which is only
available on scene requests to the porndb using uuid to request scene information.
"""
- with environment() as (tempdir, _parrot, config):
+ with environment() as (temp_dir, _parrot, config):
test_dir = Path(__file__).resolve().parent
- target_file = tempdir / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
+ target_file = temp_dir / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
shutil.copy(test_dir / 'Site.22.01.01.painful.pun.XXX.720p.xpost.mp4', target_file)
poster = None
name_parts = parse_file_name(target_file.name, config)
@@ -128,8 +136,8 @@ def test_non_existent_file(self):
Test writing metadata to an mp4, including tag information, which is only
available on scene requests to the porndb using uuid to request scene information.
"""
- with environment() as (tempdir, _parrot, config):
- targetfile = tempdir / 'test' / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
+ with environment() as (temp_dir, _parrot, config):
+ targetfile = temp_dir / 'test' / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
poster = None
name_parts = parse_file_name(targetfile.name, config)
info = match(name_parts, config)
@@ -143,8 +151,8 @@ def test_empty_infos(self):
available on scene requests to the porndb using uuid to request scene information.
"""
with tempfile.TemporaryDirectory(prefix='test') as tmpdir:
- tempdir = Path(tmpdir)
- target_file = tempdir / 'test' / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
+ temp_dir = Path(tmpdir)
+ target_file = temp_dir / 'test' / 'EvilAngel.22.01.03.Carmela.Clutch.Fabulous.Anal.3-Way.XXX.mp4'
target_file.parent.mkdir(parents=True, exist_ok=True)
test_dir = Path(__file__).resolve().parent
shutil.copy(test_dir / 'Site.22.01.01.painful.pun.XXX.720p.xpost.mp4', target_file)
diff --git a/test/namer_test.py b/test/namer_test.py
index 17daf28f..98afe5c0 100644
--- a/test/namer_test.py
+++ b/test/namer_test.py
@@ -8,11 +8,13 @@
import unittest
from pathlib import Path
+from loguru import logger
from mutagen.mp4 import MP4
from namer.configuration import NamerConfig
from namer.configuration_utils import to_ini
from namer.namer import check_arguments, main, set_permissions
+from test import utils
from test.utils import new_ea, sample_config, validate_mp4_tags, environment, FakeTPDB
@@ -21,15 +23,21 @@ class UnitTestAsTheDefaultExecution(unittest.TestCase):
Always test first.
"""
+ def __init__(self, method_name='runTest'):
+ super().__init__(method_name)
+
+ if not utils.is_debugging():
+ logger.remove()
+
def test_check_arguments(self):
"""
verify file system checks
"""
with tempfile.TemporaryDirectory(prefix='test') as tmpdir:
- tempdir = Path(tmpdir)
- target_dir = tempdir / 'path/'
- file = tempdir / 'file'
- config = tempdir / 'config'
+ temp_dir = Path(tmpdir)
+ target_dir = temp_dir / 'path/'
+ file = temp_dir / 'file'
+ config = temp_dir / 'config'
error = check_arguments(dir_to_process=target_dir, file_to_process=file, config_override=config)
self.assertTrue(error)
target_dir.mkdir()
@@ -42,8 +50,8 @@ def test_writing_metadata_file(self: unittest.TestCase):
"""
test namer main method renames and tags in place when -f (video file) is passed
"""
- with environment() as (tempdir, _fakeTPDB, config):
- targets = [new_ea(tempdir, use_dir=False)]
+ with environment() as (temp_dir, fake_tpdb, config):
+ targets = [new_ea(temp_dir, use_dir=False)]
main(['-f', str(targets[0].file), '-c', str(config.config_file)])
output = MP4(targets[0].get_file().parent / 'Evil Angel - 2022-01-03 - Carmela Clutch Fabulous Anal 3-Way! [WEBDL-240].mp4')
self.assertEqual(output.get('\xa9nam'), ['Carmela Clutch: Fabulous Anal 3-Way!'])
@@ -52,8 +60,8 @@ def test_writing_metadata_dir(self: unittest.TestCase):
"""
test namer main method renames and tags in place when -d (directory) is passed
"""
- with environment() as (tempdir, _fakeTPDB, config):
- targets = [new_ea(tempdir, use_dir=True)]
+ with environment() as (temp_dir, fake_tpdb, config):
+ targets = [new_ea(temp_dir, use_dir=True)]
main(['-d', str(targets[0].get_file().parent), '-c', str(config.config_file)])
output = MP4(targets[0].get_file().parent.parent / 'Evil Angel' / 'Evil Angel - 2022-01-03 - Carmela Clutch Fabulous Anal 3-Way! [WEBDL-240].mp4')
self.assertEqual(output.get('\xa9nam'), ['Carmela Clutch: Fabulous Anal 3-Way!'])
@@ -63,13 +71,13 @@ def test_writing_metadata_all_dirs(self: unittest.TestCase):
Test multiple directories are processed when -d (directory) and -m are passed.
Process all subdirs of -d.
"""
- with environment() as (tempdir, _fakeTPDB, config):
- tempdir: Path
- _fakeTPDB: FakeTPDB
+ with environment() as (temp_dir, fake_tpdb, config):
+ temp_dir: Path
+ fake_tpdb: FakeTPDB
config: NamerConfig
targets = [
- new_ea(tempdir, use_dir=True, post_stem='1'),
- new_ea(tempdir, use_dir=True, post_stem='2'),
+ new_ea(temp_dir, use_dir=True, post_stem='1'),
+ new_ea(temp_dir, use_dir=True, post_stem='2'),
]
main(['-d', str(targets[0].get_file().parent.parent), '-m', '-c', str(config.config_file)])
output = MP4(targets[0].get_file().parent.parent / 'Evil Angel' / 'Evil Angel - 2022-01-03 - Carmela Clutch Fabulous Anal 3-Way! [WEBDL-240].mp4')
@@ -88,23 +96,23 @@ def test_writing_metadata_from_nfo(self):
config.min_file_size = 0
with tempfile.TemporaryDirectory(prefix='test') as tmpdir:
current = Path(__file__).resolve().parent
- tempdir = Path(tmpdir)
+ temp_dir = Path(tmpdir)
nfo_file = current / 'ea.nfo'
mp4_file = current / 'Site.22.01.01.painful.pun.XXX.720p.xpost.mp4'
poster_file = current / 'poster.png'
- target_nfo_file = tempdir / 'ea.nfo'
- target_mp4_file = tempdir / 'ea.mp4'
- target_poster_file = tempdir / 'poster.png'
+ target_nfo_file = temp_dir / 'ea.nfo'
+ target_mp4_file = temp_dir / 'ea.mp4'
+ target_poster_file = temp_dir / 'poster.png'
shutil.copy(mp4_file, target_mp4_file)
shutil.copy(nfo_file, target_nfo_file)
shutil.copy(poster_file, target_poster_file)
- cfgfile = tempdir / 'test_namer.cfg'
- with open(cfgfile, 'w') as file:
+ cfg_file = temp_dir / 'test_namer.cfg'
+ with open(cfg_file, 'w') as file:
content = to_ini(config)
file.write(content)
- main(['-f', str(target_mp4_file), '-i', '-c', str(cfgfile)])
+ main(['-f', str(target_mp4_file), '-i', '-c', str(cfg_file)])
output = MP4(target_mp4_file.parent / 'Evil Angel - 2022-01-03 - Carmela Clutch Fabulous Anal 3-Way! [WEBDL-240].mp4')
self.assertEqual(output.get('\xa9nam'), ['Carmela Clutch: Fabulous Anal 3-Way!'])
@@ -114,8 +122,8 @@ def test_writing_metadata_all_dirs_files(self):
Process all sub-dirs of -d.
"""
config = sample_config()
- with environment(config) as (tempdir, _fakeTPDB, config):
- targets = [new_ea(tempdir, use_dir=False, post_stem='1'), new_ea(tempdir, use_dir=False, post_stem='2')]
+ with environment(config) as (temp_dir, fake_tpdb, config):
+ targets = [new_ea(temp_dir, use_dir=False, post_stem='1'), new_ea(temp_dir, use_dir=False, post_stem='2')]
main(['-d', str(targets[0].get_file().parent), '-m', '-c', str(config.config_file)])
output1 = targets[0].get_file().parent / 'Evil Angel - 2022-01-03 - Carmela Clutch Fabulous Anal 3-Way! [WEBDL-240].mp4'
validate_mp4_tags(self, output1)
diff --git a/test/namer_types_test.py b/test/namer_types_test.py
index ed0e7de0..b6814dfe 100644
--- a/test/namer_types_test.py
+++ b/test/namer_types_test.py
@@ -2,16 +2,18 @@
Test namer_types.py
"""
-import logging
import os
import sys
import unittest
from pathlib import Path
+from loguru import logger
+
from namer.configuration import NamerConfig
from namer.configuration_utils import verify_configuration
from namer.name_formatter import PartialFormatter
from namer.comparison_results import Performer
+from test import utils
class UnitTestAsTheDefaultExecution(unittest.TestCase):
@@ -19,6 +21,12 @@ class UnitTestAsTheDefaultExecution(unittest.TestCase):
Always test first.
"""
+ def __init__(self, method_name='runTest'):
+ super().__init__(method_name)
+
+ if not utils.is_debugging():
+ logger.remove()
+
def test_performer(self):
"""
Test performer __str__
@@ -97,7 +105,6 @@ def test_config_verification(self):
"""
Verify config verification.
"""
- logging.basicConfig(level=logging.INFO)
config = NamerConfig()
success = verify_configuration(config, PartialFormatter())
self.assertEqual(success, True)
diff --git a/test/namer_videophash_test.py b/test/namer_videophash_test.py
index 6d7f8141..6a2487f0 100644
--- a/test/namer_videophash_test.py
+++ b/test/namer_videophash_test.py
@@ -2,15 +2,17 @@
Test namer_videophash.py
"""
-import logging
import shutil
import tempfile
import unittest
from pathlib import Path
+from loguru import logger
+
from namer.videophash import imagehash
from namer.videophash.videophashstash import StashVideoPerceptualHash
from namer.videophash.videophash import VideoPerceptualHash
+from test import utils
from test.utils import sample_config
@@ -19,6 +21,12 @@ class UnitTestAsTheDefaultExecution(unittest.TestCase):
Always test first.
"""
+ def __init__(self, method_name='runTest'):
+ super().__init__(method_name)
+
+ if not utils.is_debugging():
+ logger.remove()
+
config = sample_config()
__generator = VideoPerceptualHash(config.ffmpeg)
__stash_generator = StashVideoPerceptualHash()
@@ -32,9 +40,9 @@ def test_get_phash(self):
expected_duration = 30
with tempfile.TemporaryDirectory(prefix='test') as tmpdir:
- tempdir = Path(tmpdir)
- shutil.copytree(Path(__file__).resolve().parent, tempdir / 'test')
- file = tempdir / 'test' / 'Site.22.01.01.painful.pun.XXX.720p.xpost.mp4'
+ temp_dir = Path(tmpdir)
+ shutil.copytree(Path(__file__).resolve().parent, temp_dir / 'test')
+ file = temp_dir / 'test' / 'Site.22.01.01.painful.pun.XXX.720p.xpost.mp4'
res = self.__generator.get_hashes(file)
self.assertIsNotNone(res)
@@ -52,9 +60,9 @@ def test_get_stash_phash(self):
expected_duration = 30
with tempfile.TemporaryDirectory(prefix='test') as tmpdir:
- tempdir = Path(tmpdir)
- shutil.copytree(Path(__file__).resolve().parent, tempdir / 'test')
- file = tempdir / 'test' / 'Site.22.01.01.painful.pun.XXX.720p.xpost.mp4'
+ temp_dir = Path(tmpdir)
+ shutil.copytree(Path(__file__).resolve().parent, temp_dir / 'test')
+ file = temp_dir / 'test' / 'Site.22.01.01.painful.pun.XXX.720p.xpost.mp4'
res = self.__stash_generator.get_hashes(file)
self.assertIsNotNone(res)
@@ -65,5 +73,4 @@ def test_get_stash_phash(self):
if __name__ == '__main__':
- logging.basicConfig(level=logging.INFO)
unittest.main()
diff --git a/test/namer_watchdog_test.py b/test/namer_watchdog_test.py
index e4dc49d7..3eaf1f97 100644
--- a/test/namer_watchdog_test.py
+++ b/test/namer_watchdog_test.py
@@ -3,31 +3,28 @@
"""
import contextlib
-import logging
import time
-import os
from typing import Any
import unittest
from pathlib import Path
+from loguru import logger
from mutagen.mp4 import MP4
from namer.ffmpeg import FFMpeg
from namer.configuration import NamerConfig
from namer.watchdog import create_watcher, done_copying, retry_failed, MovieWatcher
+from test import utils
from test.utils import Wait, new_ea, new_dorcel, validate_mp4_tags, validate_permissions, environment, sample_config, ProcessingTarget
-def wait_until_processed(watcher: MovieWatcher, durration: int = 60):
+def wait_until_processed(watcher: MovieWatcher, duration: int = 60):
"""
Waits until all files have been moved out of watch/working dirs.
"""
config = watcher.get_config()
- logging.info('waiting for files to be processes')
- Wait().seconds(durration).checking(1).until(lambda: len(list(config.watch_dir.iterdir())) > 0 or len(list(config.work_dir.iterdir())) > 0).isFalse()
- logging.info('past waiting for files')
+ Wait().seconds(duration).checking(1).until(lambda: len(list(config.watch_dir.iterdir())) > 0 or len(list(config.work_dir.iterdir())) > 0).is_false()
watcher.stop()
- logging.info('past stopping')
@contextlib.contextmanager
@@ -35,12 +32,25 @@ def make_watchdog_context(config: NamerConfig, targets=None):
if targets is None:
targets = []
- with environment(config) as (tempdir, mock_tpdb, config):
+ with environment(config) as (temp_dir, mock_tpdb, config):
for target in targets:
if target.file is None:
target.setup(config.watch_dir)
with create_watcher(config) as watcher:
- yield tempdir, watcher, mock_tpdb
+ yield temp_dir, watcher, mock_tpdb
+
+
+def remove_performer_genders(data: Any):
+ single_scene = data['data']
+ for json_performer in single_scene['performers']:
+ if not json_performer['extra']:
+ continue
+ json_performer['extra']['gender'] = None
+
+
+def remove_performers(data: Any):
+ single_scene = data['data']
+ single_scene['performers'] = []
class UnitTestAsTheDefaultExecution(unittest.TestCase):
@@ -48,6 +58,12 @@ class UnitTestAsTheDefaultExecution(unittest.TestCase):
Always test first.
"""
+ def __init__(self, method_name='runTest'):
+ super().__init__(method_name)
+
+ if not utils.is_debugging():
+ logger.remove()
+
def test_done_copying_non_existent_file(self):
"""
Test negatives.
@@ -65,7 +81,7 @@ def test_handler_collisions_success(self):
config.write_namer_log = True
config.min_file_size = 0
targets: list[ProcessingTarget] = [new_ea(), new_ea(use_dir=False)]
- with make_watchdog_context(config, targets) as (tempdir, watcher, fakeTPDB):
+ with make_watchdog_context(config, targets) as (temp_dir, watcher, fake_tpdb):
wait_until_processed(watcher)
self.assertFalse(targets[0].get_file().exists())
self.assertEqual(len(list(config.work_dir.iterdir())), 0)
@@ -78,7 +94,6 @@ def test_handler_collisions_success(self):
self.assertEqual(output2.get('\xa9nam'), ['Carmela Clutch: Fabulous Anal 3-Way!'])
self.assertEqual(len(list(config.failed_dir.iterdir())), 0)
self.assertEqual(len(list(config.watch_dir.iterdir())), 0)
- logging.info(os.environ.get('PYTEST_CURRENT_TEST'))
def test_handler_collisions_success_choose_best(self):
"""
@@ -94,7 +109,7 @@ def test_handler_collisions_success_choose_best(self):
config.preserve_duplicates = False
config.max_desired_resolutions = -1
config.desired_codec = ['hevc', 'h264']
- with make_watchdog_context(config) as (tempdir, watcher, fakeTPDB):
+ with make_watchdog_context(config) as (temp_dir, watcher, fake_tpdb):
targets: list[ProcessingTarget] = [new_ea(config.watch_dir, mp4_file_name=okay), new_ea(config.watch_dir, use_dir=False, post_stem='2', mp4_file_name=better), new_ea(config.watch_dir, use_dir=False, post_stem='1', mp4_file_name=best)]
wait_until_processed(watcher, 120)
self.assertFalse(targets[0].get_file().exists())
@@ -111,7 +126,6 @@ def test_handler_collisions_success_choose_best(self):
self.assertEqual(stream.codec_name, 'hevc')
output_file2 = config.dest_dir / 'Evil Angel' / 'Evil Angel - 2022-01-03 - Carmela Clutch Fabulous Anal 3-Way! [WEBDL-720p](1).mp4'
self.assertFalse(output_file2.exists())
- logging.info(os.environ.get('PYTEST_CURRENT_TEST'))
def test_event_listener_success(self):
"""
@@ -122,7 +136,7 @@ def test_event_listener_success(self):
config.min_file_size = 0
config.write_namer_log = True
config.min_file_size = 0
- with make_watchdog_context(config) as (tempdir, watcher, fakeTPDB):
+ with make_watchdog_context(config) as (temp_dir, watcher, fake_tpdb):
targets = [new_ea(config.watch_dir)]
wait_until_processed(watcher)
self.assertFalse(targets[0].get_file().exists())
@@ -132,7 +146,6 @@ def test_event_listener_success(self):
self.assertEqual(output.get('\xa9nam'), ['Carmela Clutch: Fabulous Anal 3-Way!'])
self.assertEqual(len(list(config.failed_dir.iterdir())), 0)
self.assertEqual(len(list(config.watch_dir.iterdir())), 0)
- logging.info(os.environ.get('PYTEST_CURRENT_TEST'))
def test_event_listener_success_conversion(self):
"""
@@ -144,14 +157,13 @@ def test_event_listener_success_conversion(self):
config.write_namer_log = True
config.min_file_size = 0
config.convert_container_to = 'mkv'
- with make_watchdog_context(config) as (tempdir, watcher, fakeTPDB):
+ with make_watchdog_context(config) as (temp_dir, watcher, fake_tpdb):
targets = [new_ea(config.watch_dir)]
wait_until_processed(watcher)
self.assertFalse(targets[0].get_file().exists())
self.assertEqual(len(list(config.work_dir.iterdir())), 0)
output_file = config.dest_dir / 'Evil Angel' / 'Evil Angel - 2022-01-03 - Carmela Clutch Fabulous Anal 3-Way! [WEBDL-240].mkv'
self.assertTrue(output_file.exists())
- logging.info(os.environ.get('PYTEST_CURRENT_TEST'))
def test_handler_deeply_nested_success_no_dirname(self):
"""
@@ -162,7 +174,7 @@ def test_handler_deeply_nested_success_no_dirname(self):
config.write_namer_log = True
config.min_file_size = 0
config.preserve_duplicates = True
- with make_watchdog_context(config) as (tempdir, watcher, fakeTPDB):
+ with make_watchdog_context(config) as (temp_dir, watcher, fake_tpdb):
targets = [
new_ea(config.watch_dir / 'deeper' / 'and_deeper', use_dir=False),
new_ea(config.watch_dir, post_stem='number2', use_dir=False),
@@ -178,7 +190,6 @@ def test_handler_deeply_nested_success_no_dirname(self):
validate_permissions(self, output_file2, 664)
self.assertEqual(len(list(config.failed_dir.iterdir())), 0)
self.assertEqual(len(list(config.watch_dir.iterdir())), 0)
- logging.info(os.environ.get('PYTEST_CURRENT_TEST'))
def test_handler_deeply_nested_success_no_dirname_extra_files(self):
"""
@@ -190,7 +201,7 @@ def test_handler_deeply_nested_success_no_dirname_extra_files(self):
config.min_file_size = 0
config.del_other_files = False
config.new_relative_path_name = '{site}/{site} - {date} - {name}/{site} - {date} - {name}.{ext}'
- with make_watchdog_context(config) as (tempdir, watcher, fakeTPDB):
+ with make_watchdog_context(config) as (temp_dir, watcher, fake_tpdb):
targets = [
new_ea(config.watch_dir / 'deeper' / 'and_deeper', use_dir=False),
]
@@ -208,7 +219,6 @@ def test_handler_deeply_nested_success_no_dirname_extra_files(self):
self.assertEqual(output_test_file.read_text(), contents)
self.assertEqual(len(list(config.failed_dir.iterdir())), 0)
self.assertEqual(len(list(config.watch_dir.iterdir())), 0)
- logging.info(os.environ.get('PYTEST_CURRENT_TEST'))
def test_handler_deeply_nested_success(self):
"""
@@ -222,7 +232,7 @@ def test_handler_deeply_nested_success(self):
config.set_dir_permissions = None
config.set_file_permissions = None
config.new_relative_path_name = './{network}/' + config.new_relative_path_name
- with make_watchdog_context(config) as (tempdir, watcher, fakeTPDB):
+ with make_watchdog_context(config) as (temp_dir, watcher, fake_tpdb):
targets = [
new_ea(config.watch_dir / 'EvilAngel - 2022-01-03 - Carmela Clutch Fabulous Anal 3-Way', use_dir=True),
]
@@ -235,7 +245,6 @@ def test_handler_deeply_nested_success(self):
validate_permissions(self, output_file, 600)
self.assertEqual(len(list(config.failed_dir.iterdir())), 0)
self.assertEqual(len(list(config.watch_dir.iterdir())), 0)
- logging.info(os.environ.get('PYTEST_CURRENT_TEST'))
def test_handler_deeply_nested_success_missing_network(self):
"""
@@ -249,7 +258,7 @@ def test_handler_deeply_nested_success_missing_network(self):
config.set_dir_permissions = None
config.set_file_permissions = None
config.new_relative_path_name = './{network}/' + config.new_relative_path_name
- with make_watchdog_context(config) as (tempdir, watcher, fakeTPDB):
+ with make_watchdog_context(config) as (temp_dir, watcher, fake_tpdb):
targets = [
new_dorcel(config.watch_dir, use_dir=True),
]
@@ -261,7 +270,6 @@ def test_handler_deeply_nested_success_missing_network(self):
validate_permissions(self, output_file, 600)
self.assertEqual(len(list(config.failed_dir.iterdir())), 0)
self.assertEqual(len(list(config.watch_dir.iterdir())), 0)
- logging.info(os.environ.get('PYTEST_CURRENT_TEST'))
def test_handler_deeply_nested_success_custom_location(self):
"""
@@ -275,7 +283,7 @@ def test_handler_deeply_nested_success_custom_location(self):
config.set_dir_permissions = None
config.set_file_permissions = None
config.new_relative_path_name = '{site} - {date} - {name}/{site} - {date} - {name} - {uuid} - {external_id} - ({resolution}).{ext}'
- with make_watchdog_context(config) as (tempdir, watcher, fakeTPDB):
+ with make_watchdog_context(config) as (temp_dir, watcher, fake_tpdb):
targets = [
new_ea(config.watch_dir / 'EvilAngel - 2022-01-03 - Carmela Clutch Fabulous Anal 3-Way', use_dir=True),
]
@@ -287,11 +295,11 @@ def test_handler_deeply_nested_success_custom_location(self):
validate_permissions(self, output_file, 600)
self.assertEqual(len(list(config.failed_dir.iterdir())), 0)
self.assertEqual(len(list(config.watch_dir.iterdir())), 0)
- logging.info(os.environ.get('PYTEST_CURRENT_TEST'))
def test_handler_deeply_nested_success_bracked(self):
"""
Test the handle function works for a directory.
+
"""
config = sample_config()
config.prefer_dir_name_if_available = True
@@ -301,7 +309,7 @@ def test_handler_deeply_nested_success_bracked(self):
config.set_dir_permissions = None
config.set_file_permissions = None
config.new_relative_path_name = '{site} - {date} - {name}/{site} - {date} - {name} - {uuid} - {external_id} - ({resolution}).{ext}'
- with make_watchdog_context(config) as (tempdir, watcher, fakeTPDB):
+ with make_watchdog_context(config) as (temp_dir, watcher, fake_tpdb):
targets = [
new_ea(config.watch_dir / 'EvilAngel - 2022-01-03 - Carmela Clutch Fabulous Anal 3-Way! XXX [XvX]', post_stem='XXX [XvX]'),
]
@@ -313,20 +321,18 @@ def test_handler_deeply_nested_success_bracked(self):
validate_permissions(self, output_file, 600)
self.assertEqual(len(list(config.failed_dir.iterdir())), 0)
self.assertEqual(len(list(config.watch_dir.iterdir())), 0)
- logging.info(os.environ.get('PYTEST_CURRENT_TEST'))
def test_handler_ignore(self):
"""
Test the handle function works for a directory.
"""
- with make_watchdog_context(sample_config()) as (tempdir, watcher, fakeTPDB):
+ with make_watchdog_context(sample_config()) as (temp_dir, watcher, fake_tpdb):
targets = [
new_ea(watcher.get_config().watch_dir / '_UNPACK_stuff' / 'EvilAngel - Carmela Clutch Fabulous Anal 3-Way', use_dir=True),
]
time.sleep(2)
watcher.stop()
self.assertTrue(targets[0].get_file().exists())
- logging.info(os.environ.get('PYTEST_CURRENT_TEST'))
def test_handler_failure(self):
"""
@@ -336,7 +342,7 @@ def test_handler_failure(self):
config.write_namer_log = True
config.del_other_files = False
config.min_file_size = 0
- with make_watchdog_context(config) as (tempdir, watcher, fakeTPDB):
+ with make_watchdog_context(config) as (temp_dir, watcher, fake_tpdb):
targets = [new_ea(config.watch_dir, use_dir=False, match=False)]
wait_until_processed(watcher)
self.assertFalse(targets[0].get_file().exists())
@@ -350,7 +356,6 @@ def test_handler_failure(self):
retry_failed(config)
self.assertEqual(len(list(config.failed_dir.iterdir())), 0)
self.assertGreater(len(list(config.watch_dir.iterdir())), 0)
- logging.info(os.environ.get('PYTEST_CURRENT_TEST'))
def test_name_parser_success(self):
"""
@@ -362,7 +367,7 @@ def test_name_parser_success(self):
config.min_file_size = 0
config.name_parser = '{_site} - {_ts}{_name}.{_ext}'
config.sites_with_no_date_info = ['evilangel']
- with make_watchdog_context(config) as (tempdir, watcher, fakeTPDB):
+ with make_watchdog_context(config) as (temp_dir, watcher, fake_tpdb):
targets = [
new_ea(config.watch_dir / 'EvilAngel - Carmela Clutch Fabulous Anal 3-Way', use_dir=True),
]
@@ -373,14 +378,6 @@ def test_name_parser_success(self):
self.assertEqual(len(list(config.failed_dir.iterdir())), 0)
self.assertEqual(len(list(config.watch_dir.iterdir())), 0)
self.assertEqual(len(list(config.work_dir.iterdir())), 0)
- logging.info(os.environ.get('PYTEST_CURRENT_TEST'))
-
- def remove_performer_genders(self, data: Any):
- single_scene = data['data']
- for json_performer in single_scene['performers']:
- if not json_performer['extra']:
- continue
- json_performer['extra']['gender'] = None
def test_missing_performers_gender_success(self):
"""
@@ -392,8 +389,8 @@ def test_missing_performers_gender_success(self):
config.write_namer_log = True
config.min_file_size = 0
config.new_relative_path_name = '{performers}/{site} - {date} - {name}.{ext}'
- with make_watchdog_context(config) as (tempdir, watcher, fakeTPDB):
- self.remove_performer_genders(fakeTPDB._scenes['ea.full.json'])
+ with make_watchdog_context(config) as (temp_dir, watcher, fake_tpdb):
+ remove_performer_genders(fake_tpdb._scenes['ea.full.json'])
targets = [new_ea(config.watch_dir)]
wait_until_processed(watcher)
self.assertFalse(targets[0].get_file().exists())
@@ -404,11 +401,6 @@ def test_missing_performers_gender_success(self):
self.assertEqual(output.get('\xa9nam'), ['Carmela Clutch: Fabulous Anal 3-Way!'])
self.assertEqual(len(list(config.failed_dir.iterdir())), 0)
self.assertEqual(len(list(config.watch_dir.iterdir())), 0)
- logging.info(os.environ.get('PYTEST_CURRENT_TEST'))
-
- def remove_performers(self, data: Any):
- single_scene = data['data']
- single_scene['performers'] = []
def test_missing_performers_success(self):
"""
@@ -420,8 +412,8 @@ def test_missing_performers_success(self):
config.write_namer_log = True
config.min_file_size = 0
config.new_relative_path_name = '{performers}/{site} - {date} - {name}.{ext}'
- with make_watchdog_context(config) as (tempdir, watcher, fakeTPDB):
- self.remove_performers(fakeTPDB._scenes['ea.full.json'])
+ with make_watchdog_context(config) as (temp_dir, watcher, fake_tpdb):
+ remove_performers(fake_tpdb._scenes['ea.full.json'])
targets = [new_ea(config.watch_dir)]
wait_until_processed(watcher)
self.assertFalse(targets[0].get_file().exists())
@@ -432,7 +424,6 @@ def test_missing_performers_success(self):
self.assertEqual(output.get('\xa9nam'), ['Carmela Clutch: Fabulous Anal 3-Way!'])
self.assertEqual(len(list(config.failed_dir.iterdir())), 0)
self.assertEqual(len(list(config.watch_dir.iterdir())), 0)
- logging.info(os.environ.get('PYTEST_CURRENT_TEST'))
def test_name_parser_failure_with_startup_processing(self):
"""
@@ -446,7 +437,7 @@ def test_name_parser_failure_with_startup_processing(self):
targets = [
new_ea(relative='EvilAngel - Carmela Clutch Fabulous Anal 3-Way/', use_dir=True),
]
- with make_watchdog_context(config, targets) as (tempdir, watcher, fakeTPDB):
+ with make_watchdog_context(config, targets) as (temp_dir, watcher, fake_tpdb):
wait_until_processed(watcher)
self.assertFalse(targets[0].get_file().exists())
output_file = config.failed_dir / 'EvilAngel - Carmela Clutch Fabulous Anal 3-Way'
@@ -456,7 +447,6 @@ def test_name_parser_failure_with_startup_processing(self):
self.assertEqual(len(list(config.watch_dir.iterdir())), 0)
self.assertEqual(len(list(config.work_dir.iterdir())), 0)
self.assertEqual(len(list(config.dest_dir.iterdir())), 0)
- logging.info(os.environ.get('PYTEST_CURRENT_TEST'))
def test_fetch_trailer_write_nfo_success(self):
"""
@@ -471,7 +461,7 @@ def test_fetch_trailer_write_nfo_success(self):
config.min_file_size = 0
config.write_nfo = True
targets = [new_ea()]
- with make_watchdog_context(config, targets) as (tempdir, watcher, fakeTPDB):
+ with make_watchdog_context(config, targets) as (temp_dir, watcher, fake_tpdb):
wait_until_processed(watcher)
self.assertFalse(targets[0].get_file().exists())
self.assertEqual(len(list(config.work_dir.iterdir())), 0)
@@ -482,9 +472,7 @@ def test_fetch_trailer_write_nfo_success(self):
self.assertEqual(len(list(config.failed_dir.iterdir())), 0)
self.assertEqual(len(list(config.watch_dir.iterdir())), 0)
self.assertTrue(nfo_file.exists() and nfo_file.is_file() and nfo_file.stat().st_size != 0)
- logging.info(os.environ.get('PYTEST_CURRENT_TEST'))
if __name__ == '__main__':
- logging.basicConfig(level=logging.INFO)
unittest.main()
diff --git a/test/namer_webhook_test.py b/test/namer_webhook_test.py
index d66102ae..2a3b7bee 100644
--- a/test/namer_webhook_test.py
+++ b/test/namer_webhook_test.py
@@ -3,12 +3,14 @@
"""
import json
-import logging
import unittest
from pathlib import Path
from unittest.mock import patch, MagicMock
+from loguru import logger
+
from namer.namer import send_webhook_notification
+from test import utils
from test.utils import sample_config, environment, new_ea
@@ -17,6 +19,12 @@ class WebhookTest(unittest.TestCase):
Test the webhook notification functionality.
"""
+ def __init__(self, method_name='runTest'):
+ super().__init__(method_name)
+
+ if not utils.is_debugging():
+ logger.remove()
+
def test_webhook_disabled(self):
"""
Test that no webhook is sent when the feature is disabled.
@@ -83,12 +91,12 @@ def test_integration_with_file_processing(self):
"""
Test that webhook is triggered when a file is successfully processed.
"""
- with environment() as (tempdir, _fakeTPDB, config):
+ with environment() as (temp_dir, fake_tpdb, config):
config.webhook_enabled = True
config.webhook_url = 'http://example.com/webhook'
with patch('namer.namer.send_webhook_notification') as mock_webhook:
- targets = [new_ea(tempdir, use_dir=False)]
+ targets = [new_ea(temp_dir, use_dir=False)]
# Process the file
from namer.namer import main
@@ -100,5 +108,4 @@ def test_integration_with_file_processing(self):
if __name__ == '__main__':
- logging.basicConfig(level=logging.INFO)
unittest.main()
diff --git a/test/utils.py b/test/utils.py
index c6f5866c..d425c7e7 100644
--- a/test/utils.py
+++ b/test/utils.py
@@ -59,10 +59,10 @@ def __wait(self, state: bool):
sleep(self._checking)
raise RuntimeError(f'Timed out waiting for predicate {self._predicate} to return {state}')
- def isTrue(self):
+ def is_true(self):
self.__wait(True)
- def isFalse(self):
+ def is_false(self):
self.__wait(False)
@@ -209,28 +209,28 @@ def environment(config: NamerConfig = None): # type: ignore
if config is None:
config = sample_config()
- with tempfile.TemporaryDirectory(prefix='test') as tmpdir, FakeTPDB() as fakeTpdb:
- tempdir = Path(tmpdir)
+ with tempfile.TemporaryDirectory(prefix='test') as tmp_dir, FakeTPDB() as fake_tpdb:
+ temp_dir = Path(tmp_dir).resolve()
config.enabled_tagging = True
config.enabled_poster = True
- config.override_tpdb_address = fakeTpdb.get_url()
- config.watch_dir = tempdir / 'watch'
+ config.override_tpdb_address = fake_tpdb.get_url()
+ config.watch_dir = temp_dir / 'watch'
config.watch_dir.mkdir(parents=True, exist_ok=True)
- config.dest_dir = tempdir / 'dest'
+ config.dest_dir = temp_dir / 'dest'
config.dest_dir.mkdir(parents=True, exist_ok=True)
- config.work_dir = tempdir / 'work'
+ config.work_dir = temp_dir / 'work'
config.work_dir.mkdir(parents=True, exist_ok=True)
- config.failed_dir = tempdir / 'failed'
+ config.failed_dir = temp_dir / 'failed'
config.failed_dir.mkdir(parents=True, exist_ok=True)
config.porndb_token = 'notarealtoken'
- cfgfile = tempdir / 'test_namer.cfg'
+ cfgfile = temp_dir / 'test_namer.cfg'
config.min_file_size = 0
with open(cfgfile, 'w') as file:
content = to_ini(config)
file.write(content)
config.config_file = cfgfile
- yield tempdir, fakeTpdb, config
+ yield temp_dir, fake_tpdb, config
def validate_permissions(test_self, file: Path, perm: int):
@@ -240,7 +240,6 @@ def validate_permissions(test_self, file: Path, perm: int):
if hasattr(os, 'chmod') and platform.system() != 'Windows':
found = oct(file.stat().st_mode)[-3:]
expected = str(perm)[-3:]
- print('Found {found}, Expected {expected}')
# test_self.assertEqual(found, "664")
test_self.assertEqual(found, expected)
diff --git a/test/web/namer_web_test.py b/test/web/namer_web_test.py
index 63dd8c2f..b195d388 100644
--- a/test/web/namer_web_test.py
+++ b/test/web/namer_web_test.py
@@ -5,12 +5,14 @@
from platform import system
import requests
+from loguru import logger
from selenium.webdriver import Chrome, ChromeOptions, Edge, EdgeOptions, Safari
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.safari.service import Service as SafariService
from namer.configuration import NamerConfig
from namer.watchdog import create_watcher
+from test import utils
from test.namer_metadataapi_test import environment
from test.namer_watchdog_test import new_ea
from test.utils import is_debugging, sample_config
@@ -62,10 +64,10 @@ def default_os_browser(debug: bool) -> WebDriver:
@contextlib.contextmanager # type: ignore
def make_test_context(config: NamerConfig):
- with environment(config) as (tempdir, mock_tpdb, config), create_watcher(config) as watcher, default_os_browser(is_debugging()) as browser:
+ with environment(config) as (temp_dir, mock_tpdb, config), create_watcher(config) as watcher, default_os_browser(is_debugging()) as browser:
url = f'http://{config.host}:{watcher.get_web_port()}{config.web_root}/failed'
browser.get(url)
- yield tempdir, watcher, browser, mock_tpdb
+ yield temp_dir, watcher, browser, mock_tpdb
class UnitTestAsTheDefaultExecution(unittest.TestCase):
@@ -73,6 +75,12 @@ class UnitTestAsTheDefaultExecution(unittest.TestCase):
Always test first.
"""
+ def __init__(self, method_name='runTest'):
+ super().__init__(method_name)
+
+ if not utils.is_debugging():
+ logger.remove()
+
def test_webdriver_flow(self: unittest.TestCase):
"""
Test we can start the app, install, run and control a browser and shut it all down safely.
@@ -88,7 +96,7 @@ def test_webdriver_flow(self: unittest.TestCase):
config.write_namer_failed_log = True
config.del_other_files = True
config.extra_sleep_time = 1
- with make_test_context(config) as (_tempdir, _watcher, browser, _mock_tpdb):
+ with make_test_context(config) as (temp_dir, watcher, browser, mock_tpdb):
new_ea(config.failed_dir, use_dir=False)
(
FailedPage(browser)
@@ -128,7 +136,6 @@ def test_webdriver_flow(self: unittest.TestCase):
.select() # returns to failed page
.assert_has_no_files()
)
- print('done')
def test_parrot(self):
with ParrotWebServer() as parrot: