Compare commits

...

24 Commits

Author SHA1 Message Date
Safihre
0108e2ef5a Update text files for 4.0.3Beta1 2023-06-16 10:53:58 +02:00
Safihre
9a81277ff6 No longer * import AppKit and Foundation 2023-06-16 09:07:29 +02:00
Safihre
06cc2ff316 Update release script to post directly to r/usenet and include link 2023-06-13 14:06:38 +02:00
renovate[bot]
7cdf4cb48c Update all dependencies 2023-06-13 14:06:31 +02:00
thezoggy
c34c547f1f Unable to modify Sorters (#2587) 2023-06-13 14:06:22 +02:00
Safihre
9507294db7 Move DirScanner Lock creation 2023-06-13 14:06:12 +02:00
Safihre
ae7dd62d9f Only initialize DirScanner Lock after starting event loop 2023-06-13 14:06:05 +02:00
renovate[bot]
52e309cb09 Update all dependencies 2023-06-13 14:06:00 +02:00
jcfp
b580373982 Fix sorting lowercasing (#2584)
* run lowercasing on season pack setname

* also subject %fn to lowercasing

* add tests

* woops
2023-06-13 14:05:37 +02:00
renovate[bot]
ec7bde5bb2 Update dependency cryptography to v41 [SECURITY] (#2583)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-13 14:05:30 +02:00
Safihre
3516eeec5b Force full refresh after changing items-per-page
Closes #2416
2023-06-13 14:05:24 +02:00
Safihre
52351192e6 Use more reliable marker if job is still active 2023-06-13 14:05:18 +02:00
Safihre
363a26b8a1 Update text files for 4.0.2 2023-06-07 17:24:54 +02:00
Safihre
7e50a00f55 Correct parameter in release script to merge PR of update 2023-05-31 22:06:26 +02:00
Safihre
a7d6a80e82 Update text files for 4.0.2RC2 2023-05-31 21:49:02 +02:00
Safihre
e7da95b2ac Merge branch 'develop' into 4.0.x 2023-05-31 21:38:48 +02:00
Safihre
74fca23d59 Update text files for 4.0.2RC1 2023-05-23 21:31:43 +02:00
Safihre
0a12fa1253 Merge branch 'develop' into 4.0.x 2023-05-23 21:31:11 +02:00
Safihre
d8c0220353 Update text files for 4.0.1 2023-05-01 21:45:27 +02:00
Safihre
4ab425d15c Update appdata for 4.0.1 release 2023-05-01 21:41:48 +02:00
François M
74e5633d1c Add releases tag (#2539)
* Add 3.7.2 release tag

* Add 4.0.0 placeholder
2023-05-01 21:41:37 +02:00
Safihre
89d36bbc61 Update sabctools to 7.0.2 2023-05-01 21:36:32 +02:00
Safihre
1877ac18a5 Show a better crash on Python <3.8 2023-05-01 21:36:23 +02:00
Safihre
c4b0da335d Update text files for 4.0.0 2023-04-28 14:47:36 +02:00
15 changed files with 121 additions and 43 deletions

View File

@@ -1,21 +1,44 @@
Release Notes - SABnzbd 4.0.0 Release Candidate 2
Release Notes - SABnzbd 4.0.3 Beta 1
=========================================================
## Bugfixes and changes since 4.0.2
- Direct Unpack could get stuck.
- Sorters could not be modified.
- Season Sorting did not respect desired capitalization.
- Windows: Windows Service would fail to start on legacy release.
- macOS: Failed to launch on macOS Sonoma Beta.
## Breaking change
- The `Parameters` setting of a `Notification Script` is now passed as
environment variable `SAB_NOTIFICATION_PARAMETERS` instead of as a
command-line parameter. This prevents the possibility of remote code
execution on systems exposed to the internet without a username/password.
If you use `nzb-notify` you need to update it to the latest version.
## Bugfixes and changes since 4.0.1
- Disabling a server during download did not stop it from downloading.
- Show last line of post-processing script output even if it failed.
- Prevent crash during Deobfuscate on non-unique paths.
- Files that could not be parsed were removed from the `Watched Folder`.
- Warn if the file system does not support unicode or long filenames.
- Warn if `Scripts Folder` is inside the application directory.
- Prevent output buffering of Python post-processing scripts.
- The `PKG-INFO` file was removed from the `src` release.
- Correctly decode partially malformed UUencoded posts.
- macOS: Tray icon could not be disabled.
## Changes since 3.7.2
- In this major update we replaced a core part of Python's SSL handling
with our own improved version. This results in large performance increases
when downloading from news servers with SSL enabled.
In addition, the general connection handling was overhauled, resulting in
performance improvements for all news servers.
- In this major update we optimized a core part of the SSL handling.
This results in large performance increase when downloading from news
servers with SSL enabled. In addition, the general connection handling
was improved, resulting in performance improvements for all news servers.
Special thanks to: mnightingale, puzzledsab and animetosho!
- There are multiple settings that can tweak performance, see:
https://github.com/sabnzbd/sabnzbd/discussions/2474
We are trying to find the most optimal default settings, so you
can help us by letting us know the results on your system!
- When adding a new news server, SSL is enabled by default.
- File assembly performance significantly improved by relying on the
CRC32 instead of the MD5 to perform QuickCheck of files.
- Slowdown more gracefully when the cache fills up.
- Slow down more gracefully when the cache fills up.
- Replaced separate Series/Movie/Date Sorting with general Sorter.
- HTTPS files are included in the `Backup`.
- Improved `Watched Folder` scanning and processing.

View File

@@ -1,3 +1,3 @@
# Special requirements for macOS universal2 binary release
# This way dependabot can auto-update them
cryptography==40.0.2
cryptography==41.0.1

View File

@@ -205,7 +205,7 @@ if RELEASE_THIS and gh_token:
# Merge pull-request
print("Merging pull request in sabnzbd/sabnzbd.github.io for the update")
update_pr.merge(method="squash")
update_pr.merge(merge_method="squash")
# Only with GitHub success we proceed to Reddit
if reddit_token := os.environ.get("REDDIT_TOKEN", ""):
@@ -227,18 +227,30 @@ if RELEASE_THIS and gh_token:
with open(RELEASE_README, "r") as readme_file:
readme_lines = readme_file.readlines()
# Put the download link after the title
readme_lines[2] = "## https://sabnzbd.org/downloads"
# Use the header in the readme as title
title = readme_lines[0]
release_notes_text = "".join(readme_lines[3:])
# Post always to r/SABnzbd
print("Posting release notes to Reddit: r/sabnzbd")
submission = subreddit_sabnzbd.submit(title, selftext=release_notes_text)
# Only stable releases to r/usenet
if not prerelease:
print("Posting release notes to Reddit: r/usenet")
submission = subreddit_usenet.submit(title, selftext=release_notes_text)
# Cross-post to r/SABnzbd
print("Cross-posting release notes to Reddit: r/sabnzbd")
submission.crosspost(subreddit_sabnzbd)
else:
# Post always to r/SABnzbd
print("Posting release notes to Reddit: r/sabnzbd")
subreddit_sabnzbd.submit(title, selftext=release_notes_text)
# Only stable releases to r/usenet
if not prerelease:
print("Cross-posting release notes to Reddit: r/usenet")
submission.crosspost(subreddit_usenet)
print("Posting release notes to Reddit: r/usenet")
subreddit_usenet.submit(title, selftext=release_notes_text)
else:
print("Missing REDDIT_TOKEN")

View File

@@ -1,6 +1,6 @@
# Basic build requirements
# Note that not all sub-dependencies are listed, but only ones we know could cause trouble
pyinstaller==5.11.0
pyinstaller==5.12.0
pyinstaller-hooks-contrib==2023.3
altgraph==0.17.3
wrapt==1.15.0
@@ -9,7 +9,7 @@ certifi
# orjson does not support 32bit Windows, exclude it based on Python-version
# This way we also test ujson on Python 3.8 in the CI-tests
orjson==3.8.14; python_version > '3.8'
orjson==3.9.1; python_version > '3.8'
# For the Windows build
pefile==2023.2.7; sys_platform == 'win32'

View File

@@ -472,7 +472,7 @@
ui.placeholder.height(hPlaceholder + hExtra);
\$('<div class="sorter-placeholder-anim" data-height="' + hPlaceholder + '"></div>').insertAfter(ui.placeholder);
},
cancel: ".pattern-table",
cancel: "input,textarea,button,select,option,.pattern-table",
change: function(event, ui) {
ui.placeholder.stop().height(0).animate({
height: ui.item.outerHeight() + hExtra

View File

@@ -110,6 +110,8 @@ function HistoryListModel(parent) {
value: newValue
})
}
// Update pagination and counters
self.parent.refresh(true)
});
// Retry a job

View File

@@ -159,6 +159,8 @@ function QueueListModel(parent) {
value: newValue
})
}
// Update pagination and counters
self.parent.refresh(true)
});
// Do we show search box. So it doesn't dissapear when nothing is found

