mirror of
https://github.com/sabnzbd/sabnzbd.git
synced 2026-01-02 04:28:02 -05:00
Compare commits
3 Commits
master
...
bugfix/cle
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
efe17ca3bb | ||
|
|
d4995e3120 | ||
|
|
90989b374a |
14
.github/workflows/build_release.yml
vendored
14
.github/workflows/build_release.yml
vendored
@@ -13,10 +13,10 @@ jobs:
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Set up Python
|
||||
- name: Set up Python 3.13
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.14"
|
||||
python-version: "3.13"
|
||||
architecture: "x64"
|
||||
cache: pip
|
||||
cache-dependency-path: "**/requirements.txt"
|
||||
@@ -89,18 +89,18 @@ jobs:
|
||||
# We need the official Python, because the GA ones only support newer macOS versions
|
||||
# The deployment target is picked up by the Python build tools automatically
|
||||
# If updated, make sure to also set LSMinimumSystemVersion in SABnzbd.spec
|
||||
PYTHON_VERSION: "3.14.0"
|
||||
MACOSX_DEPLOYMENT_TARGET: "10.15"
|
||||
PYTHON_VERSION: "3.13.7"
|
||||
MACOSX_DEPLOYMENT_TARGET: "10.13"
|
||||
# We need to force compile for universal2 support
|
||||
CFLAGS: -arch x86_64 -arch arm64
|
||||
ARCHFLAGS: -arch x86_64 -arch arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Set up Python
|
||||
- name: Set up Python 3.13
|
||||
# Only use this for the caching of pip packages!
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.14"
|
||||
python-version: "3.13"
|
||||
cache: pip
|
||||
cache-dependency-path: "**/requirements.txt"
|
||||
- name: Cache Python download
|
||||
@@ -219,7 +219,7 @@ jobs:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.14"
|
||||
python-version: "3.x"
|
||||
cache: pip
|
||||
cache-dependency-path: "builder/release-requirements.txt"
|
||||
- name: Download Source distribution artifact
|
||||
|
||||
4
.github/workflows/integration_testing.yml
vendored
4
.github/workflows/integration_testing.yml
vendored
@@ -37,10 +37,10 @@ jobs:
|
||||
include:
|
||||
- name: macOS
|
||||
os: macos-13
|
||||
python-version: "3.14"
|
||||
python-version: "3.13"
|
||||
- name: Windows
|
||||
os: windows-2022
|
||||
python-version: "3.14"
|
||||
python-version: "3.13"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
2
.github/workflows/translations.yml
vendored
2
.github/workflows/translations.yml
vendored
@@ -30,7 +30,7 @@ jobs:
|
||||
run: |
|
||||
python3 tools/make_mo.py
|
||||
- name: Push translatable and translated texts back to repo
|
||||
uses: stefanzweifel/git-auto-commit-action@v7.0.0
|
||||
uses: stefanzweifel/git-auto-commit-action@v6.0.1
|
||||
if: env.TX_TOKEN
|
||||
with:
|
||||
commit_message: |
|
||||
|
||||
77
README.mkd
77
README.mkd
@@ -1,74 +1,7 @@
|
||||
Release Notes - SABnzbd 4.5.5
|
||||
Release Notes - SABnzbd 4.5.0 Release Candidate 1
|
||||
=========================================================
|
||||
|
||||
## Bug fixes and changes in 4.5.5
|
||||
|
||||
* macOS: Failed to start on versions of macOS older than 11.
|
||||
Python 3.14 dropped support for macOS 10.13 and 10.14.
|
||||
Because of that macOS 10.15 is required to run 4.5.5.
|
||||
|
||||
## Bug fixes and changes in 4.5.4
|
||||
|
||||
### New Features
|
||||
* History details now includes option to mark job as `Completed`.
|
||||
* `Quota` notifications available for all notification services.
|
||||
- Sends alerts at 75%, 90%, and 100% quota usage.
|
||||
* Multi-Operations now supports Move to Top/Bottom.
|
||||
* New `outgoing_nntp_ip` option to bind outgoing NNTP connections to specific IP address.
|
||||
|
||||
### Improvements
|
||||
* Setup wizard now requires successful Server Test before proceeding.
|
||||
* Anime episode notation `S04 - 10` now supported for Sorting and Duplicate Detection.
|
||||
* Multi-Operations: Play/Resume button unselects on second click for better usability.
|
||||
* Unrar now handles renaming of invalid characters on Windows filesystem.
|
||||
* Switched from vendored `sabnzbd.rarfile` module to `rarfile>=4.2`.
|
||||
* Warning displayed when removing all Orphaned jobs (clears Temporary Download folder).
|
||||
|
||||
### Bug Fixes
|
||||
* Active connections counter in Status window now updates correctly.
|
||||
* Job setting changes during URL-grabbing no longer ignored.
|
||||
* Incomplete `.par2` file parsing no longer leaves files behind.
|
||||
* `Local IPv4 address` now detectable when using Socks5 proxy.
|
||||
* Server configuration changes no longer show `Failure` message during page reload.
|
||||
|
||||
### Platform-Specific
|
||||
* Linux: `Make Windows compatible` automatically enabled when needed.
|
||||
* Windows: Executables are now signed using SignPath Foundation certificate.
|
||||
* Windows: Can now start SABnzbd directly from installer.
|
||||
* Windows and macOS: Binaries now use Python 3.14.
|
||||
|
||||
## Bug fixes and changes in 4.5.3
|
||||
|
||||
* Remember if `Permanently delete` was previously checked.
|
||||
* All available IP-addresses will be included when selecting the fastest.
|
||||
* Pre-queue script rejected NZBs were sometimes reported as `URL Fetching failed`.
|
||||
* RSS `Next scan` time was not adjusted after manual `Read All Feeds Now`.
|
||||
* Prevent renaming of `.cbr` files during verification.
|
||||
* If `--disable-file-log` was enabled, `Show Logging` would crash.
|
||||
* API: Added `time_added`, timestamp of when the job was added to the queue.
|
||||
* API: History output could contain duplicate items.
|
||||
* Snap: Updated packages and changed build process for reliability.
|
||||
* macOS: Repair would fail on macOS 10.13 High Sierra.
|
||||
* Windows: Unable to start on Windows 8.
|
||||
* Windows: Updated Unrar to 7.13, which resolves CVE-2025-8088.
|
||||
|
||||
## Bug fixes and changes in 4.5.2
|
||||
|
||||
* Added Tab and Shift+Tab navigation to move between rename fields in queue.
|
||||
* Invalid cookies of other services could result in errors.
|
||||
* Internet Bandwidth test could be stuck in infinite loop.
|
||||
* RSS readout did not ignore torrent alternatives.
|
||||
* Prowl and Pushover settings did not load correctly.
|
||||
* Renamed `osx` to `macos` internally.
|
||||
* API: Removed `B` post-fix from `quota` and `left_quota` fields in `queue`.
|
||||
* Windows: Support more languages in the installer.
|
||||
* Windows and macOS: Updated par2cmdline-turbo to 1.3.0 and Unrar to 7.12.
|
||||
|
||||
## Bug fixes and changes in 4.5.1
|
||||
|
||||
* Correct platform detection on Linux.
|
||||
* The `From SxxEyy` RSS filters did not always work.
|
||||
* Windows and macOS: Update Unrar to 7.11.
|
||||
This is the first Release Candidate for the 4.5.0 release.
|
||||
|
||||
## New features in 4.5.0
|
||||
|
||||
@@ -88,8 +21,10 @@ Release Notes - SABnzbd 4.5.5
|
||||
|
||||
## Upgrade notices
|
||||
|
||||
* Direct upgrade supported from version 3.0.0 and newer.
|
||||
* Older versions require performing a `Queue repair` after upgrading.
|
||||
* You can directly upgrade from version 3.0.0 and newer.
|
||||
* Upgrading from older versions will require performing a `Queue repair`.
|
||||
* Downgrading from version 4.2.0 or newer to 3.7.2 or older will require
|
||||
performing a `Queue repair` due to changes in the internal data format.
|
||||
|
||||
## Known problems and solutions
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
import glob
|
||||
import platform
|
||||
import re
|
||||
import sys
|
||||
import os
|
||||
@@ -27,7 +28,6 @@ import tarfile
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
import configobj
|
||||
import packaging.version
|
||||
from typing import List
|
||||
|
||||
from constants import (
|
||||
@@ -109,52 +109,6 @@ def patch_version_file(release_name):
|
||||
ver.write(version_file)
|
||||
|
||||
|
||||
def test_macos_min_version(binary_path: str):
|
||||
# Skip check if nothing was set
|
||||
if macos_min_version := os.environ.get("MACOSX_DEPLOYMENT_TARGET"):
|
||||
# Skip any arm64 specific files
|
||||
if "arm64" in binary_path:
|
||||
print(f"Skipping arm64 binary {binary_path}")
|
||||
return
|
||||
|
||||
# Check minimum macOS version is at least mac OS10.13
|
||||
# We only check the x86_64 since for arm64 it's always macOS 11+
|
||||
print(f"Checking if binary supports macOS {macos_min_version} and above: {binary_path}")
|
||||
otool_output = run_external_command(
|
||||
[
|
||||
"otool",
|
||||
"-arch",
|
||||
"x86_64",
|
||||
"-l",
|
||||
binary_path,
|
||||
],
|
||||
print_output=False,
|
||||
)
|
||||
|
||||
# Parse the output for LC_BUILD_VERSION minos
|
||||
# The output is very large, so that's why we enumerate over it
|
||||
req_version = packaging.version.parse(macos_min_version)
|
||||
bin_version = None
|
||||
lines = otool_output.split("\n")
|
||||
for line_nr, line in enumerate(lines):
|
||||
if "LC_VERSION_MIN_MACOSX" in line:
|
||||
# Display the version in the next lines
|
||||
bin_version = packaging.version.parse(lines[line_nr + 2].split()[1])
|
||||
elif "minos" in line:
|
||||
bin_version = packaging.version.parse(line.split()[1])
|
||||
|
||||
if bin_version and bin_version > req_version:
|
||||
raise ValueError(f"{binary_path} requires {bin_version}, we want {req_version}")
|
||||
else:
|
||||
# We got the information we need
|
||||
break
|
||||
else:
|
||||
print(lines)
|
||||
raise RuntimeError(f"Could not determine minimum macOS version for {binary_path}")
|
||||
else:
|
||||
print(f"Skipping macOS version check, MACOSX_DEPLOYMENT_TARGET not set")
|
||||
|
||||
|
||||
def test_sab_binary(binary_path: str):
|
||||
"""Wrapper to have a simple start-up test for the binary"""
|
||||
with tempfile.TemporaryDirectory() as config_dir:
|
||||
@@ -336,11 +290,7 @@ if __name__ == "__main__":
|
||||
"macos/7zip/7zz",
|
||||
]
|
||||
for file_to_sign in files_to_sign:
|
||||
# Make sure it supports the macOS versions we want first
|
||||
test_macos_min_version(file_to_sign)
|
||||
|
||||
# Then sign in
|
||||
print("Signing %s with hardened runtime" % file_to_sign)
|
||||
print("Signing %s with hardended runtime" % file_to_sign)
|
||||
run_external_command(
|
||||
[
|
||||
"codesign",
|
||||
@@ -365,16 +315,13 @@ if __name__ == "__main__":
|
||||
|
||||
# Make sure we created a fully universal2 release when releasing or during CI
|
||||
if RELEASE_THIS or ON_GITHUB_ACTIONS:
|
||||
for bin_to_check in glob.glob("dist/SABnzbd.app/**/*.so", recursive=True):
|
||||
for bin_to_check in glob.glob("dist/SABnzbd.app/Contents/MacOS/**/*.so", recursive=True):
|
||||
print("Checking if binary is universal2: %s" % bin_to_check)
|
||||
file_output = run_external_command(["file", bin_to_check], print_output=False)
|
||||
# Make sure we have both arm64 and x86
|
||||
if not ("x86_64" in file_output and "arm64" in file_output):
|
||||
raise RuntimeError("Non-universal2 binary found!")
|
||||
|
||||
# Make sure it supports the macOS versions we want
|
||||
test_macos_min_version(bin_to_check)
|
||||
|
||||
# Only continue if we can sign
|
||||
if authority:
|
||||
# We use PyInstaller to sign the main SABnzbd executable and the SABnzbd.app
|
||||
|
||||
@@ -75,7 +75,7 @@ print("----")
|
||||
# Check if tagged as release and check for token
|
||||
gh_token = os.environ.get("AUTOMATION_GITHUB_TOKEN", "")
|
||||
if RELEASE_THIS and gh_token:
|
||||
gh_obj = github.Github(auth=github.Auth.Token(gh_token))
|
||||
gh_obj = github.Github(gh_token)
|
||||
gh_repo = gh_obj.get_repo("sabnzbd/sabnzbd")
|
||||
|
||||
# Read the release notes
|
||||
@@ -86,7 +86,7 @@ if RELEASE_THIS and gh_token:
|
||||
for release in gh_repo.get_releases():
|
||||
if release.tag_name == RELEASE_VERSION:
|
||||
gh_release = release
|
||||
print("Found existing release %s" % gh_release.name)
|
||||
print("Found existing release %s" % gh_release.title)
|
||||
break
|
||||
else:
|
||||
# Did not find it, so create the release, use the GitHub tag we got as input
|
||||
|
||||
@@ -4,7 +4,7 @@ pyinstaller==6.16.0
|
||||
packaging==25.0
|
||||
pyinstaller-hooks-contrib==2025.9
|
||||
altgraph==0.17.4
|
||||
wrapt==2.0.0
|
||||
wrapt==1.17.3
|
||||
setuptools==80.9.0
|
||||
|
||||
# For the Windows build
|
||||
|
||||
@@ -159,16 +159,7 @@ Unicode true
|
||||
;------------------------------------------------------------------
|
||||
; Run as user-level at end of install
|
||||
Function PageFinishRun
|
||||
; Check if SABnzbd service is installed
|
||||
!insertmacro SERVICE "installed" "SABnzbd" ""
|
||||
Pop $0 ;response
|
||||
${If} $0 == true
|
||||
; Service is installed, start the service
|
||||
!insertmacro SERVICE "start" "SABnzbd" ""
|
||||
${Else}
|
||||
; Service not installed, run executable as user
|
||||
${StdUtils.ExecShellAsUser} $0 "$INSTDIR\SABnzbd.exe" "" ""
|
||||
${EndIf}
|
||||
${StdUtils.ExecShellAsUser} $0 "$INSTDIR\SABnzbd.exe" "" ""
|
||||
FunctionEnd
|
||||
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
<textarea name="notes" id="notes" rows="3" cols="50"></textarea>
|
||||
</div>
|
||||
<div class="field-pair no-field-pair-bg">
|
||||
<button class="btn btn-default addNewServer" disabled data-toggle="tooltip" data-placement="top" title="$T('wizard-test-server-required')"><span class="glyphicon glyphicon-plus"></span> $T('button-addServer')</button>
|
||||
<button class="btn btn-default addNewServer" disabled><span class="glyphicon glyphicon-plus"></span> $T('button-addServer')</button>
|
||||
<button class="btn btn-default testServer" type="button"><span class="glyphicon glyphicon-sort"></span> $T('button-testServer')</button>
|
||||
</div>
|
||||
<div class="field-pair result-box">
|
||||
@@ -464,9 +464,6 @@
|
||||
When finished loading
|
||||
**/
|
||||
jQuery(document).ready(function(){
|
||||
// Initialize tooltips
|
||||
jQuery('[data-toggle="tooltip"]').tooltip()
|
||||
|
||||
// Reload form in case we change items that make the servers appear different
|
||||
jQuery('input[name="priority"], input[name="displayname"], textarea[name="notes"]').on('change', function(event) {
|
||||
var parentForm = jQuery(event.target).parents("form")
|
||||
@@ -563,9 +560,6 @@
|
||||
// Allow adding the new server if we are in the new-server section
|
||||
if(theButton.parents("form[action='addServer']").length) {
|
||||
jQuery(".addNewServer").removeAttr("disabled")
|
||||
jQuery(".addNewServer").removeAttr("data-toggle")
|
||||
jQuery(".addNewServer").removeAttr("title")
|
||||
jQuery(".addNewServer").tooltip("destroy")
|
||||
}
|
||||
} else {
|
||||
resultBox.addClass('alert-danger')
|
||||
@@ -574,10 +568,6 @@
|
||||
// Disable the adding of new server, just to be sure
|
||||
if(theButton.parents("form[action='addServer']").length) {
|
||||
jQuery(".addNewServer").attr("disabled", "disabled")
|
||||
jQuery(".addNewServer").attr("data-toggle", "tooltip")
|
||||
jQuery(".addNewServer").attr("data-placement", "top")
|
||||
jQuery(".addNewServer").attr("title", "$T('wizard-test-server-required')")
|
||||
jQuery(".addNewServer").tooltip()
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -285,14 +285,6 @@ col2 h3 a,
|
||||
border-top-color: #E4E4E4 !important;
|
||||
}
|
||||
|
||||
.tooltip.left .tooltip-arrow {
|
||||
border-left-color: #E4E4E4 !important;
|
||||
}
|
||||
|
||||
.tooltip.right .tooltip-arrow {
|
||||
border-right-color: #E4E4E4 !important;
|
||||
}
|
||||
|
||||
.Special .glyphicon-asterisk {
|
||||
color: #E4E4E4 !important;
|
||||
}
|
||||
|
||||
@@ -52,14 +52,16 @@
|
||||
var glitterTranslate = new Object();
|
||||
glitterTranslate.paused = "$T('post-Paused')";
|
||||
glitterTranslate.left = "$T('Glitter-left')";
|
||||
glitterTranslate.clearOrphanWarning = "$T('Glitter-clearOrphanWarning')";
|
||||
glitterTranslate.clearWarn = "$T('confirm')";
|
||||
glitterTranslate.pausePromptFail = "$T('Glitter-pausePromptFail')"
|
||||
glitterTranslate.pauseFor = "$T('pauseFor')"
|
||||
glitterTranslate.minutes = "$T('mins')"
|
||||
glitterTranslate.shutdown = "$T('shutdownOK?')";
|
||||
glitterTranslate.restart = "$T('explain-Restart') $T('explain-needNewLogin')".replace(/\<br(\s*\/|)\>/g, '\n');
|
||||
glitterTranslate.repair = "$T('explain-Repair')".replace(/<br \/>/g, "\n").replace(/"/g,'"');
|
||||
glitterTranslate.confirm = "$T('confirm')";
|
||||
glitterTranslate.deleteMsg = "$T('nzo-delete')";
|
||||
glitterTranslate.removeDown = "$T('confirm')";
|
||||
glitterTranslate.removeDow1 = "$T('confirm')";
|
||||
glitterTranslate.markComplete = "$T('button-mark-completed')";
|
||||
glitterTranslate.renameAbort = "$T('Glitter-confirmAbortDirectUnpack')\n$T('confirm')";
|
||||
glitterTranslate.retryAll = "$T('link-retryAll')?";
|
||||
|
||||
@@ -895,7 +895,7 @@ function ViewModel() {
|
||||
|
||||
// Orphaned folder deletion of all
|
||||
self.removeAllOrphaned = function() {
|
||||
if (confirm(glitterTranslate.clearOrphanWarning)) {
|
||||
if (!self.confirmDeleteHistory() || confirm(glitterTranslate.clearWarn)) {
|
||||
// Show notification
|
||||
showNotification('.main-notification-box-removing-multiple', 0, self.statusInfo.folders().length)
|
||||
// Delete them all
|
||||
@@ -912,7 +912,7 @@ function ViewModel() {
|
||||
|
||||
// Orphaned folder adding of all
|
||||
self.addAllOrphaned = function() {
|
||||
if (confirm(glitterTranslate.confirm)) {
|
||||
if (!self.confirmDeleteHistory() || confirm(glitterTranslate.clearWarn)) {
|
||||
// Show notification
|
||||
showNotification('.main-notification-box-sendback')
|
||||
// Delete them all
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
<script type="text/javascript">
|
||||
var txtTestServer = "$T('wizard-server-text')";
|
||||
var txtChecking = "$T('srv-testing')";
|
||||
var txtTestRequired = "$T('wizard-test-server-required')";
|
||||
<!--#include raw $webdir + "/static/javascript/checkserver.js"#-->
|
||||
</script>
|
||||
<h3>$T('wizard-server')</h3>
|
||||
@@ -83,7 +82,7 @@
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<button id="serverTest" class="btn btn-default" data-toggle="tooltip" data-placement="left"><span class="glyphicon glyphicon-sort"></span> $T('wizard-button-testServer')</button>
|
||||
<button id="serverTest" class="btn btn-default"><span class="glyphicon glyphicon-sort"></span> $T('wizard-button-testServer')</button>
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<div id="serverResponse" class="well well-sm">$T('wizard-server-text')</div>
|
||||
|
||||
@@ -16,16 +16,9 @@ function checkRequired() {
|
||||
// Check if form is valid using HTML5 validation and if server test passed
|
||||
if ($("form").get(0).checkValidity() && serverTestSuccessful) {
|
||||
$("#next-button").removeClass('disabled')
|
||||
$("#next-button").removeAttr('data-toggle')
|
||||
$("#next-button").removeAttr('title')
|
||||
$("#next-button").tooltip('destroy')
|
||||
return true;
|
||||
} else {
|
||||
$("#next-button").addClass('disabled')
|
||||
$("#next-button").attr('data-toggle', 'tooltip')
|
||||
$("#next-button").attr('data-placement', 'left')
|
||||
$("#next-button").attr('title', txtTestRequired)
|
||||
$("#next-button").tooltip()
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,9 +30,8 @@
|
||||
<url type="faq">https://sabnzbd.org/wiki/faq</url>
|
||||
<url type="contact">https://sabnzbd.org/live-chat.html</url>
|
||||
<releases>
|
||||
<release version="4.5.5" date="2025-10-24" type="stable"/>
|
||||
<release version="4.5.4" date="2025-10-22" type="stable"/>
|
||||
<release version="4.5.3" date="2025-08-25" type="stable"/>
|
||||
<release version="4.5.4" date="2025-10-31" type="stable"/>
|
||||
<release version="4.5.3" date="2025-08-31" type="stable"/>
|
||||
<release version="4.5.2" date="2025-07-09" type="stable"/>
|
||||
<release version="4.5.1" date="2025-04-11" type="stable"/>
|
||||
<release version="4.5.0" date="2025-04-01" type="stable"/>
|
||||
|
||||
@@ -4318,10 +4318,6 @@ msgstr ""
|
||||
msgid "Retry all"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Are you sure you want to delete all folders in your Temporary Download Folder? This cannot be undone!"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Fetch NZB from URL"
|
||||
msgstr ""
|
||||
@@ -4560,11 +4556,6 @@ msgstr ""
|
||||
msgid "Start Wizard"
|
||||
msgstr ""
|
||||
|
||||
#. Tooltip for disabled Next button
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Click on Test Server before continuing"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Restore backup"
|
||||
msgstr ""
|
||||
|
||||
@@ -4535,12 +4535,6 @@ msgstr ""
|
||||
msgid "Retry all"
|
||||
msgstr "Opakovat vše"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Are you sure you want to delete all folders in your Temporary Download "
|
||||
"Folder? This cannot be undone!"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Fetch NZB from URL"
|
||||
msgstr "Získat NZB z URL"
|
||||
@@ -4787,11 +4781,6 @@ msgstr ""
|
||||
msgid "Start Wizard"
|
||||
msgstr ""
|
||||
|
||||
#. Tooltip for disabled Next button
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Click on Test Server before continuing"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Restore backup"
|
||||
msgstr ""
|
||||
|
||||
@@ -4685,12 +4685,6 @@ msgstr "Fjern alle"
|
||||
msgid "Retry all"
|
||||
msgstr "Prøv igen alle"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Are you sure you want to delete all folders in your Temporary Download "
|
||||
"Folder? This cannot be undone!"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Fetch NZB from URL"
|
||||
msgstr "Hent NZB fra URL"
|
||||
@@ -4941,11 +4935,6 @@ msgstr "Afslut SABnzbd"
|
||||
msgid "Start Wizard"
|
||||
msgstr "Start guide"
|
||||
|
||||
#. Tooltip for disabled Next button
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Click on Test Server before continuing"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Restore backup"
|
||||
msgstr ""
|
||||
|
||||
@@ -4851,12 +4851,6 @@ msgstr "Alle löschen"
|
||||
msgid "Retry all"
|
||||
msgstr "Alle wiederholen"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Are you sure you want to delete all folders in your Temporary Download "
|
||||
"Folder? This cannot be undone!"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Fetch NZB from URL"
|
||||
msgstr "NZB aus URL laden"
|
||||
@@ -5112,11 +5106,6 @@ msgstr "SABnzbd beenden"
|
||||
msgid "Start Wizard"
|
||||
msgstr "Assistenten starten"
|
||||
|
||||
#. Tooltip for disabled Next button
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Click on Test Server before continuing"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Restore backup"
|
||||
msgstr "Backup wiederherstellen"
|
||||
|
||||
@@ -4823,12 +4823,6 @@ msgstr "Eliminar todo"
|
||||
msgid "Retry all"
|
||||
msgstr "Re-intentar todo"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Are you sure you want to delete all folders in your Temporary Download "
|
||||
"Folder? This cannot be undone!"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Fetch NZB from URL"
|
||||
msgstr "Descargar NZB desde URL"
|
||||
@@ -5084,11 +5078,6 @@ msgstr "Salir SABnzbd"
|
||||
msgid "Start Wizard"
|
||||
msgstr "Iniciar Asistente"
|
||||
|
||||
#. Tooltip for disabled Next button
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Click on Test Server before continuing"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Restore backup"
|
||||
msgstr "Restaurar copia de seguridad"
|
||||
|
||||
@@ -4642,12 +4642,6 @@ msgstr "Poista kaikki"
|
||||
msgid "Retry all"
|
||||
msgstr "Yritä uudelleen kaikki"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Are you sure you want to delete all folders in your Temporary Download "
|
||||
"Folder? This cannot be undone!"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Fetch NZB from URL"
|
||||
msgstr "Nouda NZB osoitteesta"
|
||||
@@ -4900,11 +4894,6 @@ msgstr "Poistu SABnzbd:stä"
|
||||
msgid "Start Wizard"
|
||||
msgstr "Käynnistä velho"
|
||||
|
||||
#. Tooltip for disabled Next button
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Click on Test Server before continuing"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Restore backup"
|
||||
msgstr ""
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
# Copyright 2007-2025 by The SABnzbd-Team (sabnzbd.org)
|
||||
#
|
||||
# Translators:
|
||||
# Safihre <safihre@sabnzbd.org>, 2025
|
||||
# Fred L <88com88@gmail.com>, 2025
|
||||
# Safihre <safihre@sabnzbd.org>, 2025
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-4.6.0\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Fred L <88com88@gmail.com>, 2025\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2025\n"
|
||||
"Language-Team: French (https://app.transifex.com/sabnzbd/teams/111101/fr/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -378,11 +378,11 @@ msgstr "Quota"
|
||||
|
||||
#: sabnzbd/bpsmeter.py
|
||||
msgid "Quota limit warning (%d%%)"
|
||||
msgstr "Avertissement de limite de quota (%d%%)"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/bpsmeter.py
|
||||
msgid "Downloading resumed after quota reset"
|
||||
msgstr "Le téléchargement a repris après la réinitialisation du quota."
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/cfg.py, sabnzbd/interface.py
|
||||
msgid "Incorrect parameter"
|
||||
@@ -3842,9 +3842,6 @@ msgid ""
|
||||
" follow with K,M,G.<br />Checked every few minutes. Notification is sent "
|
||||
"when quota is spent."
|
||||
msgstr ""
|
||||
"Quota pour ce serveur, calculé à partir du moment où il est défini. En "
|
||||
"octets, suivi éventuellement de K,M,G.<br />Vérifié toutes les quelques "
|
||||
"minutes. Une notification est envoyée lorsque le quota est atteint."
|
||||
|
||||
#. Server's retention time in days
|
||||
#: sabnzbd/skintext.py
|
||||
@@ -4838,14 +4835,6 @@ msgstr "Tout supprimer"
|
||||
msgid "Retry all"
|
||||
msgstr "Réessayer tous"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Are you sure you want to delete all folders in your Temporary Download "
|
||||
"Folder? This cannot be undone!"
|
||||
msgstr ""
|
||||
"Êtes-vous sûr de vouloir supprimer tous les dossiers de votre Dossier de "
|
||||
"Téléchargement Temporaire ? Cette opération ne peut pas être annulée !"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Fetch NZB from URL"
|
||||
msgstr "Importer le NZB depuis l'URL"
|
||||
@@ -5104,11 +5093,6 @@ msgstr "Quitter SABnzbd"
|
||||
msgid "Start Wizard"
|
||||
msgstr "Lancer l'assistant"
|
||||
|
||||
#. Tooltip for disabled Next button
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Click on Test Server before continuing"
|
||||
msgstr "Cliquez sur Tester le Serveur avant de continuer"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Restore backup"
|
||||
msgstr "Restaurer la sauvegarde"
|
||||
|
||||
@@ -4650,12 +4650,6 @@ msgstr "מחק הכל"
|
||||
msgid "Retry all"
|
||||
msgstr "נסה שוב הכל"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Are you sure you want to delete all folders in your Temporary Download "
|
||||
"Folder? This cannot be undone!"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Fetch NZB from URL"
|
||||
msgstr "משוך NZB מכתובת"
|
||||
@@ -4910,11 +4904,6 @@ msgstr "צא מן SABnzbd"
|
||||
msgid "Start Wizard"
|
||||
msgstr "התחל אשף"
|
||||
|
||||
#. Tooltip for disabled Next button
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Click on Test Server before continuing"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Restore backup"
|
||||
msgstr "שחזר גיבוי"
|
||||
|
||||
@@ -4787,12 +4787,6 @@ msgstr "Elimina tutto"
|
||||
msgid "Retry all"
|
||||
msgstr "Riprova tutto"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Are you sure you want to delete all folders in your Temporary Download "
|
||||
"Folder? This cannot be undone!"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Fetch NZB from URL"
|
||||
msgstr "Recupera NZB da URL"
|
||||
@@ -5049,11 +5043,6 @@ msgstr "Esci da SABnzbd"
|
||||
msgid "Start Wizard"
|
||||
msgstr "Avvia procedura guidata"
|
||||
|
||||
#. Tooltip for disabled Next button
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Click on Test Server before continuing"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Restore backup"
|
||||
msgstr "Ripristina backup"
|
||||
|
||||
@@ -4616,12 +4616,6 @@ msgstr "Ta bort alle"
|
||||
msgid "Retry all"
|
||||
msgstr "Prøv alle på nytt"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Are you sure you want to delete all folders in your Temporary Download "
|
||||
"Folder? This cannot be undone!"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Fetch NZB from URL"
|
||||
msgstr "Hent NZB fra URL"
|
||||
@@ -4872,11 +4866,6 @@ msgstr "Avslutt SABnzbd"
|
||||
msgid "Start Wizard"
|
||||
msgstr "Start Veiviser"
|
||||
|
||||
#. Tooltip for disabled Next button
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Click on Test Server before continuing"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Restore backup"
|
||||
msgstr ""
|
||||
|
||||
@@ -4784,12 +4784,6 @@ msgstr "Alles wissen"
|
||||
msgid "Retry all"
|
||||
msgstr "Alles opnieuw proberen"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Are you sure you want to delete all folders in your Temporary Download "
|
||||
"Folder? This cannot be undone!"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Fetch NZB from URL"
|
||||
msgstr "Haal NZB op via URL"
|
||||
@@ -5045,11 +5039,6 @@ msgstr "Stop SABnzbd"
|
||||
msgid "Start Wizard"
|
||||
msgstr "Wizard starten"
|
||||
|
||||
#. Tooltip for disabled Next button
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Click on Test Server before continuing"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Restore backup"
|
||||
msgstr "Backup herstellen"
|
||||
|
||||
@@ -4628,12 +4628,6 @@ msgstr "Usuń wszystko"
|
||||
msgid "Retry all"
|
||||
msgstr "Ponów wszystkie"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Are you sure you want to delete all folders in your Temporary Download "
|
||||
"Folder? This cannot be undone!"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Fetch NZB from URL"
|
||||
msgstr "Pobierz NZB z URL"
|
||||
@@ -4882,11 +4876,6 @@ msgstr "Wyjście z SABnzbd"
|
||||
msgid "Start Wizard"
|
||||
msgstr "Uruchom kreatora konfiguracji"
|
||||
|
||||
#. Tooltip for disabled Next button
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Click on Test Server before continuing"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Restore backup"
|
||||
msgstr ""
|
||||
|
||||
@@ -4639,12 +4639,6 @@ msgstr "Excluir Todos"
|
||||
msgid "Retry all"
|
||||
msgstr "Repetir todos"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Are you sure you want to delete all folders in your Temporary Download "
|
||||
"Folder? This cannot be undone!"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Fetch NZB from URL"
|
||||
msgstr "Buscar NZB de uma URL"
|
||||
@@ -4893,11 +4887,6 @@ msgstr "Sair do SABnzbd"
|
||||
msgid "Start Wizard"
|
||||
msgstr "Iniciar o Assistente"
|
||||
|
||||
#. Tooltip for disabled Next button
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Click on Test Server before continuing"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Restore backup"
|
||||
msgstr ""
|
||||
|
||||
@@ -4658,12 +4658,6 @@ msgstr "Șterge tot"
|
||||
msgid "Retry all"
|
||||
msgstr "Reîncearcă toate"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Are you sure you want to delete all folders in your Temporary Download "
|
||||
"Folder? This cannot be undone!"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Fetch NZB from URL"
|
||||
msgstr "Descarcă NZB din URL"
|
||||
@@ -4915,11 +4909,6 @@ msgstr "Închide SABnzbd"
|
||||
msgid "Start Wizard"
|
||||
msgstr "Porneşte Vrăjitor"
|
||||
|
||||
#. Tooltip for disabled Next button
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Click on Test Server before continuing"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Restore backup"
|
||||
msgstr ""
|
||||
|
||||
@@ -4622,12 +4622,6 @@ msgstr "Удалить всё"
|
||||
msgid "Retry all"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Are you sure you want to delete all folders in your Temporary Download "
|
||||
"Folder? This cannot be undone!"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Fetch NZB from URL"
|
||||
msgstr ""
|
||||
@@ -4878,11 +4872,6 @@ msgstr ""
|
||||
msgid "Start Wizard"
|
||||
msgstr ""
|
||||
|
||||
#. Tooltip for disabled Next button
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Click on Test Server before continuing"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Restore backup"
|
||||
msgstr ""
|
||||
|
||||
@@ -4601,12 +4601,6 @@ msgstr "Избриши све"
|
||||
msgid "Retry all"
|
||||
msgstr "Ponovo pokušaj sve"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Are you sure you want to delete all folders in your Temporary Download "
|
||||
"Folder? This cannot be undone!"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Fetch NZB from URL"
|
||||
msgstr "Povuci NZB sa URL"
|
||||
@@ -4855,11 +4849,6 @@ msgstr "Затвори SABnzbd"
|
||||
msgid "Start Wizard"
|
||||
msgstr "Покрени чаробњака"
|
||||
|
||||
#. Tooltip for disabled Next button
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Click on Test Server before continuing"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Restore backup"
|
||||
msgstr ""
|
||||
|
||||
@@ -4613,12 +4613,6 @@ msgstr "Ta bort alla"
|
||||
msgid "Retry all"
|
||||
msgstr "Starta om alla"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Are you sure you want to delete all folders in your Temporary Download "
|
||||
"Folder? This cannot be undone!"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Fetch NZB from URL"
|
||||
msgstr "Hämta NZB från URL"
|
||||
@@ -4869,11 +4863,6 @@ msgstr "Avsluta SABnzbd"
|
||||
msgid "Start Wizard"
|
||||
msgstr "Starta guide"
|
||||
|
||||
#. Tooltip for disabled Next button
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Click on Test Server before continuing"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Restore backup"
|
||||
msgstr ""
|
||||
|
||||
@@ -370,11 +370,11 @@ msgstr "Kota"
|
||||
|
||||
#: sabnzbd/bpsmeter.py
|
||||
msgid "Quota limit warning (%d%%)"
|
||||
msgstr "Kota sınır ikazı (%d%%)"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/bpsmeter.py
|
||||
msgid "Downloading resumed after quota reset"
|
||||
msgstr "İndirme kota sıfırlamasının ardından devam etti"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/cfg.py, sabnzbd/interface.py
|
||||
msgid "Incorrect parameter"
|
||||
@@ -3786,10 +3786,6 @@ msgid ""
|
||||
" follow with K,M,G.<br />Checked every few minutes. Notification is sent "
|
||||
"when quota is spent."
|
||||
msgstr ""
|
||||
"Bu sunucu için, ayarlandığı zamandan itibaren hesaplanan kota. Bayt olarak, "
|
||||
"seçime dayalı bir şekilde K, M, G takip edebilir. <br /> Her birkaç "
|
||||
"dakikada bir kontrol edilir. Kota sonuna ulaşıldığında bir bildirim "
|
||||
"gönderilir."
|
||||
|
||||
#. Server's retention time in days
|
||||
#: sabnzbd/skintext.py
|
||||
@@ -4780,14 +4776,6 @@ msgstr "Tümünü Sil"
|
||||
msgid "Retry all"
|
||||
msgstr "Tümünü tekrar dene"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Are you sure you want to delete all folders in your Temporary Download "
|
||||
"Folder? This cannot be undone!"
|
||||
msgstr ""
|
||||
"Geçici İndirme Dizini'ndeki tüm dizinleri silmek istediğinizden emin "
|
||||
"misiniz? Bu geri alınamaz!"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Fetch NZB from URL"
|
||||
msgstr "URL konumundan NZB al"
|
||||
@@ -5044,11 +5032,6 @@ msgstr "SABnzb'den çık"
|
||||
msgid "Start Wizard"
|
||||
msgstr "Sihirbazı Başlat"
|
||||
|
||||
#. Tooltip for disabled Next button
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Click on Test Server before continuing"
|
||||
msgstr "Devam etmeden evvel Sunucuyu Dene unsuruna tıklayın"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Restore backup"
|
||||
msgstr "Yedeklemeyi geri getir"
|
||||
|
||||
@@ -4553,12 +4553,6 @@ msgstr "全部删除"
|
||||
msgid "Retry all"
|
||||
msgstr "全部重试"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid ""
|
||||
"Are you sure you want to delete all folders in your Temporary Download "
|
||||
"Folder? This cannot be undone!"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Fetch NZB from URL"
|
||||
msgstr "从 URL 装取 NZB"
|
||||
@@ -4805,11 +4799,6 @@ msgstr "退出 SABnzbd"
|
||||
msgid "Start Wizard"
|
||||
msgstr "启动向导"
|
||||
|
||||
#. Tooltip for disabled Next button
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Click on Test Server before continuing"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Restore backup"
|
||||
msgstr ""
|
||||
|
||||
@@ -32,7 +32,7 @@ rebulk==3.2.0
|
||||
|
||||
# Recent cryptography versions require Rust. If you run into issues compiling this
|
||||
# SABnzbd will also work with older pre-Rust versions such as cryptography==3.3.2
|
||||
cryptography==46.0.3
|
||||
cryptography==46.0.2
|
||||
|
||||
# We recommend using "orjson" as it is 2x as fast as "ujson". However, it requires
|
||||
# Rust so SABnzbd works just as well with "ujson" or the Python built in "json" module
|
||||
@@ -50,8 +50,8 @@ winrt-Windows.UI.Notifications==3.2.1; sys_platform == 'win32'
|
||||
typing_extensions==4.15.0; sys_platform == 'win32'
|
||||
|
||||
# macOS system calls
|
||||
pyobjc-core==12.0; sys_platform == 'darwin'
|
||||
pyobjc-framework-Cocoa==12.0; sys_platform == 'darwin'
|
||||
pyobjc-core==11.1; sys_platform == 'darwin'
|
||||
pyobjc-framework-Cocoa==11.1; sys_platform == 'darwin'
|
||||
|
||||
# Linux notifications
|
||||
notify2==0.3.1; sys_platform != 'win32' and sys_platform != 'darwin'
|
||||
@@ -64,8 +64,8 @@ markdown==3.9
|
||||
paho-mqtt==1.6.1 # Pinned, newer versions don't work with AppRise yet
|
||||
|
||||
# Requests Requirements
|
||||
charset_normalizer==3.4.4
|
||||
idna==3.11
|
||||
charset_normalizer==3.4.3
|
||||
idna==3.10
|
||||
urllib3==2.5.0
|
||||
certifi==2025.10.5
|
||||
oauthlib==3.3.1
|
||||
|
||||
0
sabnzbd/deobfuscate_filenames.py
Executable file → Normal file
0
sabnzbd/deobfuscate_filenames.py
Executable file → Normal file
@@ -194,10 +194,9 @@ def parse_par2_file(fname: str, md5of16k: Dict[bytes, str]) -> Tuple[str, Dict[s
|
||||
for i in range(48, pack_len - 32, 20):
|
||||
filecrc32[fileid].append(struct.unpack("<I", data[i + 16 : i + 20])[0])
|
||||
|
||||
# On large files, we stop after seeing all the listings and have crc32 data for all listings
|
||||
# Our unit-tests do not include large par2 files, so we cannot verify cases like #3164!
|
||||
# On large files, we stop after seeing all the listings
|
||||
# On smaller files, we scan them fully to get the par2-creator
|
||||
if total_size > SCAN_LIMIT and len(filepar2info) == nr_files == len(filecrc32):
|
||||
if total_size > SCAN_LIMIT and len(filepar2info) == nr_files:
|
||||
break
|
||||
|
||||
# Process all the data
|
||||
|
||||
@@ -488,7 +488,7 @@ def process_job(nzo: NzbObject) -> bool:
|
||||
|
||||
if all_ok:
|
||||
# Remove files matching the cleanup list
|
||||
cleanup_list(tmp_workdir_complete, skip_nzb=True)
|
||||
newfiles = cleanup_list(newfiles, skip_nzb=True)
|
||||
|
||||
# Check if this is an NZB-only download, if so redirect to queue
|
||||
# except when PP was Download-only
|
||||
@@ -501,7 +501,7 @@ def process_job(nzo: NzbObject) -> bool:
|
||||
cleanup_empty_directories(tmp_workdir_complete)
|
||||
else:
|
||||
# Full cleanup including nzb's
|
||||
cleanup_list(tmp_workdir_complete, skip_nzb=False)
|
||||
newfiles = cleanup_list(newfiles, skip_nzb=False)
|
||||
|
||||
script_ret = 0
|
||||
script_error = False
|
||||
@@ -536,7 +536,7 @@ def process_job(nzo: NzbObject) -> bool:
|
||||
# TV/Movie/Date Renaming code part 2 - rename and move files to parent folder
|
||||
if all_ok and file_sorter.sorter_active:
|
||||
if newfiles:
|
||||
workdir_complete, ok = file_sorter.rename(newfiles, workdir_complete)
|
||||
workdir_complete, ok, newfiles = file_sorter.rename(newfiles, workdir_complete)
|
||||
if not ok:
|
||||
nzo.set_unpack_info("Unpack", T("Failed to move files"))
|
||||
nzo.fail_msg = T("Failed to move files")
|
||||
@@ -607,9 +607,9 @@ def process_job(nzo: NzbObject) -> bool:
|
||||
unique=True,
|
||||
)
|
||||
|
||||
# Cleanup again, including NZB files
|
||||
# Cleanup again, any changes made by the script will not be handled
|
||||
if all_ok and os.path.isdir(workdir_complete):
|
||||
cleanup_list(workdir_complete, False)
|
||||
newfiles = cleanup_list(newfiles, False)
|
||||
|
||||
# Force error for empty result
|
||||
all_ok = all_ok and not empty
|
||||
@@ -1101,27 +1101,34 @@ def handle_empty_queue():
|
||||
sabnzbd.LIBC.malloc_trim(0)
|
||||
|
||||
|
||||
def cleanup_list(wdir: str, skip_nzb: bool):
|
||||
def cleanup_list(file_paths: List[str], skip_nzb: bool) -> List[str]:
|
||||
"""Remove all files whose extension matches the cleanup list,
|
||||
optionally ignoring the nzb extension
|
||||
optionally ignoring the nzb extension.
|
||||
Returns the updated list of files (excluding removed files).
|
||||
"""
|
||||
if cfg.cleanup_list():
|
||||
try:
|
||||
with os.scandir(wdir) as files:
|
||||
for entry in files:
|
||||
if entry.is_dir():
|
||||
cleanup_list(entry.path, skip_nzb)
|
||||
cleanup_empty_directories(entry.path)
|
||||
else:
|
||||
if on_cleanup_list(entry.name, skip_nzb):
|
||||
try:
|
||||
logging.info("Removing unwanted file %s", entry.path)
|
||||
remove_file(entry.path)
|
||||
except Exception:
|
||||
logging.error(T("Removing %s failed"), clip_path(entry.path))
|
||||
logging.info("Traceback: ", exc_info=True)
|
||||
except Exception:
|
||||
logging.info("Traceback: ", exc_info=True)
|
||||
if not cfg.cleanup_list():
|
||||
return file_paths
|
||||
|
||||
logging.info("Checking for extensions to clean up: %s", cfg.cleanup_list.get_string())
|
||||
|
||||
remaining_files = []
|
||||
for file_path in file_paths:
|
||||
filename = os.path.basename(file_path)
|
||||
if on_cleanup_list(filename, skip_nzb):
|
||||
try:
|
||||
logging.info("Removing unwanted file %s", file_path)
|
||||
remove_file(file_path)
|
||||
# File was removed, don't add to remaining_files
|
||||
except Exception:
|
||||
logging.error(T("Removing %s failed"), clip_path(file_path))
|
||||
logging.info("Traceback: ", exc_info=True)
|
||||
# File removal failed, keep it in the list
|
||||
remaining_files.append(file_path)
|
||||
else:
|
||||
# File not on cleanup list, keep it
|
||||
remaining_files.append(file_path)
|
||||
|
||||
return remaining_files
|
||||
|
||||
|
||||
def prefix(path: str, pre: str) -> str:
|
||||
@@ -1274,6 +1281,7 @@ def del_marker(path: str):
|
||||
|
||||
|
||||
def remove_from_list(name: Optional[str], lst: List[str]):
|
||||
"""Removes item from list, modifies list in place"""
|
||||
if name:
|
||||
for n in range(len(lst)):
|
||||
if lst[n].endswith(name):
|
||||
|
||||
@@ -840,9 +840,6 @@ SKIN_TEXT = {
|
||||
"Glitter-backToQueue": TT("Send back to queue"),
|
||||
"Glitter-purgeOrphaned": TT("Delete All"),
|
||||
"Glitter-retryAllOrphaned": TT("Retry all"),
|
||||
"Glitter-clearOrphanWarning": TT(
|
||||
"Are you sure you want to delete all folders in your Temporary Download Folder? This cannot be undone!"
|
||||
),
|
||||
"Glitter-deleteJobAndFolders": TT("Remove NZB & Delete Files"),
|
||||
"Glitter-addFromURL": TT("Fetch NZB from URL"),
|
||||
"Glitter-addFromFile": TT("Upload NZB"),
|
||||
@@ -919,7 +916,6 @@ SKIN_TEXT = {
|
||||
"wizard-goto": TT("Go to SABnzbd"), #: Wizard step
|
||||
"wizard-exit": TT("Exit SABnzbd"), #: Wizard EXIT button on first page
|
||||
"wizard-start": TT("Start Wizard"), #: Wizard START button on first page
|
||||
"wizard-test-server-required": TT("Click on Test Server before continuing"), #: Tooltip for disabled Next button
|
||||
"restore-backup": TT("Restore backup"),
|
||||
# Special
|
||||
"yourRights": TT(
|
||||
|
||||
@@ -501,6 +501,39 @@ class Sorter:
|
||||
logging.info("Traceback: ", exc_info=True)
|
||||
return success
|
||||
|
||||
def _update_files_after_renames(self, base_path: str, original_files: List[str]) -> List[str]:
|
||||
"""Update files list to reflect any renames that may have occurred in the base_path"""
|
||||
updated_files = []
|
||||
renamed_files = set() # Track files that no longer exist at their original paths
|
||||
|
||||
for file_path in original_files:
|
||||
# Convert to absolute path for checking
|
||||
if os.path.isabs(file_path):
|
||||
abs_file_path = file_path
|
||||
else:
|
||||
abs_file_path = os.path.join(base_path, file_path)
|
||||
abs_file_path = os.path.normpath(abs_file_path)
|
||||
|
||||
# If the original file still exists, keep it
|
||||
if os.path.exists(abs_file_path):
|
||||
updated_files.append(file_path)
|
||||
else:
|
||||
renamed_files.add(os.path.basename(file_path))
|
||||
|
||||
# If any files were renamed, add all current files in the base_path (excluding originals)
|
||||
if renamed_files:
|
||||
try:
|
||||
for item in os.listdir(base_path):
|
||||
item_path = os.path.join(base_path, item)
|
||||
if os.path.isfile(item_path) and item not in renamed_files:
|
||||
# Only add if not already in the list (to avoid duplicates)
|
||||
if item_path not in updated_files:
|
||||
updated_files.append(item_path)
|
||||
except (OSError, FileNotFoundError):
|
||||
pass
|
||||
|
||||
return updated_files
|
||||
|
||||
def _to_filepath(self, f: str, base_path: str) -> str:
|
||||
if not is_full_path(f):
|
||||
f = os.path.join(base_path, f)
|
||||
@@ -515,23 +548,24 @@ class Sorter:
|
||||
and os.stat(filepath).st_size >= self.rename_limit
|
||||
)
|
||||
|
||||
def rename(self, files: List[str], base_path: str) -> Tuple[str, bool]:
|
||||
def rename(self, files: List[str], base_path: str) -> Tuple[str, bool, List[str]]:
|
||||
if not self.rename_files:
|
||||
return move_to_parent_directory(base_path)
|
||||
return move_to_parent_directory(base_path, files)
|
||||
|
||||
# Log the minimum filesize for renaming
|
||||
if self.rename_limit > 0:
|
||||
logging.debug("Minimum filesize for renaming set to %s bytes", self.rename_limit)
|
||||
|
||||
# Store the list of all files for later use
|
||||
all_files = files
|
||||
all_files = files[:]
|
||||
updated_files = files[:]
|
||||
|
||||
# Filter files to remove nonexistent, undersized, samples, and excluded extensions
|
||||
files = [f for f in files if self._filter_files(f, base_path)]
|
||||
|
||||
if len(files) == 0:
|
||||
logging.debug("No files left to rename after applying filter")
|
||||
return move_to_parent_directory(base_path)
|
||||
return move_to_parent_directory(base_path, updated_files)
|
||||
|
||||
# Check for season packs or sequential filenames and handle their renaming separately;
|
||||
# if neither applies or succeeds, fall back to going with the single largest file instead.
|
||||
@@ -541,7 +575,9 @@ class Sorter:
|
||||
logging.debug("Trying to rename season pack files %s", files)
|
||||
if self._rename_season_pack(files, base_path, all_files):
|
||||
cleanup_empty_directories(base_path)
|
||||
return move_to_parent_directory(base_path)
|
||||
# Update the files list to reflect any renames that happened
|
||||
updated_files = self._update_files_after_renames(base_path, updated_files)
|
||||
return move_to_parent_directory(base_path, updated_files)
|
||||
else:
|
||||
logging.debug("Season pack sorting didn´t rename any files")
|
||||
|
||||
@@ -550,7 +586,9 @@ class Sorter:
|
||||
logging.debug("Trying to rename sequential files %s", sequential_files)
|
||||
if self._rename_sequential(sequential_files, base_path):
|
||||
cleanup_empty_directories(base_path)
|
||||
return move_to_parent_directory(base_path)
|
||||
# Update the files list to reflect any renames that happened
|
||||
updated_files = self._update_files_after_renames(base_path, updated_files)
|
||||
return move_to_parent_directory(base_path, updated_files)
|
||||
else:
|
||||
logging.debug("Sequential file handling didn't rename any files")
|
||||
|
||||
@@ -575,14 +613,16 @@ class Sorter:
|
||||
renamer(filepath, new_filepath)
|
||||
renamed_files.append(new_filepath)
|
||||
except Exception:
|
||||
logging.error(T("Failed to rename %s to %s"), clip_path(base_path), clip_path(new_filepath))
|
||||
logging.error(T("Failed to rename %s to %s"), clip_path(filepath), clip_path(new_filepath))
|
||||
logging.info("Traceback: ", exc_info=True)
|
||||
|
||||
rename_similar(base_path, f_ext, self.filename_set, renamed_files)
|
||||
else:
|
||||
logging.debug("Cannot rename %s, new path %s already exists.", largest_file.get("name"), new_filepath)
|
||||
|
||||
return move_to_parent_directory(base_path)
|
||||
# Update the files list to reflect any renames that happened
|
||||
updated_files = self._update_files_after_renames(base_path, updated_files)
|
||||
return move_to_parent_directory(base_path, updated_files)
|
||||
|
||||
|
||||
class BasicAnalyzer(Sorter):
|
||||
@@ -607,29 +647,55 @@ def ends_in_file(path: str) -> bool:
|
||||
return bool(RE_ENDEXT.search(path) or RE_ENDFN.search(path))
|
||||
|
||||
|
||||
def move_to_parent_directory(workdir: str) -> Tuple[str, bool]:
|
||||
"""Move all files under 'workdir' into 'workdir/..'"""
|
||||
# Determine 'folder'/..
|
||||
def move_to_parent_directory(workdir: str, files: List[str]) -> Tuple[str, bool, List[str]]:
|
||||
"""Move specified files from workdir to workdir's parent directory and track file movements"""
|
||||
if not files:
|
||||
return workdir, True, []
|
||||
|
||||
# Determine 'workdir/..' as destination
|
||||
workdir = os.path.abspath(os.path.normpath(workdir))
|
||||
dest = os.path.abspath(os.path.normpath(os.path.join(workdir, "..")))
|
||||
|
||||
logging.debug("Moving files from %s to parent directory: %s", workdir, dest)
|
||||
|
||||
logging.debug("Moving all files from %s to %s", workdir, dest)
|
||||
updated_files = []
|
||||
|
||||
# Check for DVD folders and bail out if found
|
||||
for item in os.listdir(workdir):
|
||||
if item.lower() in IGNORED_MOVIE_FOLDERS:
|
||||
return workdir, True
|
||||
try:
|
||||
for item in os.listdir(workdir):
|
||||
if os.path.isdir(os.path.join(workdir, item)) and item.lower() in IGNORED_MOVIE_FOLDERS:
|
||||
return workdir, True, files
|
||||
except (OSError, FileNotFoundError):
|
||||
# Skip directory listing if directory doesn't exist
|
||||
pass
|
||||
|
||||
for root, dirs, files in os.walk(workdir):
|
||||
for _file in files:
|
||||
path = os.path.join(root, _file)
|
||||
new_path = path.replace(workdir, dest)
|
||||
ok, new_path = move_to_path(path, new_path)
|
||||
if not ok:
|
||||
return dest, False
|
||||
# Move each file to the parent directory
|
||||
for file_path in files:
|
||||
# Convert relative paths to absolute paths within workdir
|
||||
if os.path.isabs(file_path):
|
||||
abs_file_path = file_path
|
||||
else:
|
||||
abs_file_path = os.path.join(workdir, file_path)
|
||||
abs_file_path = os.path.normpath(abs_file_path)
|
||||
|
||||
if not os.path.exists(abs_file_path):
|
||||
# Skip files that don't exist
|
||||
continue
|
||||
|
||||
filename = os.path.basename(abs_file_path)
|
||||
new_path = os.path.join(dest, filename)
|
||||
|
||||
ok, new_path = move_to_path(abs_file_path, new_path)
|
||||
if not ok:
|
||||
return dest, False, files
|
||||
# Track this file as it was moved
|
||||
updated_files.append(new_path)
|
||||
|
||||
# Clean up empty directories in the workdir
|
||||
cleanup_empty_directories(workdir)
|
||||
return dest, True
|
||||
|
||||
# Return the parent directory and list of files that were actually moved
|
||||
return dest, True, updated_files
|
||||
|
||||
|
||||
def guess_what(name: str) -> MatchesDict:
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
# You MUST use double quotes (so " and not ')
|
||||
# Do not forget to update the appdata file for every major release!
|
||||
|
||||
__version__ = "4.5.5"
|
||||
__baseline__ = "a61a5539a7e0e0dc1f9ae140222436ba8f9fe679"
|
||||
__version__ = "4.6.0-dev"
|
||||
__baseline__ = "unknown"
|
||||
|
||||
@@ -10,7 +10,7 @@ pytest-httpserver
|
||||
flaky
|
||||
xmltodict
|
||||
tavern
|
||||
tavern==3.0.0; python_version >= '3.11' # Latest version only supported on Python 3.11 and above
|
||||
tavern==3.0.0a9; python_version >= '3.11' # Latest version only supported on Python 3.11 and above
|
||||
flask
|
||||
tavalidate
|
||||
importlib_metadata
|
||||
|
||||
@@ -351,13 +351,15 @@ class TestSortingFunctions:
|
||||
ffs.fs.create_file(base_dir + "/" + test_file, int("0644", 8))
|
||||
assert os.path.exists(base_dir + "/" + test_file) is True
|
||||
|
||||
return_path, return_status = sorting.move_to_parent_directory(base_dir + "/TEST")
|
||||
# Create the file list to move
|
||||
files_to_move = [base_dir + "/TEST/DIR/FILE"]
|
||||
return_path, return_status, return_files = sorting.move_to_parent_directory(base_dir + "/TEST", files_to_move)
|
||||
|
||||
# Affected by move
|
||||
assert not os.path.exists(base_dir + "/TEST/DIR/FILE") # Moved to subdir
|
||||
assert not os.path.exists(base_dir + "/TEST/DIR2") # Deleted empty directory
|
||||
assert not os.path.exists(base_dir + "/DIR2") # Dirs don't get moved, only their file content
|
||||
assert os.path.exists(base_dir + "/DIR/FILE") # Moved file
|
||||
assert os.path.exists(base_dir + "/FILE") # Moved file
|
||||
# Not moved
|
||||
assert not os.path.exists(base_dir + "/some.file")
|
||||
assert not os.path.exists(base_dir + "/2")
|
||||
@@ -366,6 +368,8 @@ class TestSortingFunctions:
|
||||
# Function return values
|
||||
assert (return_path) == base_dir
|
||||
assert (return_status) is True
|
||||
assert len(return_files) == 1
|
||||
assert return_files[0] == base_dir + "/FILE"
|
||||
|
||||
# Exception for DVD directories
|
||||
with pyfakefs.fake_filesystem_unittest.Patcher() as ffs:
|
||||
@@ -380,13 +384,15 @@ class TestSortingFunctions:
|
||||
ffs.fs.create_file(base_dir + "/" + test_file, int("0644", 8))
|
||||
assert os.path.exists(base_dir + "/" + test_file) is True
|
||||
|
||||
return_path, return_status = sorting.move_to_parent_directory(base_dir + "/TEST")
|
||||
# Create the file list to move (includes file in DVD directory)
|
||||
files_to_move = [base_dir + "/TEST/" + dvd + "/FILE"]
|
||||
return_path, return_status, return_files = sorting.move_to_parent_directory(base_dir + "/TEST", files_to_move)
|
||||
|
||||
# Nothing should move in the presence of a DVD directory structure
|
||||
assert os.path.exists(base_dir + "/TEST/" + dvd + "/FILE")
|
||||
assert os.path.exists(base_dir + "/TEST/DIR2")
|
||||
assert not os.path.exists(base_dir + "/DIR2")
|
||||
assert not os.path.exists(base_dir + "/DIR/FILE")
|
||||
assert not os.path.exists(base_dir + "/FILE")
|
||||
assert not os.path.exists(base_dir + "/some.file")
|
||||
assert not os.path.exists(base_dir + "/2")
|
||||
assert os.path.exists(base_dir + "/dir/some.file")
|
||||
@@ -394,6 +400,8 @@ class TestSortingFunctions:
|
||||
# Function return values
|
||||
assert (return_path) == base_dir + "/TEST"
|
||||
assert (return_status) is True
|
||||
# Files should be returned as-is when DVD structure prevents moving
|
||||
assert return_files == files_to_move
|
||||
|
||||
@pytest.mark.skipif(not sys.platform.startswith("win"), reason="Windows tests")
|
||||
def test_move_to_parent_directory_win(self):
|
||||
@@ -409,13 +417,15 @@ class TestSortingFunctions:
|
||||
ffs.fs.create_file(base_dir + "\\" + test_file, int("0644", 8))
|
||||
assert os.path.exists(base_dir + "\\" + test_file) is True
|
||||
|
||||
return_path, return_status = sorting.move_to_parent_directory(base_dir + "\\TEST")
|
||||
# Create the file list to move
|
||||
files_to_move = [base_dir + "\\TEST\\DIR\\FILE"]
|
||||
return_path, return_status, return_files = sorting.move_to_parent_directory(base_dir + "\\TEST", files_to_move)
|
||||
|
||||
# Affected by move
|
||||
assert not os.path.exists(base_dir + "\\TEST\\DIR\\FILE") # Moved to subdir
|
||||
assert not os.path.exists(base_dir + "\\TEST\\DIR2") # Deleted empty directory
|
||||
assert not os.path.exists(base_dir + "\\DIR2") # Dirs don't get moved, only their file content
|
||||
assert os.path.exists(base_dir + "\\DIR\\FILE") # Moved file
|
||||
assert os.path.exists(base_dir + "\\FILE") # Moved file
|
||||
# Not moved
|
||||
assert not os.path.exists(base_dir + "\\some.file")
|
||||
assert not os.path.exists(base_dir + "\\2")
|
||||
@@ -424,6 +434,8 @@ class TestSortingFunctions:
|
||||
# Function return values
|
||||
assert (return_path) == base_dir
|
||||
assert (return_status) is True
|
||||
assert len(return_files) == 1
|
||||
assert return_files[0] == base_dir + "\\FILE"
|
||||
|
||||
# Exception for DVD directories
|
||||
with pyfakefs.fake_filesystem_unittest.Patcher() as ffs:
|
||||
@@ -438,20 +450,24 @@ class TestSortingFunctions:
|
||||
ffs.fs.create_file(base_dir + "\\" + test_file, int("0644", 8))
|
||||
assert os.path.exists(base_dir + "\\" + test_file) is True
|
||||
|
||||
return_path, return_status = sorting.move_to_parent_directory(base_dir + "\\TEST")
|
||||
# Create the file list to move (includes file in DVD directory)
|
||||
files_to_move = [base_dir + "\\TEST\\" + dvd + "\\FILE"]
|
||||
return_path, return_status, return_files = sorting.move_to_parent_directory(base_dir + "\\TEST", files_to_move)
|
||||
|
||||
# Nothing should move in the presence of a DVD directory structure
|
||||
assert os.path.exists(base_dir + "\\TEST\\" + dvd + "\\FILE")
|
||||
assert os.path.exists(base_dir + "\\TEST\\DIR2")
|
||||
assert not os.path.exists(base_dir + "\\DIR2")
|
||||
assert not os.path.exists(base_dir + "\\DIR\\FILE")
|
||||
assert not os.path.exists(base_dir + "\\FILE")
|
||||
assert not os.path.exists(base_dir + "\\some.file")
|
||||
assert not os.path.exists(base_dir + "\\2")
|
||||
assert os.path.exists(base_dir + "\\dir\\some.file")
|
||||
assert os.path.exists(base_dir + "\\dir\\2")
|
||||
# Function return values
|
||||
# Function return values - should return original directory when DVD structure found
|
||||
assert (return_path) == base_dir + "\\TEST"
|
||||
assert (return_status) is True
|
||||
# Files should be returned as-is when DVD structure prevents moving
|
||||
assert return_files == files_to_move
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("clean_cache_dir")
|
||||
@@ -766,6 +782,10 @@ class TestSortingSorter:
|
||||
):
|
||||
"""Test the file renaming of the Sorter class"""
|
||||
with pyfakefs.fake_filesystem_unittest.Patcher() as ffs:
|
||||
# Add guessit package directory to real paths so it can access its config files
|
||||
import guessit
|
||||
guessit_path = os.path.dirname(guessit.__file__)
|
||||
ffs.fs.add_real_paths([guessit_path])
|
||||
# Make up a job name
|
||||
job_name = "Simulated.Job." + job_tag + ".2160p.Web.x264-SAB"
|
||||
|
||||
@@ -816,7 +836,7 @@ class TestSortingSorter:
|
||||
)
|
||||
sorter.get_values()
|
||||
sorter.construct_path()
|
||||
sort_dest, is_ok = sorter.rename(all_files, job_dir)
|
||||
sort_dest, is_ok, updated_files = sorter.rename(all_files, job_dir)
|
||||
|
||||
# Check the result
|
||||
try:
|
||||
@@ -1314,7 +1334,7 @@ class TestSortingSorter:
|
||||
sorted_path = sorter.construct_path()
|
||||
# Check season pack status again after constructing the path
|
||||
assert sorter.is_season_pack is result_is_season_pack_later
|
||||
sorted_dest, sorted_ok = sorter.rename(globber(job_dir), job_dir)
|
||||
sorted_dest, sorted_ok, updated_files = sorter.rename(globber(job_dir), job_dir)
|
||||
|
||||
# Verify the results
|
||||
for pattern, number in result_globs.items():
|
||||
|
||||
Reference in New Issue
Block a user