View File

@@ -9,15 +9,15 @@ configobj==5.0.8
cheroot==10.0.0
six==1.16.0
cherrypy==18.8.0
jaraco.functools==3.6.0
jaraco.collections==4.1.0
jaraco.functools==3.7.0
jaraco.collections==4.2.0
jaraco.text==3.8.1 # Newer version introduces irrelevant extra dependencies
jaraco.classes==3.2.3
jaraco.context==4.3.0
more-itertools==9.1.0
zc.lockfile==3.0.post1
python-dateutil==2.8.2
tempora==5.2.2
tempora==5.3.0
pytz==2023.3
sgmllib3k==1.0.0
portend==3.1.0
@@ -30,17 +30,17 @@ 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==40.0.2
cryptography==41.0.1
# 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
ujson==5.7.0
ujson==5.8.0
# Windows system integration
pywin32==306; sys_platform == 'win32'
# macOS system calls
pyobjc==9.1.1; sys_platform == 'darwin'
pyobjc==9.2; sys_platform == 'darwin'
# Linux notifications
notify2==0.3.1; sys_platform != 'win32' and sys_platform != 'darwin'

View File

@@ -251,7 +251,7 @@ class DirectUnpacker(threading.Thread):
extracted = []
# Are there more files left?
while self.nzo.files and not self.next_sets:
while not self.removed_from_queue and not self.next_sets:
with self.next_file_lock:
self.next_file_lock.wait()

View File

@@ -66,7 +66,7 @@ class DirScanner(threading.Thread):
self.loop: Optional[asyncio.AbstractEventLoop] = None
self.scanner_task: Optional[asyncio.Task] = None
self.lock = asyncio.Lock() # Prevents concurrent scans
self.lock: Optional[asyncio.Lock] = None # Prevents concurrent scans
self.error_reported = False # Prevents multiple reporting of missing watched folder
self.dirscan_dir = cfg.dirscan_dir.get_path()
self.dirscan_speed = cfg.dirscan_speed()
@@ -109,7 +109,6 @@ class DirScanner(threading.Thread):
def run(self):
"""Start the scanner"""
logging.info("Dirscanner starting up")
self.loop = asyncio.new_event_loop()
try:
@@ -184,7 +183,6 @@ class DirScanner(threading.Thread):
async def when_stable_add_nzbfile(self, path: str, catdir: Optional[str], stat_tuple: os.stat_result):
"""Try and import the NZB but wait until the attributes are stable for 1 second, but give up after 3 sec"""
logging.info("Trying to import %s", path)
# Wait until the attributes are stable for 1 second, but give up after 3 sec
@@ -225,6 +223,11 @@ class DirScanner(threading.Thread):
async def scan_async(self, dirscan_dir: str):
"""Do one scan of the watched folder"""
# On Python 3.8 we first need an event loop before we can create a asyncio.Lock
if not self.lock:
with DIR_SCANNER_LOCK:
self.lock = asyncio.Lock()
async with self.lock:
if sabnzbd.PAUSED_ALL:
return

View File

@@ -19,14 +19,40 @@
sabnzbd.osxmenu - macOS Top Menu
"""
from Foundation import *
from AppKit import *
from objc import YES, NO
import os
import sys
import time
import logging
from objc import YES, NO
from Foundation import (
NSObject,
NSDate,
NSTimer,
NSRunLoop,
NSDefaultRunLoopMode,
NSColor,
NSFont,
NSImage,
NSAttributedString,
)
from AppKit import (
NSStatusBar,
NSMenu,
NSMenuItem,
NSAlternateKeyMask,
NSTerminateNow,
NSEventTrackingRunLoopMode,
NSVariableStatusItemLength,
NSForegroundColorAttributeName,
NSFontAttributeName,
NSOnState,
NSOffState,
NSBaselineOffsetAttributeName,
NSParagraphStyleAttributeName,
NSMutableParagraphStyle,
NSParagraphStyle,
NSCenterTextAlignment,
)
import sabnzbd
import sabnzbd.cfg
@@ -315,7 +341,7 @@ class SABnzbdDelegate(NSObject):
},
)
menu_history_item.setAttributedTitle_(jobfailed)
menu_history_item.setRepresentedObject_("%s" % history["storage"])
menu_history_item.setRepresentedObject_(history["storage"])
self.menu_history.addItem_(menu_history_item)
else:
menu_history_item = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(T("Empty"), "", "")

View File

@@ -432,7 +432,7 @@ class Sorter:
("%ext", f_ext.lstrip(".")),
],
)
f_new = f_name_new + f_ext
f_new = to_lowercase(f_name_new + f_ext)
try:
logging.debug("Renaming season pack file %s to %s", f, f_new)
@@ -477,11 +477,13 @@ class Sorter:
f_name, f_ext = os.path.splitext(os.path.split(f)[1])
new_filepath = os.path.join(
base_path,
path_subst(
self.filename_set + self.multipart_label,
[("%1", str(index)), ("%fn", f_name), ("%ext", f_ext.lstrip("."))],
)
+ f_ext,
to_lowercase(
path_subst(
self.filename_set + self.multipart_label,
[("%1", str(index)), ("%fn", f_name), ("%ext", f_ext.lstrip("."))],
)
+ f_ext,
),
)
try:
logging.debug("Renaming %s to %s", filepath, new_filepath)
@@ -557,7 +559,8 @@ class Sorter:
f_name, f_ext = os.path.splitext(largest_file.get("name"))
filepath = self._to_filepath(largest_file.get("name"), base_path)
new_filepath = os.path.join(
base_path, path_subst(self.filename_set, [("%fn", f_name), ("%ext", f_ext.lstrip("."))]) + f_ext
base_path,
to_lowercase(path_subst(self.filename_set, [("%fn", f_name), ("%ext", f_ext.lstrip("."))]) + f_ext),
)
if not os.path.exists(new_filepath):
renamed_files = []

View File

@@ -5,5 +5,5 @@
# You MUST use double quotes (so " and not ')
__version__ = "4.1.0-develop"
__version__ = "4.0.3Beta1"
__baseline__ = "unknown"

View File

@@ -18,6 +18,7 @@
"""
tests.test_dirscanner - Testing functions in dirscanner.py
"""
import asyncio
import pyfakefs.fake_filesystem_unittest as ffs

View File

@@ -617,10 +617,12 @@ class TestSortingSorter:
[
("%sn s%0se%0e.%ext", True), # %0e marker
("%sn s%se%e.%ext", True), # %e marker
("{%sn }s%se%e.%ext", True), # Same with lowercasing; test for issue #2578
("%sn.%ext", False), # No episode marker
("%sn_%0se%0e", False), # No extension marker
("%r/%sn s%0se%0e.%ext", True), # %0e marker, with dir in sort string
("%r/%sn s%se%e.%ext", True), # %e marker, with dir in sort string
("%r/{%sn} s%se%e.%ext", True), # Same with lowercasing; test for issue #2578
("%r/%sn.%ext", False), # No episode marker, with dir in sort string
("%r/%sn_%0se%0e", False), # No extension marker, with dir in sort string
],
@@ -717,7 +719,11 @@ class TestSortingSorter:
# Also do a basic filename check
for root, dirs, files in os.walk(base_dir):
for filename in files:
assert re.fullmatch(r"Pack Renamer s23e0?\d.*" + extension, filename)
if "{" in sort_string:
# Lowercasing marker in sort string, expect lowercase results
assert re.fullmatch(r"pack renamer s23e0?\d.*" + extension, filename)
else:
assert re.fullmatch(r"Pack Renamer s23e0?\d.*" + extension, filename)
else:
# No season pack renaming should happen, verify original files are still in place
assert os.path.exists(os.path.join(base_dir, f))