diff --git a/SABnzbd.py b/SABnzbd.py index bb8c1a7..a906a62 100755 --- a/SABnzbd.py +++ b/SABnzbd.py @@ -102,13 +102,13 @@ LOG_FLAG = False def guard_loglevel(): - """ Callback function for guarding loglevel """ + """Callback function for guarding loglevel""" global LOG_FLAG LOG_FLAG = True def warning_helpful(*args, **kwargs): - """ Wrapper to ignore helpfull warnings if desired """ + """Wrapper to ignore helpfull warnings if desired""" if sabnzbd.cfg.helpfull_warnings(): return logging.warning(*args, **kwargs) return logging.info(*args, **kwargs) @@ -123,13 +123,13 @@ class GUIHandler(logging.Handler): """ def __init__(self, size): - """ Initializes the handler """ + """Initializes the handler""" logging.Handler.__init__(self) self._size: int = size self.store: List[Dict[str, Any]] = [] def emit(self, record: logging.LogRecord): - """ Emit a record by adding it to our private queue """ + """Emit a record by adding it to our private queue""" # If % is part of the msg, this could fail try: parsed_msg = record.msg % record.args @@ -171,7 +171,7 @@ class GUIHandler(logging.Handler): return len(self.store) def content(self): - """ Return an array with last records """ + """Return an array with last records""" return self.store @@ -236,7 +236,7 @@ GNU GENERAL PUBLIC LICENSE Version 2 or (at your option) any later version. def daemonize(): - """ Daemonize the process, based on various StackOverflow answers """ + """Daemonize the process, based on various StackOverflow answers""" try: pid = os.fork() if pid > 0: @@ -278,7 +278,7 @@ def daemonize(): def abort_and_show_error(browserhost, cherryport, err=""): - """ Abort program because of CherryPy troubles """ + """Abort program because of CherryPy troubles""" logging.error(T("Failed to start web-interface") + " : " + str(err)) if not sabnzbd.DAEMON: if "49" in err: @@ -290,7 +290,7 @@ def abort_and_show_error(browserhost, cherryport, err=""): def identify_web_template(key, defweb, wdir): - """ Determine a correct web template set, return full template path """ + """Determine a correct web template set, return full template path""" if wdir is None: try: wdir = fix_webname(key()) @@ -321,7 +321,7 @@ def identify_web_template(key, defweb, wdir): def check_template_scheme(color, web_dir): - """ Check existence of color-scheme """ + """Check existence of color-scheme""" if color and os.path.exists(os.path.join(web_dir, "static", "stylesheets", "colorschemes", color + ".css")): return color elif color and os.path.exists(os.path.join(web_dir, "static", "stylesheets", "colorschemes", color)): @@ -348,7 +348,7 @@ def fix_webname(name): def get_user_profile_paths(vista_plus): - """ Get the default data locations on Windows""" + """Get the default data locations on Windows""" if sabnzbd.DAEMON: # In daemon mode, do not try to access the user profile # just assume that everything defaults to the program dir @@ -407,7 +407,7 @@ def get_user_profile_paths(vista_plus): def print_modules(): - """ Log all detected optional or external modules """ + """Log all detected optional or external modules""" if sabnzbd.decoder.SABYENC_ENABLED: # Yes, we have SABYenc, and it's the correct version, so it's enabled logging.info("SABYenc module (v%s)... found!", sabnzbd.decoder.SABYENC_VERSION) @@ -484,7 +484,7 @@ def print_modules(): def all_localhosts(): - """ Return all unique values of localhost in order of preference """ + """Return all unique values of localhost in order of preference""" ips = ["127.0.0.1"] try: # Check whether IPv6 is available and enabled @@ -512,7 +512,7 @@ def all_localhosts(): def check_resolve(host): - """ Return True if 'host' resolves """ + """Return True if 'host' resolves""" try: socket.getaddrinfo(host, None) except socket.error: @@ -655,7 +655,7 @@ def get_webhost(cherryhost, cherryport, https_port): def attach_server(host, port, cert=None, key=None, chain=None): - """ Define and attach server, optionally HTTPS """ + """Define and attach server, optionally HTTPS""" if sabnzbd.cfg.ipv6_hosting() or "::1" not in host: http_server = cherrypy._cpserver.Server() http_server.bind_addr = (host, port) @@ -668,7 +668,7 @@ def attach_server(host, port, cert=None, key=None, chain=None): def is_sabnzbd_running(url): - """ Return True when there's already a SABnzbd instance running. """ + """Return True when there's already a SABnzbd instance running.""" try: url = "%s&mode=version" % url # Do this without certificate verification, few installations will have that @@ -681,7 +681,7 @@ def is_sabnzbd_running(url): def find_free_port(host, currentport): - """ Return a free port, 0 when nothing is free """ + """Return a free port, 0 when nothing is free""" n = 0 while n < 10 and currentport <= 49151: try: @@ -835,7 +835,7 @@ def commandline_handler(): def get_f_option(opts): - """ Return value of the -f option """ + """Return value of the -f option""" for opt, arg in opts: if opt == "-f": return arg @@ -1635,7 +1635,7 @@ if sabnzbd.WIN32: import servicemanager class SABnzbd(win32serviceutil.ServiceFramework): - """ Win32 Service Handler """ + """Win32 Service Handler""" _svc_name_ = "SABnzbd" _svc_display_name_ = "SABnzbd Binary Newsreader" diff --git a/builder/package.py b/builder/package.py index bc5f088..53909f5 100644 --- a/builder/package.py +++ b/builder/package.py @@ -71,14 +71,14 @@ def safe_remove(path): def delete_files_glob(name): - """ Delete one file or set of files from wild-card spec """ + """Delete one file or set of files from wild-card spec""" for f in glob.glob(name): if os.path.exists(f): os.remove(f) def run_external_command(command): - """ Wrapper to ease the use of calling external programs """ + """Wrapper to ease the use of calling external programs""" process = subprocess.Popen(command, text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) output, _ = process.communicate() ret = process.wait() @@ -90,7 +90,7 @@ def run_external_command(command): def run_git_command(parms): - """ Run git command, raise error if it failed """ + """Run git command, raise error if it failed""" return run_external_command(["git"] + parms) diff --git a/sabnzbd/__init__.py b/sabnzbd/__init__.py index 7a489f0..6031364 100644 --- a/sabnzbd/__init__.py +++ b/sabnzbd/__init__.py @@ -452,13 +452,13 @@ def halt(): def notify_shutdown_loop(): - """ Trigger the main loop to wake up""" + """Trigger the main loop to wake up""" with sabnzbd.SABSTOP_CONDITION: sabnzbd.SABSTOP_CONDITION.notify() def shutdown_program(): - """ Stop program after halting and saving """ + """Stop program after halting and saving""" if not sabnzbd.SABSTOP: logging.info("[%s] Performing SABnzbd shutdown", misc.caller_name()) sabnzbd.halt() @@ -468,7 +468,7 @@ def shutdown_program(): def trigger_restart(timeout=None): - """ Trigger a restart by setting a flag an shutting down CP """ + """Trigger a restart by setting a flag an shutting down CP""" # Sometimes we need to wait a bit to send good-bye to the browser if timeout: time.sleep(timeout) @@ -482,22 +482,22 @@ def trigger_restart(timeout=None): # Misc Wrappers ############################################################################## def new_limit(): - """ Callback for article cache changes """ + """Callback for article cache changes""" sabnzbd.ArticleCache.new_limit(cfg.cache_limit.get_int()) def guard_restart(): - """ Callback for config options requiring a restart """ + """Callback for config options requiring a restart""" sabnzbd.RESTART_REQ = True def guard_top_only(): - """ Callback for change of top_only option """ + """Callback for change of top_only option""" sabnzbd.NzbQueue.set_top_only(cfg.top_only()) def guard_pause_on_pp(): - """ Callback for change of pause-download-on-pp """ + """Callback for change of pause-download-on-pp""" if cfg.pause_on_post_processing(): pass # Not safe to idle downloader, because we don't know # if post-processing is active now @@ -506,17 +506,17 @@ def guard_pause_on_pp(): def guard_quota_size(): - """ Callback for change of quota_size """ + """Callback for change of quota_size""" sabnzbd.BPSMeter.change_quota() def guard_quota_dp(): - """ Callback for change of quota_day or quota_period """ + """Callback for change of quota_day or quota_period""" sabnzbd.Scheduler.restart() def guard_language(): - """ Callback for change of the interface language """ + """Callback for change of the interface language""" sabnzbd.lang.set_language(cfg.language()) sabnzbd.api.clear_trans_cache() @@ -534,12 +534,12 @@ def set_https_verification(value): def guard_https_ver(): - """ Callback for change of https verification """ + """Callback for change of https verification""" set_https_verification(cfg.enable_https_verification()) def add_url(url, pp=None, script=None, cat=None, priority=None, nzbname=None, password=None): - """ Add NZB based on a URL, attributes optional """ + """Add NZB based on a URL, attributes optional""" if "http" not in url: return if not pp or pp == "-1": @@ -568,7 +568,7 @@ def add_url(url, pp=None, script=None, cat=None, priority=None, nzbname=None, pa def save_state(): - """ Save all internal bookkeeping to disk """ + """Save all internal bookkeeping to disk""" config.save_config() sabnzbd.ArticleCache.flush_articles() sabnzbd.NzbQueue.save() @@ -580,14 +580,14 @@ def save_state(): def pause_all(): - """ Pause all activities than cause disk access """ + """Pause all activities than cause disk access""" sabnzbd.PAUSED_ALL = True sabnzbd.Downloader.pause() logging.debug("PAUSED_ALL active") def unpause_all(): - """ Resume all activities """ + """Resume all activities""" sabnzbd.PAUSED_ALL = False sabnzbd.Downloader.resume() logging.debug("PAUSED_ALL inactive") @@ -599,20 +599,20 @@ def unpause_all(): def backup_exists(filename: str) -> bool: - """ Return True if backup exists and no_dupes is set """ + """Return True if backup exists and no_dupes is set""" path = cfg.nzb_backup_dir.get_path() return path and os.path.exists(os.path.join(path, filename + ".gz")) def backup_nzb(filename: str, data: AnyStr): - """ Backup NZB file """ + """Backup NZB file""" path = cfg.nzb_backup_dir.get_path() if path: save_compressed(path, filename, data) def save_compressed(folder: str, filename: str, data: AnyStr): - """ Save compressed NZB file in folder """ + """Save compressed NZB file in folder""" if filename.endswith(".nzb"): filename += ".gz" else: @@ -728,7 +728,7 @@ def add_nzbfile( def enable_server(server): - """ Enable server (scheduler only) """ + """Enable server (scheduler only)""" try: config.get_config("servers", server).enable.set(1) except: @@ -739,7 +739,7 @@ def enable_server(server): def disable_server(server): - """ Disable server (scheduler only) """ + """Disable server (scheduler only)""" try: config.get_config("servers", server).enable.set(0) except: @@ -750,7 +750,7 @@ def disable_server(server): def system_shutdown(): - """ Shutdown system after halting download and saving bookkeeping """ + """Shutdown system after halting download and saving bookkeeping""" logging.info("Performing system shutdown") Thread(target=halt).start() @@ -766,7 +766,7 @@ def system_shutdown(): def system_hibernate(): - """ Hibernate system """ + """Hibernate system""" logging.info("Performing system hybernation") if sabnzbd.WIN32: powersup.win_hibernate() @@ -777,7 +777,7 @@ def system_hibernate(): def system_standby(): - """ Standby system """ + """Standby system""" logging.info("Performing system standby") if sabnzbd.WIN32: powersup.win_standby() @@ -788,7 +788,7 @@ def system_standby(): def restart_program(): - """ Restart program (used by scheduler) """ + """Restart program (used by scheduler)""" logging.info("Scheduled restart request") # Just set the stop flag, because stopping CherryPy from # the scheduler is not reliable @@ -831,7 +831,7 @@ def change_queue_complete_action(action, new=True): def run_script(script): - """ Run a user script (queue complete only) """ + """Run a user script (queue complete only)""" script_path = filesystem.make_script_path(script) if script_path: try: @@ -842,7 +842,7 @@ def run_script(script): def keep_awake(): - """ If we still have work to do, keep Windows/macOS system awake """ + """If we still have work to do, keep Windows/macOS system awake""" if KERNEL32 or FOUNDATION: if sabnzbd.cfg.keep_awake(): ES_CONTINUOUS = 0x80000000 @@ -890,7 +890,7 @@ def get_new_id(prefix, folder, check_list=None): def save_data(data, _id, path, do_pickle=True, silent=False): - """ Save data to a diskfile """ + """Save data to a diskfile""" if not silent: logging.debug("[%s] Saving data for %s in %s", misc.caller_name(), _id, path) path = os.path.join(path, _id) @@ -917,7 +917,7 @@ def save_data(data, _id, path, do_pickle=True, silent=False): def load_data(data_id, path, remove=True, do_pickle=True, silent=False): - """ Read data from disk file """ + """Read data from disk file""" path = os.path.join(path, data_id) if not os.path.exists(path): @@ -949,7 +949,7 @@ def load_data(data_id, path, remove=True, do_pickle=True, silent=False): def remove_data(_id: str, path: str): - """ Remove admin file """ + """Remove admin file""" path = os.path.join(path, _id) try: if os.path.exists(path): @@ -959,19 +959,19 @@ def remove_data(_id: str, path: str): def save_admin(data: Any, data_id: str): - """ Save data in admin folder in specified format """ + """Save data in admin folder in specified format""" logging.debug("[%s] Saving data for %s", misc.caller_name(), data_id) save_data(data, data_id, cfg.admin_dir.get_path()) def load_admin(data_id: str, remove=False, silent=False) -> Any: - """ Read data in admin folder in specified format """ + """Read data in admin folder in specified format""" logging.debug("[%s] Loading data for %s", misc.caller_name(), data_id) return load_data(data_id, cfg.admin_dir.get_path(), remove=remove, silent=silent) def request_repair(): - """ Request a full repair on next restart """ + """Request a full repair on next restart""" path = os.path.join(cfg.admin_dir.get_path(), REPAIR_REQUEST) try: with open(path, "w") as f: @@ -981,7 +981,7 @@ def request_repair(): def check_repair_request(): - """ Return True if repair request found, remove afterwards """ + """Return True if repair request found, remove afterwards""" path = os.path.join(cfg.admin_dir.get_path(), REPAIR_REQUEST) if os.path.exists(path): try: @@ -1044,7 +1044,7 @@ def check_all_tasks(): def pid_file(pid_path=None, pid_file=None, port=0): - """ Create or remove pid file """ + """Create or remove pid file""" if not sabnzbd.WIN32: if pid_path and pid_path.startswith("/"): sabnzbd.DIR_PID = os.path.join(pid_path, "sabnzbd-%d.pid" % port) @@ -1077,14 +1077,14 @@ def check_incomplete_vs_complete(): def wait_for_download_folder(): - """ Wait for download folder to become available """ + """Wait for download folder to become available""" while not cfg.download_dir.test_path(): logging.debug('Waiting for "incomplete" folder') time.sleep(2.0) def test_ipv6(): - """ Check if external IPv6 addresses are reachable """ + """Check if external IPv6 addresses are reachable""" if not cfg.selftest_host(): # User disabled the test, assume active IPv6 return True @@ -1112,7 +1112,7 @@ def test_ipv6(): def test_cert_checking(): - """ Test quality of certificate validation """ + """Test quality of certificate validation""" # User disabled the test, assume proper SSL certificates if not cfg.selftest_host(): return True @@ -1139,7 +1139,7 @@ def test_cert_checking(): def history_updated(): - """ To make sure we always have a fresh history """ + """To make sure we always have a fresh history""" sabnzbd.LAST_HISTORY_UPDATE += 1 # Never go over the limit if sabnzbd.LAST_HISTORY_UPDATE + 1 >= sys.maxsize: diff --git a/sabnzbd/api.py b/sabnzbd/api.py index 91a9c97..35cbcfd 100644 --- a/sabnzbd/api.py +++ b/sabnzbd/api.py @@ -86,7 +86,7 @@ _MSG_BAD_SERVER_PARMS = "Incorrect server settings" def api_handler(kwargs): - """ API Dispatcher """ + """API Dispatcher""" # Clean-up the arguments for vr in ("mode", "output", "name"): if vr in kwargs and isinstance(kwargs[vr], list): @@ -101,13 +101,13 @@ def api_handler(kwargs): def _api_get_config(name, output, kwargs): - """ API: accepts output, keyword, section """ + """API: accepts output, keyword, section""" _, data = config.get_dconfig(kwargs.get("section"), kwargs.get("keyword")) return report(output, keyword="config", data=data) def _api_set_config(name, output, kwargs): - """ API: accepts output, keyword, section """ + """API: accepts output, keyword, section""" if cfg.configlock(): return report(output, _MSG_CONFIG_LOCKED) if kwargs.get("section") == "servers": @@ -126,7 +126,7 @@ def _api_set_config(name, output, kwargs): def _api_set_config_default(name, output, kwargs): - """ API: Reset requested config variables back to defaults. Currently only for misc-section """ + """API: Reset requested config variables back to defaults. Currently only for misc-section""" if cfg.configlock(): return report(output, _MSG_CONFIG_LOCKED) keywords = kwargs.get("keyword", []) @@ -141,7 +141,7 @@ def _api_set_config_default(name, output, kwargs): def _api_del_config(name, output, kwargs): - """ API: accepts output, keyword, section """ + """API: accepts output, keyword, section""" if cfg.configlock(): return report(output, _MSG_CONFIG_LOCKED) if del_from_section(kwargs): @@ -151,13 +151,13 @@ def _api_del_config(name, output, kwargs): def _api_queue(name, output, kwargs): - """ API: Dispatcher for mode=queue """ + """API: Dispatcher for mode=queue""" value = kwargs.get("value", "") return _api_queue_table.get(name, (_api_queue_default, 2))[0](output, value, kwargs) def _api_queue_delete(output, value, kwargs): - """ API: accepts output, value """ + """API: accepts output, value""" if value.lower() == "all": removed = sabnzbd.NzbQueue.remove_all(kwargs.get("search")) return report(output, keyword="", data={"status": bool(removed), "nzo_ids": removed}) @@ -171,7 +171,7 @@ def _api_queue_delete(output, value, kwargs): def _api_queue_delete_nzf(output, value, kwargs): - """ API: accepts value(=nzo_id), value2(=nzf_id) """ + """API: accepts value(=nzo_id), value2(=nzf_id)""" value2 = kwargs.get("value2") if value and value2: removed = sabnzbd.NzbQueue.remove_nzf(value, value2, force_delete=True) @@ -181,7 +181,7 @@ def _api_queue_delete_nzf(output, value, kwargs): def _api_queue_rename(output, value, kwargs): - """ API: accepts output, value(=old name), value2(=new name), value3(=password) """ + """API: accepts output, value(=old name), value2(=new name), value3(=password)""" value2 = kwargs.get("value2") value3 = kwargs.get("value3") if value and value2: @@ -192,19 +192,19 @@ def _api_queue_rename(output, value, kwargs): def _api_queue_change_complete_action(output, value, kwargs): - """ API: accepts output, value(=action) """ + """API: accepts output, value(=action)""" sabnzbd.change_queue_complete_action(value) return report(output) def _api_queue_purge(output, value, kwargs): - """ API: accepts output """ + """API: accepts output""" removed = sabnzbd.NzbQueue.remove_all(kwargs.get("search")) return report(output, keyword="", data={"status": bool(removed), "nzo_ids": removed}) def _api_queue_pause(output, value, kwargs): - """ API: accepts output, value(=list of nzo_id) """ + """API: accepts output, value(=list of nzo_id)""" if value: items = value.split(",") handled = sabnzbd.NzbQueue.pause_multiple_nzo(items) @@ -214,7 +214,7 @@ def _api_queue_pause(output, value, kwargs): def _api_queue_resume(output, value, kwargs): - """ API: accepts output, value(=list of nzo_id) """ + """API: accepts output, value(=list of nzo_id)""" if value: items = value.split(",") handled = sabnzbd.NzbQueue.resume_multiple_nzo(items) @@ -224,7 +224,7 @@ def _api_queue_resume(output, value, kwargs): def _api_queue_priority(output, value, kwargs): - """ API: accepts output, value(=nzo_id), value2(=priority) """ + """API: accepts output, value(=nzo_id), value2(=priority)""" value2 = kwargs.get("value2") if value and value2: try: @@ -242,7 +242,7 @@ def _api_queue_priority(output, value, kwargs): def _api_queue_sort(output, value, kwargs): - """ API: accepts output, sort, dir """ + """API: accepts output, sort, dir""" sort = kwargs.get("sort") direction = kwargs.get("dir", "") if sort: @@ -253,7 +253,7 @@ def _api_queue_sort(output, value, kwargs): def _api_queue_default(output, value, kwargs): - """ API: accepts output, sort, dir, start, limit """ + """API: accepts output, sort, dir, start, limit""" start = int_conv(kwargs.get("start")) limit = int_conv(kwargs.get("limit")) search = kwargs.get("search") @@ -264,7 +264,7 @@ def _api_queue_default(output, value, kwargs): def _api_queue_rating(output, value, kwargs): - """ API: accepts output, value(=nzo_id), type, setting, detail """ + """API: accepts output, value(=nzo_id), type, setting, detail""" vote_map = {"up": sabnzbd.Rating.VOTE_UP, "down": sabnzbd.Rating.VOTE_DOWN} flag_map = { "spam": sabnzbd.Rating.FLAG_SPAM, @@ -296,17 +296,17 @@ def _api_queue_rating(output, value, kwargs): def _api_options(name, output, kwargs): - """ API: accepts output """ + """API: accepts output""" return options_list(output) def _api_translate(name, output, kwargs): - """ API: accepts output, value(=acronym) """ + """API: accepts output, value(=acronym)""" return report(output, keyword="value", data=T(kwargs.get("value", ""))) def _api_addfile(name, output, kwargs): - """ API: accepts name, output, pp, script, cat, priority, nzbname """ + """API: accepts name, output, pp, script, cat, priority, nzbname""" # Normal upload will send the nzb in a kw arg called name or nzbfile if not name or isinstance(name, str): name = kwargs.get("nzbfile", None) @@ -332,7 +332,7 @@ def _api_addfile(name, output, kwargs): def _api_retry(name, output, kwargs): - """ API: accepts name, output, value(=nzo_id), nzbfile(=optional NZB), password (optional) """ + """API: accepts name, output, value(=nzo_id), nzbfile(=optional NZB), password (optional)""" value = kwargs.get("value") # Normal upload will send the nzb in a kw arg called nzbfile if name is None or isinstance(name, str): @@ -348,7 +348,7 @@ def _api_retry(name, output, kwargs): def _api_cancel_pp(name, output, kwargs): - """ API: accepts name, output, value(=nzo_id) """ + """API: accepts name, output, value(=nzo_id)""" nzo_id = kwargs.get("value") if sabnzbd.PostProcessor.cancel_pp(nzo_id): return report(output, keyword="", data={"status": True, "nzo_id": nzo_id}) @@ -357,7 +357,7 @@ def _api_cancel_pp(name, output, kwargs): def _api_addlocalfile(name, output, kwargs): - """ API: accepts name, output, pp, script, cat, priority, nzbname """ + """API: accepts name, output, pp, script, cat, priority, nzbname""" if name: if os.path.exists(name): pp = kwargs.get("pp") @@ -395,7 +395,7 @@ def _api_addlocalfile(name, output, kwargs): def _api_switch(name, output, kwargs): - """ API: accepts output, value(=first id), value2(=second id) """ + """API: accepts output, value(=first id), value2(=second id)""" value = kwargs.get("value") value2 = kwargs.get("value2") if value and value2: @@ -407,7 +407,7 @@ def _api_switch(name, output, kwargs): def _api_change_cat(name, output, kwargs): - """ API: accepts output, value(=nzo_id), value2(=category) """ + """API: accepts output, value(=nzo_id), value2(=category)""" value = kwargs.get("value") value2 = kwargs.get("value2") if value and value2: @@ -422,7 +422,7 @@ def _api_change_cat(name, output, kwargs): def _api_change_script(name, output, kwargs): - """ API: accepts output, value(=nzo_id), value2(=script) """ + """API: accepts output, value(=nzo_id), value2(=script)""" value = kwargs.get("value") value2 = kwargs.get("value2") if value and value2: @@ -437,7 +437,7 @@ def _api_change_script(name, output, kwargs): def _api_change_opts(name, output, kwargs): - """ API: accepts output, value(=nzo_id), value2(=pp) """ + """API: accepts output, value(=nzo_id), value2(=pp)""" value = kwargs.get("value") value2 = kwargs.get("value2") result = 0 @@ -447,13 +447,13 @@ def _api_change_opts(name, output, kwargs): def _api_fullstatus(name, output, kwargs): - """ API: full history status""" + """API: full history status""" status = build_status(skip_dashboard=kwargs.get("skip_dashboard", 1), output=output) return report(output, keyword="status", data=status) def _api_history(name, output, kwargs): - """ API: accepts output, value(=nzo_id), start, limit, search, nzo_ids """ + """API: accepts output, value(=nzo_id), start, limit, search, nzo_ids""" value = kwargs.get("value", "") start = int_conv(kwargs.get("start")) limit = int_conv(kwargs.get("limit")) @@ -517,7 +517,7 @@ def _api_history(name, output, kwargs): def _api_get_files(name, output, kwargs): - """ API: accepts output, value(=nzo_id) """ + """API: accepts output, value(=nzo_id)""" value = kwargs.get("value") if value: return report(output, keyword="files", data=build_file_list(value)) @@ -526,7 +526,7 @@ def _api_get_files(name, output, kwargs): def _api_addurl(name, output, kwargs): - """ API: accepts name, output, pp, script, cat, priority, nzbname """ + """API: accepts name, output, pp, script, cat, priority, nzbname""" pp = kwargs.get("pp") script = kwargs.get("script") cat = kwargs.get("cat") @@ -544,27 +544,27 @@ def _api_addurl(name, output, kwargs): def _api_pause(name, output, kwargs): - """ API: accepts output """ + """API: accepts output""" sabnzbd.Scheduler.plan_resume(0) sabnzbd.Downloader.pause() return report(output) def _api_resume(name, output, kwargs): - """ API: accepts output """ + """API: accepts output""" sabnzbd.Scheduler.plan_resume(0) sabnzbd.unpause_all() return report(output) def _api_shutdown(name, output, kwargs): - """ API: accepts output """ + """API: accepts output""" sabnzbd.shutdown_program() return report(output) def _api_warnings(name, output, kwargs): - """ API: accepts name, output """ + """API: accepts name, output""" if name == "clear": return report(output, keyword="warnings", data=sabnzbd.GUIHANDLER.clear()) elif name == "show": @@ -575,22 +575,22 @@ def _api_warnings(name, output, kwargs): def _api_get_cats(name, output, kwargs): - """ API: accepts output """ + """API: accepts output""" return report(output, keyword="categories", data=list_cats(False)) def _api_get_scripts(name, output, kwargs): - """ API: accepts output """ + """API: accepts output""" return report(output, keyword="scripts", data=list_scripts()) def _api_version(name, output, kwargs): - """ API: accepts output """ + """API: accepts output""" return report(output, keyword="version", data=sabnzbd.__version__) def _api_auth(name, output, kwargs): - """ API: accepts output """ + """API: accepts output""" auth = "None" if not cfg.disable_key(): auth = "badkey" @@ -608,7 +608,7 @@ def _api_auth(name, output, kwargs): def _api_restart(name, output, kwargs): - """ API: accepts output """ + """API: accepts output""" logging.info("Restart requested by API") # Do the shutdown async to still send goodbye to browser Thread(target=sabnzbd.trigger_restart, kwargs={"timeout": 1}).start() @@ -616,7 +616,7 @@ def _api_restart(name, output, kwargs): def _api_restart_repair(name, output, kwargs): - """ API: accepts output """ + """API: accepts output""" logging.info("Queue repair requested by API") sabnzbd.request_repair() # Do the shutdown async to still send goodbye to browser @@ -625,26 +625,26 @@ def _api_restart_repair(name, output, kwargs): def _api_disconnect(name, output, kwargs): - """ API: accepts output """ + """API: accepts output""" sabnzbd.Downloader.disconnect() return report(output) def _api_osx_icon(name, output, kwargs): - """ API: accepts output, value """ + """API: accepts output, value""" value = kwargs.get("value", "1").strip() cfg.osx_menu.set(value != "0") return report(output) def _api_rescan(name, output, kwargs): - """ API: accepts output """ + """API: accepts output""" sabnzbd.NzbQueue.scan_jobs(all_jobs=False, action=True) return report(output) def _api_eval_sort(name, output, kwargs): - """ API: evaluate sorting expression """ + """API: evaluate sorting expression""" name = kwargs.get("name", "") value = kwargs.get("value", "") title = kwargs.get("title") @@ -657,43 +657,43 @@ def _api_eval_sort(name, output, kwargs): def _api_watched_now(name, output, kwargs): - """ API: accepts output """ + """API: accepts output""" sabnzbd.DirScanner.scan() return report(output) def _api_resume_pp(name, output, kwargs): - """ API: accepts output """ + """API: accepts output""" sabnzbd.PostProcessor.paused = False return report(output) def _api_pause_pp(name, output, kwargs): - """ API: accepts output """ + """API: accepts output""" sabnzbd.PostProcessor.paused = True return report(output) def _api_rss_now(name, output, kwargs): - """ API: accepts output """ + """API: accepts output""" # Run RSS scan async, because it can take a long time sabnzbd.Scheduler.force_rss() return report(output) def _api_retry_all(name, output, kwargs): - """ API: Retry all failed items in History """ + """API: Retry all failed items in History""" return report(output, keyword="status", data=retry_all_jobs()) def _api_reset_quota(name, output, kwargs): - """ Reset quota left """ + """Reset quota left""" sabnzbd.BPSMeter.reset_quota(force=True) return report(output) def _api_test_email(name, output, kwargs): - """ API: send a test email, return result """ + """API: send a test email, return result""" logging.info("Sending test email") pack = {"download": ["action 1", "action 2"], "unpack": ["action 1", "action 2"]} res = sabnzbd.emailer.endjob( @@ -715,61 +715,61 @@ def _api_test_email(name, output, kwargs): def _api_test_windows(name, output, kwargs): - """ API: send a test to Windows, return result """ + """API: send a test to Windows, return result""" logging.info("Sending test notification") res = sabnzbd.notifier.send_windows("SABnzbd", T("Test Notification"), "other") return report(output, error=res) def _api_test_notif(name, output, kwargs): - """ API: send a test to Notification Center, return result """ + """API: send a test to Notification Center, return result""" logging.info("Sending test notification") res = sabnzbd.notifier.send_notification_center("SABnzbd", T("Test Notification"), "other") return report(output, error=res) def _api_test_osd(name, output, kwargs): - """ API: send a test OSD notification, return result """ + """API: send a test OSD notification, return result""" logging.info("Sending OSD notification") res = sabnzbd.notifier.send_notify_osd("SABnzbd", T("Test Notification")) return report(output, error=res) def _api_test_prowl(name, output, kwargs): - """ API: send a test Prowl notification, return result """ + """API: send a test Prowl notification, return result""" logging.info("Sending Prowl notification") res = sabnzbd.notifier.send_prowl("SABnzbd", T("Test Notification"), "other", force=True, test=kwargs) return report(output, error=res) def _api_test_pushover(name, output, kwargs): - """ API: send a test Pushover notification, return result """ + """API: send a test Pushover notification, return result""" logging.info("Sending Pushover notification") res = sabnzbd.notifier.send_pushover("SABnzbd", T("Test Notification"), "other", force=True, test=kwargs) return report(output, error=res) def _api_test_pushbullet(name, output, kwargs): - """ API: send a test Pushbullet notification, return result """ + """API: send a test Pushbullet notification, return result""" logging.info("Sending Pushbullet notification") res = sabnzbd.notifier.send_pushbullet("SABnzbd", T("Test Notification"), "other", force=True, test=kwargs) return report(output, error=res) def _api_test_nscript(name, output, kwargs): - """ API: execute a test notification script, return result """ + """API: execute a test notification script, return result""" logging.info("Executing notification script") res = sabnzbd.notifier.send_nscript("SABnzbd", T("Test Notification"), "other", force=True, test=kwargs) return report(output, error=res) def _api_undefined(name, output, kwargs): - """ API: accepts output """ + """API: accepts output""" return report(output, _MSG_NOT_IMPLEMENTED) def _api_browse(name, output, kwargs): - """ Return tree of local path """ + """Return tree of local path""" compact = kwargs.get("compact") if compact and compact == "1": @@ -783,14 +783,14 @@ def _api_browse(name, output, kwargs): def _api_config(name, output, kwargs): - """ API: Dispatcher for "config" """ + """API: Dispatcher for "config" """ if cfg.configlock(): return report(output, _MSG_CONFIG_LOCKED) return _api_config_table.get(name, (_api_config_undefined, 2))[0](output, kwargs) def _api_config_speedlimit(output, kwargs): - """ API: accepts output, value(=speed) """ + """API: accepts output, value(=speed)""" value = kwargs.get("value") if not value: value = "0" @@ -799,12 +799,12 @@ def _api_config_speedlimit(output, kwargs): def _api_config_get_speedlimit(output, kwargs): - """ API: accepts output """ + """API: accepts output""" return report(output, keyword="speedlimit", data=sabnzbd.Downloader.get_limit()) def _api_config_set_colorscheme(output, kwargs): - """ API: accepts output""" + """API: accepts output""" value = kwargs.get("value") if value: cfg.web_color.set(value) @@ -814,21 +814,21 @@ def _api_config_set_colorscheme(output, kwargs): def _api_config_set_pause(output, kwargs): - """ API: accepts output, value(=pause interval) """ + """API: accepts output, value(=pause interval)""" value = kwargs.get("value") sabnzbd.Scheduler.plan_resume(int_conv(value)) return report(output) def _api_config_set_apikey(output, kwargs): - """ API: accepts output """ + """API: accepts output""" cfg.api_key.set(config.create_api_key()) config.save_config() return report(output, keyword="apikey", data=cfg.api_key()) def _api_config_set_nzbkey(output, kwargs): - """ API: accepts output """ + """API: accepts output""" cfg.nzb_key.set(config.create_api_key()) config.save_config() return report(output, keyword="nzbkey", data=cfg.nzb_key()) @@ -849,7 +849,7 @@ def _api_config_regenerate_certs(output, kwargs): def _api_config_test_server(output, kwargs): - """ API: accepts output, server-params """ + """API: accepts output, server-params""" result, msg = test_nntp_server_dict(kwargs) response = {"result": result, "message": msg} if output: @@ -859,12 +859,12 @@ def _api_config_test_server(output, kwargs): def _api_config_undefined(output, kwargs): - """ API: accepts output """ + """API: accepts output""" return report(output, _MSG_NOT_IMPLEMENTED) def _api_server_stats(name, output, kwargs): - """ API: accepts output """ + """API: accepts output""" sum_t, sum_m, sum_w, sum_d = sabnzbd.BPSMeter.get_sums() stats = {"total": sum_t, "month": sum_m, "week": sum_w, "day": sum_d, "servers": {}} @@ -974,7 +974,7 @@ _api_config_table = { def api_level(mode: str, name: str) -> int: - """ Return access level required for this API call """ + """Return access level required for this API call""" if mode == "queue" and name in _api_queue_table: return _api_queue_table[name][1] if mode == "config" and name in _api_config_table: @@ -1091,7 +1091,7 @@ class xml_factory: def handle_server_api(output, kwargs): - """ Special handler for API-call 'set_config' [servers] """ + """Special handler for API-call 'set_config' [servers]""" name = kwargs.get("keyword") if not name: name = kwargs.get("name") @@ -1109,7 +1109,7 @@ def handle_server_api(output, kwargs): def handle_rss_api(output, kwargs): - """ Special handler for API-call 'set_config' [rss] """ + """Special handler for API-call 'set_config' [rss]""" name = kwargs.get("keyword") if not name: name = kwargs.get("name") @@ -1143,7 +1143,7 @@ def handle_rss_api(output, kwargs): def handle_cat_api(output, kwargs): - """ Special handler for API-call 'set_config' [categories] """ + """Special handler for API-call 'set_config' [categories]""" name = kwargs.get("keyword") if not name: name = kwargs.get("name") @@ -1387,7 +1387,7 @@ def build_queue(start=0, limit=0, trans=False, output=None, search=None, nzo_ids def fast_queue() -> Tuple[bool, int, float, str]: - """ Return paused, bytes_left, bpsnow, time_left """ + """Return paused, bytes_left, bpsnow, time_left""" bytes_left = sabnzbd.sabnzbd.NzbQueue.remaining() paused = sabnzbd.Downloader.paused bpsnow = sabnzbd.BPSMeter.bps @@ -1467,7 +1467,7 @@ def options_list(output): def retry_job(job, new_nzb=None, password=None): - """ Re enter failed job in the download queue """ + """Re enter failed job in the download queue""" if job: history_db = sabnzbd.get_db_connection() futuretype, url, pp, script, cat = history_db.get_other(job) @@ -1484,7 +1484,7 @@ def retry_job(job, new_nzb=None, password=None): def retry_all_jobs(): - """ Re enter all failed jobs in the download queue """ + """Re enter all failed jobs in the download queue""" # Fetch all retryable folders from History items = sabnzbd.api.build_history()[0] nzo_ids = [] @@ -1495,14 +1495,14 @@ def retry_all_jobs(): def del_job_files(job_paths): - """ Remove files of each path in the list """ + """Remove files of each path in the list""" for path in job_paths: if path and clip_path(path).lower().startswith(cfg.download_dir.get_clipped_path().lower()): remove_all(path, recursive=True) def del_hist_job(job, del_files): - """ Remove history element """ + """Remove history element""" if job: path = sabnzbd.PostProcessor.get_path(job) if path: @@ -1514,7 +1514,7 @@ def del_hist_job(job, del_files): def Tspec(txt): - """ Translate special terms """ + """Translate special terms""" if txt == "None": return T("None") elif txt in ("Default", "*"): @@ -1543,14 +1543,14 @@ def Ttemplate(txt): def clear_trans_cache(): - """ Clean cache for skin translations """ + """Clean cache for skin translations""" global _SKIN_CACHE _SKIN_CACHE = {} sabnzbd.WEBUI_READY = True def build_header(webdir="", output=None, trans_functions=True): - """ Build the basic header """ + """Build the basic header""" try: uptime = calc_age(sabnzbd.START) except: @@ -1628,7 +1628,7 @@ def build_header(webdir="", output=None, trans_functions=True): def build_queue_header(search=None, nzo_ids=None, start=0, limit=0, output=None): - """ Build full queue header """ + """Build full queue header""" header = build_header(output=output) @@ -1782,7 +1782,7 @@ def build_history( def get_active_history(queue, items): - """ Get the currently in progress and active history queue. """ + """Get the currently in progress and active history queue.""" for nzo in queue: item = {} ( @@ -1825,7 +1825,7 @@ def get_active_history(queue, items): def calc_timeleft(bytesleft, bps): - """ Calculate the time left in the format HH:MM:SS """ + """Calculate the time left in the format HH:MM:SS""" try: if bytesleft <= 0: return "0:00:00" @@ -1877,7 +1877,7 @@ def plural_to_single(kw, def_kw=""): def del_from_section(kwargs): - """ Remove keyword in section """ + """Remove keyword in section""" section = kwargs.get("section", "") if section in ("servers", "rss", "categories"): keyword = kwargs.get("keyword") @@ -1895,7 +1895,7 @@ def del_from_section(kwargs): def history_remove_failed(): - """ Remove all failed jobs from history, including files """ + """Remove all failed jobs from history, including files""" logging.info("Scheduled removal of all failed jobs") with HistoryDB() as history_db: del_job_files(history_db.get_failed_paths()) @@ -1903,7 +1903,7 @@ def history_remove_failed(): def history_remove_completed(): - """ Remove all completed jobs from history """ + """Remove all completed jobs from history""" logging.info("Scheduled removal of all completed jobs") with HistoryDB() as history_db: history_db.remove_completed() diff --git a/sabnzbd/articlecache.py b/sabnzbd/articlecache.py index 398076d..8c8ba14 100644 --- a/sabnzbd/articlecache.py +++ b/sabnzbd/articlecache.py @@ -55,7 +55,7 @@ class ArticleCache: return ANFO(len(self.__article_table), abs(self.__cache_size), self.__cache_limit_org) def new_limit(self, limit: int): - """ Called when cache limit changes """ + """Called when cache limit changes""" self.__cache_limit_org = limit if limit < 0: self.__cache_limit = self.__cache_upper_limit @@ -70,20 +70,20 @@ class ArticleCache: @synchronized(ARTICLE_COUNTER_LOCK) def reserve_space(self, data_size: int): - """ Reserve space in the cache """ + """Reserve space in the cache""" self.__cache_size += data_size @synchronized(ARTICLE_COUNTER_LOCK) def free_reserved_space(self, data_size: int): - """ Remove previously reserved space """ + """Remove previously reserved space""" self.__cache_size -= data_size def space_left(self) -> bool: - """ Is there space left in the set limit? """ + """Is there space left in the set limit?""" return self.__cache_size < self.__cache_limit def save_article(self, article: Article, data: bytes): - """ Save article in cache, either memory or disk """ + """Save article in cache, either memory or disk""" nzo = article.nzf.nzo if nzo.is_gone(): # Do not discard this article because the @@ -115,7 +115,7 @@ class ArticleCache: self.__flush_article_to_disk(article, data) def load_article(self, article: Article): - """ Load the data of the article """ + """Load the data of the article""" data = None nzo = article.nzf.nzo @@ -145,7 +145,7 @@ class ArticleCache: logging.debug("Failed to flush item from cache, probably already deleted or written to disk") def purge_articles(self, articles: List[Article]): - """ Remove all saved articles, from memory and disk """ + """Remove all saved articles, from memory and disk""" logging.debug("Purging %s articles from the cache/disk", len(articles)) for article in articles: if article in self.__article_table: diff --git a/sabnzbd/assembler.py b/sabnzbd/assembler.py index 670a285..b44955f 100644 --- a/sabnzbd/assembler.py +++ b/sabnzbd/assembler.py @@ -267,7 +267,7 @@ SAFE_EXTS = (".mkv", ".mp4", ".avi", ".wmv", ".mpg", ".webm") def is_cloaked(nzo: NzbObject, path: str, names: List[str]) -> bool: - """ Return True if this is likely to be a cloaked encrypted post """ + """Return True if this is likely to be a cloaked encrypted post""" fname = os.path.splitext(get_filename(path.lower()))[0] for name in names: name = get_filename(name.lower()) @@ -296,7 +296,7 @@ def is_cloaked(nzo: NzbObject, path: str, names: List[str]) -> bool: def check_encrypted_and_unwanted_files(nzo: NzbObject, filepath: str) -> Tuple[bool, Optional[str]]: - """ Combines check for unwanted and encrypted files to save on CPU and IO """ + """Combines check for unwanted and encrypted files to save on CPU and IO""" encrypted = False unwanted = None diff --git a/sabnzbd/bpsmeter.py b/sabnzbd/bpsmeter.py index 4e16547..56f8fad 100644 --- a/sabnzbd/bpsmeter.py +++ b/sabnzbd/bpsmeter.py @@ -39,14 +39,14 @@ RE_HHMM = re.compile(r"(\d+):(\d+)\s*$") def tomorrow(t: float) -> float: - """ Return timestamp for tomorrow (midnight) """ + """Return timestamp for tomorrow (midnight)""" now = time.localtime(t) ntime = (now[0], now[1], now[2], 0, 0, 0, now[6], now[7], now[8]) return time.mktime(ntime) + DAY def this_week(t: float) -> float: - """ Return timestamp for start of this week (monday) """ + """Return timestamp for start of this week (monday)""" while 1: tm = time.localtime(t) if tm.tm_wday == 0: @@ -57,19 +57,19 @@ def this_week(t: float) -> float: def next_week(t: float) -> float: - """ Return timestamp for start of next week (monday) """ + """Return timestamp for start of next week (monday)""" return this_week(t) + WEEK def this_month(t: float) -> float: - """ Return timestamp for start of next month """ + """Return timestamp for start of next month""" now = time.localtime(t) ntime = (now[0], now[1], 1, 0, 0, 0, 0, 0, now[8]) return time.mktime(ntime) def last_month_day(tm: time.struct_time) -> int: - """ Return last day of this month """ + """Return last day of this month""" year, month = tm[:2] day = DAYS[month] # This simple formula for leap years is good enough @@ -79,7 +79,7 @@ def last_month_day(tm: time.struct_time) -> int: def next_month(t: float) -> float: - """ Return timestamp for start of next month """ + """Return timestamp for start of next month""" now = time.localtime(t) month = now.tm_mon + 1 year = now.tm_year @@ -128,7 +128,7 @@ class BPSMeter: self.quota_enabled: bool = True # Scheduled quota enable/disable def save(self): - """ Save admin to disk """ + """Save admin to disk""" sabnzbd.save_admin( ( self.last_update, @@ -150,7 +150,7 @@ class BPSMeter: ) def defaults(self): - """ Get the latest data from the database and assign to a fake server """ + """Get the latest data from the database and assign to a fake server""" logging.debug("Setting default BPS meter values") with sabnzbd.database.HistoryDB() as history_db: grand, month, week = history_db.get_history_size() @@ -167,7 +167,7 @@ class BPSMeter: self.quota = self.left = cfg.quota_size.get_float() def read(self): - """ Read admin from disk, return True when pause is needed """ + """Read admin from disk, return True when pause is needed""" res = False quota = self.left = cfg.quota_size.get_float() # Quota for this period self.have_quota = bool(cfg.quota_size()) @@ -201,7 +201,7 @@ class BPSMeter: return res def update(self, server: Optional[str] = None, amount: int = 0, force_full_update: bool = True): - """ Update counters for "server" with "amount" bytes """ + """Update counters for "server" with "amount" bytes""" t = time.time() # Add amount to temporary storage @@ -339,7 +339,7 @@ class BPSMeter: self.bps_list = self.bps_list[len(self.bps_list) - BPS_LIST_MAX :] def get_sums(self): - """ return tuple of grand, month, week, day totals """ + """return tuple of grand, month, week, day totals""" return ( sum([v for v in self.grand_total.values()]), sum([v for v in self.month_total.values()]), @@ -348,7 +348,7 @@ class BPSMeter: ) def amounts(self, server: str): - """ Return grand, month, week, day and article totals for specified server """ + """Return grand, month, week, day and article totals for specified server""" return ( self.grand_total.get(server, 0), self.month_total.get(server, 0), @@ -360,7 +360,7 @@ class BPSMeter: ) def clear_server(self, server: str): - """ Clean counters for specified server """ + """Clean counters for specified server""" if server in self.day_total: del self.day_total[server] if server in self.week_total: @@ -425,7 +425,7 @@ class BPSMeter: return True def next_reset(self, t: Optional[float] = None): - """ Determine next reset time """ + """Determine next reset time""" t = t or time.time() tm = time.localtime(t) if self.q_period == "d": @@ -456,7 +456,7 @@ class BPSMeter: logging.debug("Will reset quota at %s", tm) def change_quota(self, allow_resume: bool = True): - """ Update quota, potentially pausing downloader """ + """Update quota, potentially pausing downloader""" if not self.have_quota and self.quota < 0.5: # Never set, use last period's size per = cfg.quota_period() @@ -486,7 +486,7 @@ class BPSMeter: self.resume() def get_quota(self): - """ If quota active, return check-function, hour, minute """ + """If quota active, return check-function, hour, minute""" if self.have_quota: self.q_period = cfg.quota_period()[0].lower() self.q_day = 1 @@ -515,24 +515,24 @@ class BPSMeter: return None, 0, 0 def set_status(self, status: bool, action: bool = True): - """ Disable/enable quota management """ + """Disable/enable quota management""" self.quota_enabled = status if action and not status: self.resume() @staticmethod def resume(): - """ Resume downloading """ + """Resume downloading""" if cfg.quota_resume() and sabnzbd.Downloader.paused: sabnzbd.Downloader.resume() def midnight(self): - """ Midnight action: dummy update for all servers """ + """Midnight action: dummy update for all servers""" for server in self.day_total.keys(): self.update(server) def quota_handler(): - """ To be called from scheduler """ + """To be called from scheduler""" logging.debug("Checking quota") sabnzbd.BPSMeter.reset_quota() diff --git a/sabnzbd/cfg.py b/sabnzbd/cfg.py index 735e099..4c8de13 100644 --- a/sabnzbd/cfg.py +++ b/sabnzbd/cfg.py @@ -69,7 +69,7 @@ def validate_email(value): def validate_server(value): - """ Check if server non-empty""" + """Check if server non-empty""" global email_endjob, email_full, email_rss if value == "" and (email_endjob() or email_full() or email_rss()): return T("Server address required"), None @@ -78,7 +78,7 @@ def validate_server(value): def validate_script(value): - """ Check if value is a valid script """ + """Check if value is a valid script""" if not sabnzbd.__INITIALIZED__ or (value and sabnzbd.filesystem.is_valid_script(value)): return None, value elif (value and value == "None") or not value: diff --git a/sabnzbd/config.py b/sabnzbd/config.py index 0b6a910..bc49b7c 100644 --- a/sabnzbd/config.py +++ b/sabnzbd/config.py @@ -52,7 +52,7 @@ RE_PARAMFINDER = re.compile(r"""(?:'.*?')|(?:".*?")|(?:[^'",\s][^,]*)""") class Option: - """ Basic option class, basic fields """ + """Basic option class, basic fields""" def __init__(self, section: str, keyword: str, default_val: Any = None, add: bool = True, protect: bool = False): """Basic option @@ -81,7 +81,7 @@ class Option: anchor[keyword] = self def get(self) -> Any: - """ Retrieve value field """ + """Retrieve value field""" if self.__value is not None: return self.__value else: @@ -91,11 +91,11 @@ class Option: return str(self.get()) def get_dict(self, safe: bool = False) -> Dict[str, Any]: - """ Return value a dictionary """ + """Return value a dictionary""" return {self.__keyword: self.get()} def set_dict(self, values: Dict[str, Any]): - """ Set value based on dictionary """ + """Set value based on dictionary""" if not self.__protect: try: self.set(values["value"]) @@ -103,7 +103,7 @@ class Option: pass def set(self, value: Any): - """ Set new value, no validation """ + """Set new value, no validation""" global modified if value is not None: if isinstance(value, list) or isinstance(value, dict) or value != self.__value: @@ -116,11 +116,11 @@ class Option: return self.__default_val def callback(self, callback: Callable): - """ Set callback function """ + """Set callback function""" self.__callback = callback def ident(self): - """ Return section-list and keyword """ + """Return section-list and keyword""" return self.__sections, self.__keyword @@ -145,7 +145,7 @@ class OptionNumber(Option): super().__init__(section, keyword, default_val, add=add, protect=protect) def set(self, value: Any): - """ set new value, limited by range """ + """set new value, limited by range""" if value is not None: try: if self.__int: @@ -165,12 +165,12 @@ class OptionNumber(Option): super().set(value) def __call__(self) -> Union[int, float]: - """ get() replacement """ + """get() replacement""" return self.get() class OptionBool(Option): - """ Boolean option class, always returns 0 or 1.""" + """Boolean option class, always returns 0 or 1.""" def __init__(self, section: str, keyword: str, default_val: bool = False, add: bool = True, protect: bool = False): super().__init__(section, keyword, int(default_val), add=add, protect=protect) @@ -180,12 +180,12 @@ class OptionBool(Option): super().set(sabnzbd.misc.int_conv(value)) def __call__(self) -> int: - """ get() replacement """ + """get() replacement""" return int(self.get()) class OptionDir(Option): - """ Directory option class """ + """Directory option class""" def __init__( self, @@ -206,7 +206,7 @@ class OptionDir(Option): super().__init__(section, keyword, default_val, add=add) def get(self) -> str: - """ Return value, corrected for platform """ + """Return value, corrected for platform""" p = super().get() if sabnzbd.WIN32: return p.replace("/", "\\") if "/" in p else p @@ -214,7 +214,7 @@ class OptionDir(Option): return p.replace("\\", "/") if "\\" in p else p def get_path(self) -> str: - """ Return full absolute path """ + """Return full absolute path""" value = self.get() path = "" if value: @@ -224,11 +224,11 @@ class OptionDir(Option): return path def get_clipped_path(self) -> str: - """ Return clipped full absolute path """ + """Return clipped full absolute path""" return clip_path(self.get_path()) def test_path(self) -> bool: - """ Return True if path exists """ + """Return True if path exists""" value = self.get() if value: return os.path.exists(real_path(self.__root, value)) @@ -236,7 +236,7 @@ class OptionDir(Option): return False def set_root(self, root: str): - """ Set new root, is assumed to be valid """ + """Set new root, is assumed to be valid""" self.__root = root def set(self, value: str, create: bool = False) -> Optional[str]: @@ -260,16 +260,16 @@ class OptionDir(Option): return error def set_create(self, value: bool): - """ Set auto-creation value """ + """Set auto-creation value""" self.__create = value def __call__(self) -> str: - """ get() replacement """ + """get() replacement""" return self.get() class OptionList(Option): - """ List option class """ + """List option class""" def __init__( self, @@ -286,7 +286,7 @@ class OptionList(Option): super().__init__(section, keyword, default_val, add=add, protect=protect) def set(self, value: Union[str, List]) -> Optional[str]: - """ Set the list given a comma-separated string or a list """ + """Set the list given a comma-separated string or a list""" error = None if value is not None: if not isinstance(value, list): @@ -301,20 +301,20 @@ class OptionList(Option): return error def get_string(self) -> str: - """ Return the list as a comma-separated string """ + """Return the list as a comma-separated string""" return ", ".join(self.get()) def default_string(self) -> str: - """ Return the default list as a comma-separated string """ + """Return the default list as a comma-separated string""" return ", ".join(self.default()) def __call__(self) -> List[str]: - """ get() replacement """ + """get() replacement""" return self.get() class OptionStr(Option): - """ String class.""" + """String class.""" def __init__( self, @@ -331,15 +331,15 @@ class OptionStr(Option): super().__init__(section, keyword, default_val, add=add, protect=protect) def get_float(self) -> float: - """ Return value converted to a float, allowing KMGT notation """ + """Return value converted to a float, allowing KMGT notation""" return sabnzbd.misc.from_units(self.get()) def get_int(self) -> int: - """ Return value converted to an int, allowing KMGT notation """ + """Return value converted to an int, allowing KMGT notation""" return int(self.get_float()) def set(self, value: Any) -> Optional[str]: - """ Set stripped value """ + """Set stripped value""" error = None if isinstance(value, str) and self.__strip: value = value.strip() @@ -351,46 +351,46 @@ class OptionStr(Option): return error def __call__(self) -> str: - """ get() replacement """ + """get() replacement""" return self.get() class OptionPassword(Option): - """ Password class. """ + """Password class.""" def __init__(self, section: str, keyword: str, default_val: str = "", add: bool = True): self.get_string = self.get_stars super().__init__(section, keyword, default_val, add=add) def get(self) -> Optional[str]: - """ Return decoded password """ + """Return decoded password""" return decode_password(super().get(), self.ident()) def get_stars(self) -> Optional[str]: - """ Return non-descript asterisk string """ + """Return non-descript asterisk string""" if self.get(): return "*" * 10 return "" def get_dict(self, safe: bool = False) -> Dict[str, str]: - """ Return value a dictionary """ + """Return value a dictionary""" if safe: return {self.ident()[1]: self.get_stars()} else: return {self.ident()[1]: self.get()} def set(self, pw: str): - """ Set password, encode it """ + """Set password, encode it""" if (pw is not None and pw == "") or (pw and pw.strip("*")): super().set(encode_password(pw)) def __call__(self) -> str: - """ get() replacement """ + """get() replacement""" return self.get() class ConfigServer: - """ Class defining a single server """ + """Class defining a single server""" def __init__(self, name, values): @@ -422,7 +422,7 @@ class ConfigServer: add_to_database("servers", self.__name, self) def set_dict(self, values: Dict[str, Any]): - """ Set one or more fields, passed as dictionary """ + """Set one or more fields, passed as dictionary""" # Replace usage_at_start value with most recent statistics if the user changes the quota value # Only when we are updating it from the Config if sabnzbd.WEBUI_READY and values.get("quota", "") != self.quota(): @@ -459,7 +459,7 @@ class ConfigServer: self.displayname.set(self.__name) def get_dict(self, safe: bool = False) -> Dict[str, Any]: - """ Return a dictionary with all attributes """ + """Return a dictionary with all attributes""" output_dict = {} output_dict["name"] = self.__name output_dict["displayname"] = self.displayname() @@ -487,11 +487,11 @@ class ConfigServer: return output_dict def delete(self): - """ Remove from database """ + """Remove from database""" delete_from_database("servers", self.__name) def rename(self, name: str): - """ Give server new display name """ + """Give server new display name""" self.displayname.set(name) def ident(self) -> Tuple[str, str]: @@ -499,7 +499,7 @@ class ConfigServer: class ConfigCat: - """ Class defining a single category """ + """Class defining a single category""" def __init__(self, name: str, values: Dict[str, Any]): self.__name = name @@ -516,7 +516,7 @@ class ConfigCat: add_to_database("categories", self.__name, self) def set_dict(self, values: Dict[str, Any]): - """ Set one or more fields, passed as dictionary """ + """Set one or more fields, passed as dictionary""" for kw in ("order", "pp", "script", "dir", "newzbin", "priority"): try: value = values[kw] @@ -525,7 +525,7 @@ class ConfigCat: continue def get_dict(self, safe: bool = False) -> Dict[str, Any]: - """ Return a dictionary with all attributes """ + """Return a dictionary with all attributes""" output_dict = {} output_dict["name"] = self.__name output_dict["order"] = self.order() @@ -537,19 +537,19 @@ class ConfigCat: return output_dict def delete(self): - """ Remove from database """ + """Remove from database""" delete_from_database("categories", self.__name) class OptionFilters(Option): - """ Filter list class """ + """Filter list class""" def __init__(self, section, keyword, add=True): super().__init__(section, keyword, add=add) self.set([]) def move(self, current: int, new: int): - """ Move filter from position 'current' to 'new' """ + """Move filter from position 'current' to 'new'""" lst = self.get() try: item = lst.pop(current) @@ -570,7 +570,7 @@ class OptionFilters(Option): self.set(lst) def delete(self, pos: int): - """ Remove filter 'pos' """ + """Remove filter 'pos'""" lst = self.get() try: lst.pop(pos) @@ -579,14 +579,14 @@ class OptionFilters(Option): self.set(lst) def get_dict(self, safe: bool = False) -> Dict[str, str]: - """ Return filter list as a dictionary with keys 'filter[0-9]+' """ + """Return filter list as a dictionary with keys 'filter[0-9]+'""" output_dict = {} for n, rss_filter in enumerate(self.get()): output_dict[f"filter{n}"] = rss_filter return output_dict def set_dict(self, values: Dict[str, Any]): - """ Create filter list from dictionary with keys 'filter[0-9]+' """ + """Create filter list from dictionary with keys 'filter[0-9]+'""" filters = [] # We don't know how many filters there are, so just assume all values are filters for n in range(len(values)): @@ -597,12 +597,12 @@ class OptionFilters(Option): self.set(filters) def __call__(self) -> List[List[str]]: - """ get() replacement """ + """get() replacement""" return self.get() class ConfigRSS: - """ Class defining a single Feed definition """ + """Class defining a single Feed definition""" def __init__(self, name, values): self.__name = name @@ -621,7 +621,7 @@ class ConfigRSS: add_to_database("rss", self.__name, self) def set_dict(self, values: Dict[str, Any]): - """ Set one or more fields, passed as dictionary """ + """Set one or more fields, passed as dictionary""" for kw in ("uri", "cat", "pp", "script", "priority", "enable"): try: value = values[kw] @@ -631,7 +631,7 @@ class ConfigRSS: self.filters.set_dict(values) def get_dict(self, safe: bool = False) -> Dict[str, Any]: - """ Return a dictionary with all attributes """ + """Return a dictionary with all attributes""" output_dict = {} output_dict["name"] = self.__name output_dict["uri"] = self.uri() @@ -646,11 +646,11 @@ class ConfigRSS: return output_dict def delete(self): - """ Remove from database """ + """Remove from database""" delete_from_database("rss", self.__name) def rename(self, new_name: str): - """ Update the name and the saved entries """ + """Update the name and the saved entries""" delete_from_database("rss", self.__name) sabnzbd.RSSReader.rename(self.__name, new_name) self.__name = new_name @@ -662,7 +662,7 @@ class ConfigRSS: @synchronized(CONFIG_LOCK) def add_to_database(section, keyword, obj): - """ add object as section/keyword to INI database """ + """add object as section/keyword to INI database""" global database if section not in database: database[section] = {} @@ -671,7 +671,7 @@ def add_to_database(section, keyword, obj): @synchronized(CONFIG_LOCK) def delete_from_database(section, keyword): - """ Remove section/keyword from INI database """ + """Remove section/keyword from INI database""" global database, CFG, modified del database[section][keyword] if section == "servers" and "[" in keyword: @@ -725,7 +725,7 @@ def get_dconfig(section, keyword, nested=False): def get_config(section, keyword): - """ Return a config object, based on 'section', 'keyword' """ + """Return a config object, based on 'section', 'keyword'""" try: return database[section][keyword] except KeyError: @@ -734,7 +734,7 @@ def get_config(section, keyword): def set_config(kwargs): - """ Set a config item, using values in dictionary """ + """Set a config item, using values in dictionary""" try: item = database[kwargs.get("section")][kwargs.get("keyword")] except KeyError: @@ -744,7 +744,7 @@ def set_config(kwargs): def delete(section: str, keyword: str): - """ Delete specific config item """ + """Delete specific config item""" try: database[section][keyword].delete() except KeyError: @@ -842,7 +842,7 @@ def _read_config(path, try_backup=False): @synchronized(SAVE_CONFIG_LOCK) def save_config(force=False): - """ Update Setup file with current option values """ + """Update Setup file with current option values""" global CFG, database, modified if not (modified or force): @@ -1025,7 +1025,7 @@ class ErrorCatchingArgumentParser(argparse.ArgumentParser): def encode_password(pw): - """ Encode password in hexadecimal if needed """ + """Encode password in hexadecimal if needed""" enc = False if pw: encPW = __PW_PREFIX @@ -1058,7 +1058,7 @@ def decode_password(pw, name): def clean_nice_ionice_parameters(value): - """ Verify that the passed parameters are not exploits """ + """Verify that the passed parameters are not exploits""" if value: parser = ErrorCatchingArgumentParser() @@ -1081,7 +1081,7 @@ def clean_nice_ionice_parameters(value): def all_lowercase(value): - """ Lowercase everything! """ + """Lowercase everything!""" if isinstance(value, list): # If list, for each item return None, [item.lower() for item in value] @@ -1089,7 +1089,7 @@ def all_lowercase(value): def validate_octal(value): - """ Check if string is valid octal number """ + """Check if string is valid octal number""" if not value: return None, value try: @@ -1100,7 +1100,7 @@ def validate_octal(value): def validate_no_unc(root, value, default): - """ Check if path isn't a UNC path """ + """Check if path isn't a UNC path""" # Only need to check the 'value' part if value and not value.startswith(r"\\"): return validate_notempty(root, value, default) @@ -1117,7 +1117,7 @@ def validate_safedir(root, value, default): def validate_notempty(root, value, default): - """ If value is empty, return default """ + """If value is empty, return default""" if value: return None, value else: @@ -1142,5 +1142,5 @@ def validate_single_tag(value: List[str]) -> Tuple[None, List[str]]: def create_api_key(): - """ Return a new randomized API_KEY """ + """Return a new randomized API_KEY""" return uuid.uuid4().hex diff --git a/sabnzbd/database.py b/sabnzbd/database.py index 84d13c3..ac04e29 100644 --- a/sabnzbd/database.py +++ b/sabnzbd/database.py @@ -41,7 +41,7 @@ DB_LOCK = threading.RLock() def convert_search(search): - """ Convert classic wildcard to SQL wildcard """ + """Convert classic wildcard to SQL wildcard""" if not search: # Default value search = "" @@ -75,14 +75,14 @@ class HistoryDB: @synchronized(DB_LOCK) def __init__(self): - """ Determine databse path and create connection """ + """Determine databse path and create connection""" self.con = self.c = None if not HistoryDB.db_path: HistoryDB.db_path = os.path.join(sabnzbd.cfg.admin_dir.get_path(), DB_HISTORY_NAME) self.connect() def connect(self): - """ Create a connection to the database """ + """Create a connection to the database""" create_table = not os.path.exists(HistoryDB.db_path) self.con = sqlite3.connect(HistoryDB.db_path) self.con.row_factory = sqlite3.Row @@ -117,7 +117,7 @@ class HistoryDB: ) def execute(self, command, args=(), save=False): - """ Wrapper for executing SQL commands """ + """Wrapper for executing SQL commands""" for tries in range(5, 0, -1): try: if args and isinstance(args, tuple): @@ -161,7 +161,7 @@ class HistoryDB: return False def create_history_db(self): - """ Create a new (empty) database file """ + """Create a new (empty) database file""" self.execute( """ CREATE TABLE "history" ( @@ -198,7 +198,7 @@ class HistoryDB: self.execute("PRAGMA user_version = 2;") def close(self): - """ Close database connection """ + """Close database connection""" try: self.c.close() self.con.close() @@ -207,7 +207,7 @@ class HistoryDB: logging.info("Traceback: ", exc_info=True) def remove_completed(self, search=None): - """ Remove all completed jobs from the database, optional with `search` pattern """ + """Remove all completed jobs from the database, optional with `search` pattern""" search = convert_search(search) logging.info("Removing all completed jobs from history") return self.execute( @@ -215,7 +215,7 @@ class HistoryDB: ) def get_failed_paths(self, search=None): - """ Return list of all storage paths of failed jobs (may contain non-existing or empty paths) """ + """Return list of all storage paths of failed jobs (may contain non-existing or empty paths)""" search = convert_search(search) fetch_ok = self.execute( """SELECT path FROM history WHERE name LIKE ? AND status = ?""", (search, Status.FAILED) @@ -226,7 +226,7 @@ class HistoryDB: return [] def remove_failed(self, search=None): - """ Remove all failed jobs from the database, optional with `search` pattern """ + """Remove all failed jobs from the database, optional with `search` pattern""" search = convert_search(search) logging.info("Removing all failed jobs from history") return self.execute( @@ -234,7 +234,7 @@ class HistoryDB: ) def remove_history(self, jobs=None): - """ Remove all jobs in the list `jobs`, empty list will remove all completed jobs """ + """Remove all jobs in the list `jobs`, empty list will remove all completed jobs""" if jobs is None: self.remove_completed() else: @@ -246,7 +246,7 @@ class HistoryDB: logging.info("[%s] Removing job %s from history", caller_name(), job) def auto_history_purge(self): - """ Remove history items based on the configured history-retention """ + """Remove history items based on the configured history-retention""" if sabnzbd.cfg.history_retention() == "0": return @@ -279,7 +279,7 @@ class HistoryDB: ) def add_history_db(self, nzo, storage="", postproc_time=0, script_output="", script_line=""): - """ Add a new job entry to the database """ + """Add a new job entry to the database""" t = build_history_info(nzo, storage, postproc_time, script_output, script_line, series_info=True) self.execute( @@ -301,7 +301,7 @@ class HistoryDB: categories: Optional[List[str]] = None, nzo_ids: Optional[List[str]] = None, ): - """ Return records for specified jobs """ + """Return records for specified jobs""" command_args = [convert_search(search)] post = "" @@ -346,7 +346,7 @@ class HistoryDB: return items, fetched_items, total_items def have_episode(self, series, season, episode): - """ Check whether History contains this series episode """ + """Check whether History contains this series episode""" total = 0 series = series.lower().replace(".", " ").replace("_", " ").replace(" ", " ") if series and season and episode: @@ -358,7 +358,7 @@ class HistoryDB: return total > 0 def have_name_or_md5sum(self, name, md5sum): - """ Check whether this name or md5sum is already in History """ + """Check whether this name or md5sum is already in History""" total = 0 if self.execute( """SELECT COUNT(*) FROM History WHERE ( LOWER(name) = LOWER(?) OR md5sum = ? ) AND STATUS != ?""", @@ -393,7 +393,7 @@ class HistoryDB: return total, month, week def get_script_log(self, nzo_id): - """ Return decompressed log file """ + """Return decompressed log file""" data = "" t = (nzo_id,) if self.execute("""SELECT script_log FROM history WHERE nzo_id = ?""", t): @@ -404,7 +404,7 @@ class HistoryDB: return data def get_name(self, nzo_id): - """ Return name of the job `nzo_id` """ + """Return name of the job `nzo_id`""" t = (nzo_id,) name = "" if self.execute("""SELECT name FROM history WHERE nzo_id = ?""", t): @@ -416,7 +416,7 @@ class HistoryDB: return name def get_path(self, nzo_id: str): - """ Return the `incomplete` path of the job `nzo_id` if it is still there """ + """Return the `incomplete` path of the job `nzo_id` if it is still there""" t = (nzo_id,) path = "" if self.execute("""SELECT path FROM history WHERE nzo_id = ?""", t): @@ -430,7 +430,7 @@ class HistoryDB: return None def get_other(self, nzo_id): - """ Return additional data for job `nzo_id` """ + """Return additional data for job `nzo_id`""" t = (nzo_id,) if self.execute("""SELECT * FROM history WHERE nzo_id = ?""", t): try: @@ -442,11 +442,11 @@ class HistoryDB: return "", "", "", "", "" def __enter__(self): - """ For context manager support """ + """For context manager support""" return self def __exit__(self, exc_type, exc_val, exc_tb): - """ For context manager support, ignore any exception """ + """For context manager support, ignore any exception""" self.close() @@ -454,7 +454,7 @@ _PP_LOOKUP = {0: "", 1: "R", 2: "U", 3: "D"} def build_history_info(nzo, workdir_complete="", postproc_time=0, script_output="", script_line="", series_info=False): - """ Collects all the information needed for the database """ + """Collects all the information needed for the database""" completed = int(time.time()) pp = _PP_LOOKUP.get(opts_to_pp(*nzo.repair_opts), "X") diff --git a/sabnzbd/decoder.py b/sabnzbd/decoder.py index c853595..438f53b 100644 --- a/sabnzbd/decoder.py +++ b/sabnzbd/decoder.py @@ -59,7 +59,7 @@ class BadYenc(Exception): class Decoder: - """ Implement thread-like coordinator for the decoders """ + """Implement thread-like coordinator for the decoders""" def __init__(self): logging.debug("Initializing decoders") @@ -106,7 +106,7 @@ class Decoder: class DecoderWorker(Thread): - """ The actuall workhorse that handles decoding! """ + """The actuall workhorse that handles decoding!""" def __init__(self, decoder_queue): super().__init__() @@ -246,7 +246,7 @@ def decode(article: Article, raw_data: List[bytes]) -> bytes: def search_new_server(article: Article) -> bool: - """ Shorthand for searching new server or else increasing bad_articles """ + """Shorthand for searching new server or else increasing bad_articles""" # Continue to the next one if we found new server if not article.search_new_server(): # Increase bad articles if no new server was found diff --git a/sabnzbd/deobfuscate_filenames.py b/sabnzbd/deobfuscate_filenames.py index a1eb826..9218a7b 100755 --- a/sabnzbd/deobfuscate_filenames.py +++ b/sabnzbd/deobfuscate_filenames.py @@ -42,7 +42,7 @@ MIN_FILE_SIZE = 10 * 1024 * 1024 def decode_par2(parfile): - """ Parse a par2 file and rename files listed in the par2 to their real name """ + """Parse a par2 file and rename files listed in the par2 to their real name""" # Check if really a par2 file if not is_parfile(parfile): logging.info("Par2 file %s was not really a par2 file") @@ -132,7 +132,7 @@ def is_probably_obfuscated(myinputfilename): def deobfuscate_list(filelist, usefulname): - """ Check all files in filelist, and if wanted, deobfuscate: rename to filename based on usefulname""" + """Check all files in filelist, and if wanted, deobfuscate: rename to filename based on usefulname""" # to be sure, only keep really exsiting files: filelist = [f for f in filelist if os.path.exists(f)] diff --git a/sabnzbd/directunpacker.py b/sabnzbd/directunpacker.py index 75c4983..e8f7fe6 100644 --- a/sabnzbd/directunpacker.py +++ b/sabnzbd/directunpacker.py @@ -106,7 +106,7 @@ class DirectUnpacker(threading.Thread): return True def set_volumes_for_nzo(self): - """ Loop over all files to detect the names """ + """Loop over all files to detect the names""" none_counter = 0 found_counter = 0 for nzf in self.nzo.files + self.nzo.finished_files: @@ -126,7 +126,7 @@ class DirectUnpacker(threading.Thread): @synchronized(START_STOP_LOCK) def add(self, nzf: NzbFile): - """ Add jobs and start instance of DirectUnpack """ + """Add jobs and start instance of DirectUnpack""" if not cfg.direct_unpack_tested(): test_disk_performance() @@ -350,7 +350,7 @@ class DirectUnpacker(threading.Thread): @synchronized(START_STOP_LOCK) def create_unrar_instance(self): - """ Start the unrar instance using the user's options """ + """Start the unrar instance using the user's options""" # Generate extraction path and save for post-proc if not self.unpack_dir_info: try: @@ -432,7 +432,7 @@ class DirectUnpacker(threading.Thread): @synchronized(START_STOP_LOCK) def abort(self): - """ Abort running instance and delete generated files """ + """Abort running instance and delete generated files""" if not self.killed and self.cur_setname: logging.info("Aborting DirectUnpack for %s", self.cur_setname) self.killed = True @@ -494,7 +494,7 @@ class DirectUnpacker(threading.Thread): self.reset_active() def get_formatted_stats(self): - """ Get percentage or number of rar's done """ + """Get percentage or number of rar's done""" if self.cur_setname and self.cur_setname in self.total_volumes: # This won't work on obfuscated posts if self.total_volumes[self.cur_setname] >= self.cur_volume and self.cur_volume: @@ -520,7 +520,7 @@ def analyze_rar_filename(filename): def abort_all(): - """ Abort all running DirectUnpackers """ + """Abort all running DirectUnpackers""" logging.info("Aborting all DirectUnpackers") for direct_unpacker in ACTIVE_UNPACKERS: direct_unpacker.abort() diff --git a/sabnzbd/dirscanner.py b/sabnzbd/dirscanner.py index 3afc23e..eb64730 100644 --- a/sabnzbd/dirscanner.py +++ b/sabnzbd/dirscanner.py @@ -32,7 +32,7 @@ import sabnzbd.cfg as cfg def compare_stat_tuple(tup1, tup2): - """ Test equality of two stat-tuples, content-related parts only """ + """Test equality of two stat-tuples, content-related parts only""" if tup1.st_ino != tup2.st_ino: return False if tup1.st_size != tup2.st_size: @@ -45,7 +45,7 @@ def compare_stat_tuple(tup1, tup2): def clean_file_list(inp_list, folder, files): - """ Remove elements of "inp_list" not found in "files" """ + """Remove elements of "inp_list" not found in "files" """ for path in sorted(inp_list): fld, name = os.path.split(path) if fld == folder: @@ -89,31 +89,31 @@ class DirScanner(threading.Thread): cfg.dirscan_speed.callback(self.newspeed) def newdir(self): - """ We're notified of a dir change """ + """We're notified of a dir change""" self.ignored = {} self.suspected = {} self.dirscan_dir = cfg.dirscan_dir.get_path() self.dirscan_speed = cfg.dirscan_speed() def newspeed(self): - """ We're notified of a scan speed change """ + """We're notified of a scan speed change""" # If set to 0, use None so the wait() is forever self.dirscan_speed = cfg.dirscan_speed() or None with self.loop_condition: self.loop_condition.notify() def stop(self): - """ Stop the dir scanner """ + """Stop the dir scanner""" self.shutdown = True with self.loop_condition: self.loop_condition.notify() def save(self): - """ Save dir scanner bookkeeping """ + """Save dir scanner bookkeeping""" sabnzbd.save_admin((self.dirscan_dir, self.ignored, self.suspected), SCAN_FILE_NAME) def run(self): - """ Start the scanner """ + """Start the scanner""" logging.info("Dirscanner starting up") self.shutdown = False @@ -125,7 +125,7 @@ class DirScanner(threading.Thread): self.scan() def scan(self): - """ Do one scan of the watched folder """ + """Do one scan of the watched folder""" def run_dir(folder, catdir): try: diff --git a/sabnzbd/downloader.py b/sabnzbd/downloader.py index 340aeb9..12b14c4 100644 --- a/sabnzbd/downloader.py +++ b/sabnzbd/downloader.py @@ -163,7 +163,7 @@ class Server: Thread(target=self._request_info_internal).start() def _request_info_internal(self): - """ Async attempt to run getaddrinfo() for specified server """ + """Async attempt to run getaddrinfo() for specified server""" logging.debug("Retrieving server address information for %s", self.host) self.info = get_server_addrinfo(self.host, self.port) if not self.info: @@ -178,7 +178,7 @@ class Server: class Downloader(Thread): - """ Singleton Downloader Thread """ + """Singleton Downloader Thread""" def __init__(self, paused=False): super().__init__() @@ -284,17 +284,17 @@ class Downloader(Thread): self.server_nr = len(self.servers) def add_socket(self, fileno: int, nw: NewsWrapper): - """ Add a socket ready to be used to the list to be watched """ + """Add a socket ready to be used to the list to be watched""" self.read_fds[fileno] = nw def remove_socket(self, nw: NewsWrapper): - """ Remove a socket to be watched """ + """Remove a socket to be watched""" if nw.nntp: self.read_fds.pop(nw.nntp.fileno, None) @NzbQueueLocker def set_paused_state(self, state: bool): - """ Set downloader to specified paused state """ + """Set downloader to specified paused state""" self.paused = state @NzbQueueLocker @@ -307,7 +307,7 @@ class Downloader(Thread): @NzbQueueLocker def pause(self): - """ Pause the downloader, optionally saving admin """ + """Pause the downloader, optionally saving admin""" if not self.paused: self.paused = True logging.info("Pausing") @@ -887,7 +887,7 @@ class Downloader(Thread): @synchronized(TIMER_LOCK) def plan_server(self, server: Server, interval: int): - """ Plan the restart of a server in 'interval' minutes """ + """Plan the restart of a server in 'interval' minutes""" if cfg.no_penalties() and interval > _PENALTY_SHORT: # Overwrite in case of no_penalties interval = _PENALTY_SHORT @@ -902,7 +902,7 @@ class Downloader(Thread): @synchronized(TIMER_LOCK) def trigger_server(self, server_id: str, timestamp: float): - """ Called by scheduler, start server if timer still valid """ + """Called by scheduler, start server if timer still valid""" logging.debug("Trigger planned server resume for server-id %s", server_id) if server_id in self.timers: if timestamp in self.timers[server_id]: @@ -931,7 +931,7 @@ class Downloader(Thread): @NzbQueueLocker @synchronized(TIMER_LOCK) def check_timers(self): - """ Make sure every server without a non-expired timer is active """ + """Make sure every server without a non-expired timer is active""" # Clean expired timers now = time.time() kicked = [] @@ -957,18 +957,18 @@ class Downloader(Thread): @NzbQueueLocker def wakeup(self): - """ Just rattle the semaphore """ + """Just rattle the semaphore""" pass @NzbQueueLocker def stop(self): - """ Shutdown, wrapped so the semaphore is notified """ + """Shutdown, wrapped so the semaphore is notified""" self.shutdown = True sabnzbd.notifier.send_notification("SABnzbd", T("Shutting down"), "startup") def clues_login(text: str) -> bool: - """ Check for any "failed login" clues in the response code """ + """Check for any "failed login" clues in the response code""" text = text.lower() for clue in ("username", "password", "invalid", "authen", "access denied"): if clue in text: @@ -977,7 +977,7 @@ def clues_login(text: str) -> bool: def clues_too_many(text: str) -> bool: - """ Check for any "too many connections" clues in the response code """ + """Check for any "too many connections" clues in the response code""" text = text.lower() for clue in ("exceed", "connections", "too many", "threads", "limit"): # Not 'download limit exceeded' error @@ -987,7 +987,7 @@ def clues_too_many(text: str) -> bool: def clues_too_many_ip(text: str) -> bool: - """ Check for any "account sharing" clues in the response code """ + """Check for any "account sharing" clues in the response code""" text = text.lower() for clue in ("simultaneous ip", "multiple ip"): if clue in text: @@ -996,7 +996,7 @@ def clues_too_many_ip(text: str) -> bool: def clues_pay(text: str) -> bool: - """ Check for messages about payments """ + """Check for messages about payments""" text = text.lower() for clue in ("credits", "paym", "expired", "exceeded"): if clue in text: diff --git a/sabnzbd/emailer.py b/sabnzbd/emailer.py index 6e8076e..aff17c7 100644 --- a/sabnzbd/emailer.py +++ b/sabnzbd/emailer.py @@ -44,14 +44,14 @@ def errormsg(msg): def get_email_date(): - """ Return un-localized date string for the Date: field """ + """Return un-localized date string for the Date: field""" # Get locale independent date/time string: "Sun May 22 20:15:12 2011" day, month, dayno, hms, year = time.asctime(time.gmtime()).split() return "%s, %s %s %s %s +0000" % (day, dayno, month, year, hms) def send_email(message, email_to, test=None): - """ Send message if message non-empty and email-parms are set """ + """Send message if message non-empty and email-parms are set""" # we should not use CFG if we are testing. we should use values # from UI instead. # email_to is replaced at send_with_template, since it can be an array @@ -153,7 +153,7 @@ def send_email(message, email_to, test=None): def send_with_template(prefix, parm, test=None): - """ Send an email using template """ + """Send an email using template""" parm["from"] = cfg.email_from() parm["date"] = get_email_date() @@ -203,7 +203,7 @@ def send_with_template(prefix, parm, test=None): def endjob( filename, cat, status, path, bytes_downloaded, fail_msg, stages, script, script_output, script_ret, test=None ): - """ Send end-of-job email """ + """Send end-of-job email""" # Is it allowed? if not check_cat("misc", cat, keyword="email") and not test: return None @@ -241,19 +241,19 @@ def endjob( def rss_mail(feed, jobs): - """ Send notification email containing list of files """ + """Send notification email containing list of files""" parm = {"amount": len(jobs), "feed": feed, "jobs": jobs} return send_with_template("rss", parm) def badfetch_mail(msg, url): - """ Send notification email about failed NZB fetch """ + """Send notification email about failed NZB fetch""" parm = {"url": url, "msg": msg} return send_with_template("badfetch", parm) def diskfull_mail(): - """ Send email about disk full, no templates """ + """Send email about disk full, no templates""" if cfg.email_full(): return send_email( T( @@ -277,7 +277,7 @@ Please make room and resume SABnzbd manually. def _prepare_message(txt): - """ Parse the headers in the template to real headers """ + """Parse the headers in the template to real headers""" msg = EmailMessage() payload = [] body = False diff --git a/sabnzbd/encoding.py b/sabnzbd/encoding.py index 5d3e14c..bf34f7b 100644 --- a/sabnzbd/encoding.py +++ b/sabnzbd/encoding.py @@ -28,14 +28,14 @@ CODEPAGE = locale.getpreferredencoding() def utob(str_in: AnyStr) -> bytes: - """ Shorthand for converting UTF-8 string to bytes """ + """Shorthand for converting UTF-8 string to bytes""" if isinstance(str_in, bytes): return str_in return str_in.encode("utf-8") def ubtou(str_in: AnyStr) -> str: - """ Shorthand for converting unicode bytes to UTF-8 string """ + """Shorthand for converting unicode bytes to UTF-8 string""" if not isinstance(str_in, bytes): return str_in return str_in.decode("utf-8") @@ -78,5 +78,5 @@ def correct_unknown_encoding(str_or_bytes_in: AnyStr) -> str: def xml_name(p): - """ Prepare name for use in HTML/XML contect """ + """Prepare name for use in HTML/XML contect""" return escape(str(p)) diff --git a/sabnzbd/filesystem.py b/sabnzbd/filesystem.py index 9a358dc..c1c3ea5 100644 --- a/sabnzbd/filesystem.py +++ b/sabnzbd/filesystem.py @@ -52,7 +52,7 @@ else: def get_ext(filename: str) -> str: - """ Return lowercased file extension """ + """Return lowercased file extension""" try: return os.path.splitext(filename)[1].lower() except: @@ -60,7 +60,7 @@ def get_ext(filename: str) -> str: def has_unwanted_extension(filename: str) -> bool: - """ Determine if a filename has an unwanted extension, given the configured mode """ + """Determine if a filename has an unwanted extension, given the configured mode""" extension = get_ext(filename).replace(".", "") if extension and sabnzbd.cfg.unwanted_extensions(): return ( @@ -77,7 +77,7 @@ def has_unwanted_extension(filename: str) -> bool: def get_filename(path: str) -> str: - """ Return path without the file extension """ + """Return path without the file extension""" try: return os.path.split(path)[1] except: @@ -85,12 +85,12 @@ def get_filename(path: str) -> str: def setname_from_path(path: str) -> str: - """ Get the setname from a path """ + """Get the setname from a path""" return os.path.splitext(os.path.basename(path))[0] def is_writable(path: str) -> bool: - """ Return True is file is writable (also when non-existent) """ + """Return True is file is writable (also when non-existent)""" if os.path.isfile(path): return bool(os.stat(path).st_mode & stat.S_IWUSR) else: @@ -267,7 +267,7 @@ def sanitize_foldername(name: str) -> str: def sanitize_and_trim_path(path: str) -> str: - """ Remove illegal characters and trim element size """ + """Remove illegal characters and trim element size""" path = path.strip() new_path = "" if sabnzbd.WIN32: @@ -470,7 +470,7 @@ def safe_fnmatch(f: str, pattern: str) -> bool: def globber(path: str, pattern: str = "*") -> List[str]: - """ Return matching base file/folder names in folder `path` """ + """Return matching base file/folder names in folder `path`""" # Cannot use glob.glob() because it doesn't support Windows long name notation if os.path.exists(path): return [f for f in os.listdir(path) if safe_fnmatch(f, pattern)] @@ -478,7 +478,7 @@ def globber(path: str, pattern: str = "*") -> List[str]: def globber_full(path: str, pattern: str = "*") -> List[str]: - """ Return matching full file/folder names in folder `path` """ + """Return matching full file/folder names in folder `path`""" # Cannot use glob.glob() because it doesn't support Windows long name notation if os.path.exists(path): return [os.path.join(path, f) for f in os.listdir(path) if safe_fnmatch(f, pattern)] @@ -502,12 +502,12 @@ def fix_unix_encoding(folder: str): def is_valid_script(basename: str) -> bool: - """ Determine if 'basename' is a valid script """ + """Determine if 'basename' is a valid script""" return basename in list_scripts(default=False, none=False) def list_scripts(default: bool = False, none: bool = True) -> List[str]: - """ Return a list of script names, optionally with 'Default' added """ + """Return a list of script names, optionally with 'Default' added""" lst = [] path = sabnzbd.cfg.script_dir.get_path() if path and os.access(path, os.R_OK): @@ -533,7 +533,7 @@ def list_scripts(default: bool = False, none: bool = True) -> List[str]: def make_script_path(script: str) -> Optional[str]: - """ Return full script path, if any valid script exists, else None """ + """Return full script path, if any valid script exists, else None""" script_path = None script_dir = sabnzbd.cfg.script_dir.get_path() if script_dir and script: @@ -558,7 +558,7 @@ def get_admin_path(name: str, future: bool): def set_chmod(path: str, permissions: int, report: bool): - """ Set 'permissions' on 'path', report any errors when 'report' is True """ + """Set 'permissions' on 'path', report any errors when 'report' is True""" try: logging.debug("Applying permissions %s (octal) to %s", oct(permissions), path) os.chmod(path, permissions) @@ -570,7 +570,7 @@ def set_chmod(path: str, permissions: int, report: bool): def set_permissions(path: str, recursive: bool = True): - """ Give folder tree and its files their proper permissions """ + """Give folder tree and its files their proper permissions""" if not sabnzbd.WIN32: umask = sabnzbd.cfg.umask() try: @@ -615,14 +615,14 @@ def userxbit(filename: str) -> bool: def clip_path(path: str) -> str: - r""" Remove \\?\ or \\?\UNC\ prefix from Windows path """ + r"""Remove \\?\ or \\?\UNC\ prefix from Windows path""" if sabnzbd.WIN32 and path and "?" in path: path = path.replace("\\\\?\\UNC\\", "\\\\", 1).replace("\\\\?\\", "", 1) return path def long_path(path: str) -> str: - """ For Windows, convert to long style path; others, return same path """ + """For Windows, convert to long style path; others, return same path""" if sabnzbd.WIN32 and path and not path.startswith("\\\\?\\"): if path.startswith("\\\\"): # Special form for UNC paths @@ -679,7 +679,7 @@ def create_all_dirs(path: str, apply_umask: bool = False) -> Union[str, bool]: @synchronized(DIR_LOCK) def get_unique_path(dirpath: str, n: int = 0, create_dir: bool = True) -> str: - """ Determine a unique folder or filename """ + """Determine a unique folder or filename""" if not check_mount(dirpath): return dirpath @@ -714,7 +714,7 @@ def get_unique_filename(path: str) -> str: @synchronized(DIR_LOCK) def listdir_full(input_dir: str, recursive: bool = True) -> List[str]: - """ List all files in dirs and sub-dirs """ + """List all files in dirs and sub-dirs""" filelist = [] for root, dirs, files in os.walk(input_dir): for file in files: @@ -768,7 +768,7 @@ def move_to_path(path: str, new_path: str) -> Tuple[bool, Optional[str]]: @synchronized(DIR_LOCK) def cleanup_empty_directories(path: str): - """ Remove all empty folders inside (and including) 'path' """ + """Remove all empty folders inside (and including) 'path'""" path = os.path.normpath(path) while 1: repeat = False @@ -792,7 +792,7 @@ def cleanup_empty_directories(path: str): @synchronized(DIR_LOCK) def get_filepath(path: str, nzo, filename: str): - """ Create unique filepath """ + """Create unique filepath""" # This procedure is only used by the Assembler thread # It does no umask setting # It uses the dir_lock for the (rare) case that the @@ -886,14 +886,14 @@ def renamer(old: str, new: str, create_local_directories: bool = False): def remove_file(path: str): - """ Wrapper function so any file removal is logged """ + """Wrapper function so any file removal is logged""" logging.debug("[%s] Deleting file %s", sabnzbd.misc.caller_name(), path) os.remove(path) @synchronized(DIR_LOCK) def remove_dir(path: str): - """ Remove directory with retries for Win32 """ + """Remove directory with retries for Win32""" logging.debug("[%s] Removing dir %s", sabnzbd.misc.caller_name(), path) if sabnzbd.WIN32: retries = 15 @@ -916,7 +916,7 @@ def remove_dir(path: str): @synchronized(DIR_LOCK) def remove_all(path: str, pattern: str = "*", keep_folder: bool = False, recursive: bool = False): - """ Remove folder and all its content (optionally recursive) """ + """Remove folder and all its content (optionally recursive)""" if path and os.path.exists(path): # Fast-remove the whole tree if recursive if pattern == "*" and not keep_folder and recursive: @@ -994,7 +994,7 @@ def disk_free_macos_clib_statfs64(directory: str) -> Tuple[int, int]: def diskspace_base(dir_to_check: str) -> Tuple[float, float]: - """ Return amount of free and used diskspace in GBytes """ + """Return amount of free and used diskspace in GBytes""" # Find first folder level that exists in the path x = "x" while x and not os.path.exists(dir_to_check): @@ -1038,7 +1038,7 @@ __LAST_DISK_CALL = 0 def diskspace(force: bool = False) -> Dict[str, Tuple[float, float]]: - """ Wrapper to cache results """ + """Wrapper to cache results""" global __DIRS_CHECKED, __DISKS_SAME, __LAST_DISK_RESULT, __LAST_DISK_CALL # Reset everything when folders changed diff --git a/sabnzbd/getipaddress.py b/sabnzbd/getipaddress.py index 8930716..928e6e4 100644 --- a/sabnzbd/getipaddress.py +++ b/sabnzbd/getipaddress.py @@ -31,14 +31,14 @@ from sabnzbd.encoding import ubtou def timeout(max_timeout): - """ Timeout decorator, parameter in seconds. """ + """Timeout decorator, parameter in seconds.""" def timeout_decorator(item): - """ Wrap the original function. """ + """Wrap the original function.""" @functools.wraps(item) def func_wrapper(*args, **kwargs): - """ Closure for function. """ + """Closure for function.""" with multiprocessing.pool.ThreadPool(processes=1) as pool: async_result = pool.apply_async(item, args, kwargs) # raises a TimeoutError if execution exceeds max_timeout diff --git a/sabnzbd/interface.py b/sabnzbd/interface.py index ba6fc63..4ed5132 100644 --- a/sabnzbd/interface.py +++ b/sabnzbd/interface.py @@ -99,7 +99,7 @@ def secured_expose( check_api_key: bool = False, access_type: int = 4, ) -> Union[Callable, str]: - """ Wrapper for both cherrypy.expose and login/access check """ + """Wrapper for both cherrypy.expose and login/access check""" if not wrap_func: return functools.partial( secured_expose, @@ -306,12 +306,12 @@ def check_login(): def check_basic_auth(_, username, password): - """ CherryPy basic authentication validation """ + """CherryPy basic authentication validation""" return username == cfg.username() and password == cfg.password() def set_auth(conf): - """ Set the authentication for CherryPy """ + """Set the authentication for CherryPy""" if cfg.username() and cfg.password() and not cfg.html_login(): conf.update( { @@ -379,7 +379,7 @@ def check_apikey(kwargs): def log_warning_and_ip(txt): - """ Include the IP and the Proxy-IP for warnings """ + """Include the IP and the Proxy-IP for warnings""" if cfg.api_warnings(): logging.warning("%s %s", txt, cherrypy.request.remote_label) @@ -487,12 +487,12 @@ class MainPage: @secured_expose(check_api_key=True, access_type=1) def api(self, **kwargs): - """ Redirect to API-handler, we check the access_type in the API-handler """ + """Redirect to API-handler, we check the access_type in the API-handler""" return api_handler(kwargs) @secured_expose def scriptlog(self, **kwargs): - """ Needed for all skins, URL is fixed due to postproc """ + """Needed for all skins, URL is fixed due to postproc""" # No session key check, due to fixed URLs name = kwargs.get("name") if name: @@ -503,7 +503,7 @@ class MainPage: @secured_expose(check_api_key=True) def retry(self, **kwargs): - """ Duplicate of retry of History, needed for some skins """ + """Duplicate of retry of History, needed for some skins""" job = kwargs.get("job", "") url = kwargs.get("url", "").strip() pp = kwargs.get("pp") @@ -522,13 +522,13 @@ class MainPage: @secured_expose def robots_txt(self, **kwargs): - """ Keep web crawlers out """ + """Keep web crawlers out""" cherrypy.response.headers["Content-Type"] = "text/plain" return "User-agent: *\nDisallow: /\n" @secured_expose def description_xml(self, **kwargs): - """ Provide the description.xml which was broadcast via SSDP """ + """Provide the description.xml which was broadcast via SSDP""" if is_lan_addr(cherrypy.request.remote.ip): cherrypy.response.headers["Content-Type"] = "application/xml" return utob(sabnzbd.utils.ssdp.server_ssdp_xml()) @@ -543,7 +543,7 @@ class Wizard: @secured_expose(check_configlock=True) def index(self, **kwargs): - """ Show the language selection page """ + """Show the language selection page""" if sabnzbd.WIN32: from sabnzbd.utils.apireg import get_install_lng @@ -559,7 +559,7 @@ class Wizard: @secured_expose(check_configlock=True) def one(self, **kwargs): - """ Accept language and show server page """ + """Accept language and show server page""" if kwargs.get("lang"): cfg.language.set(kwargs.get("lang")) @@ -605,7 +605,7 @@ class Wizard: @secured_expose(check_configlock=True) def two(self, **kwargs): - """ Accept server and show the final page for restart """ + """Accept server and show the final page for restart""" # Save server details if kwargs: kwargs["enable"] = 1 @@ -627,13 +627,13 @@ class Wizard: @secured_expose def exit(self, **kwargs): - """ Stop SABnzbd """ + """Stop SABnzbd""" sabnzbd.shutdown_program() return T("SABnzbd shutdown finished") def get_access_info(): - """ Build up a list of url's that sabnzbd can be accessed from """ + """Build up a list of url's that sabnzbd can be accessed from""" # Access_url is used to provide the user a link to SABnzbd depending on the host cherryhost = cfg.cherryhost() host = socket.gethostname().lower() @@ -1680,7 +1680,7 @@ class ConfigServer: def unique_svr_name(server): - """ Return a unique variant on given server name """ + """Return a unique variant on given server name""" num = 0 svr = 1 new_name = server @@ -1695,7 +1695,7 @@ def unique_svr_name(server): def check_server(host, port, ajax): - """ Check if server address resolves properly """ + """Check if server address resolves properly""" if host.lower() == "localhost" and sabnzbd.AMBI_LOCALHOST: return badParameterResponse(T("Warning: LOCALHOST is ambiguous, use numerical IP-address."), ajax) @@ -1706,7 +1706,7 @@ def check_server(host, port, ajax): def handle_server(kwargs, root=None, new_svr=False): - """ Internal server handler """ + """Internal server handler""" ajax = kwargs.get("ajax") host = kwargs.get("host", "").strip() if not host: @@ -1857,7 +1857,7 @@ class ConfigRss: @secured_expose(check_api_key=True, check_configlock=True) def save_rss_rate(self, **kwargs): - """ Save changed RSS automatic readout rate """ + """Save changed RSS automatic readout rate""" cfg.rss_rate.set(kwargs.get("rss_rate")) config.save_config() sabnzbd.Scheduler.restart() @@ -1886,7 +1886,7 @@ class ConfigRss: @secured_expose(check_api_key=True, check_configlock=True) def save_rss_feed(self, **kwargs): - """ Update Feed level attributes """ + """Update Feed level attributes""" feed_name = kwargs.get("feed") try: cf = config.get_rss()[feed_name] @@ -1912,7 +1912,7 @@ class ConfigRss: @secured_expose(check_api_key=True, check_configlock=True) def toggle_rss_feed(self, **kwargs): - """ Toggle automatic read-out flag of Feed """ + """Toggle automatic read-out flag of Feed""" try: item = config.get_rss()[kwargs.get("feed")] except KeyError: @@ -1927,7 +1927,7 @@ class ConfigRss: @secured_expose(check_api_key=True, check_configlock=True) def add_rss_feed(self, **kwargs): - """ Add one new RSS feed definition """ + """Add one new RSS feed definition""" feed = Strip(kwargs.get("feed")).strip("[]") uri = Strip(kwargs.get("uri")) if feed and uri: @@ -1956,11 +1956,11 @@ class ConfigRss: @secured_expose(check_api_key=True, check_configlock=True) def upd_rss_filter(self, **kwargs): - """ Wrapper, so we can call from api.py """ + """Wrapper, so we can call from api.py""" self.internal_upd_rss_filter(**kwargs) def internal_upd_rss_filter(self, **kwargs): - """ Save updated filter definition """ + """Save updated filter definition""" try: feed_cfg = config.get_rss()[kwargs.get("feed")] except KeyError: @@ -1993,7 +1993,7 @@ class ConfigRss: @secured_expose(check_api_key=True, check_configlock=True) def del_rss_feed(self, *args, **kwargs): - """ Remove complete RSS feed """ + """Remove complete RSS feed""" kwargs["section"] = "rss" kwargs["keyword"] = kwargs.get("feed") del_from_section(kwargs) @@ -2002,11 +2002,11 @@ class ConfigRss: @secured_expose(check_api_key=True, check_configlock=True) def del_rss_filter(self, **kwargs): - """ Wrapper, so we can call from api.py """ + """Wrapper, so we can call from api.py""" self.internal_del_rss_filter(**kwargs) def internal_del_rss_filter(self, **kwargs): - """ Remove one RSS filter """ + """Remove one RSS filter""" try: feed_cfg = config.get_rss()[kwargs.get("feed")] except KeyError: @@ -2020,7 +2020,7 @@ class ConfigRss: @secured_expose(check_api_key=True, check_configlock=True) def download_rss_feed(self, *args, **kwargs): - """ Force download of all matching jobs in a feed """ + """Force download of all matching jobs in a feed""" if "feed" in kwargs: feed = kwargs["feed"] self.__refresh_readout = feed @@ -2032,14 +2032,14 @@ class ConfigRss: @secured_expose(check_api_key=True, check_configlock=True) def clean_rss_jobs(self, *args, **kwargs): - """ Remove processed RSS jobs from UI """ + """Remove processed RSS jobs from UI""" sabnzbd.RSSReader.clear_downloaded(kwargs["feed"]) self.__evaluate = True raise rssRaiser(self.__root, kwargs) @secured_expose(check_api_key=True, check_configlock=True) def test_rss_feed(self, *args, **kwargs): - """ Read the feed content again and show results """ + """Read the feed content again and show results""" if "feed" in kwargs: feed = kwargs["feed"] self.__refresh_readout = feed @@ -2052,7 +2052,7 @@ class ConfigRss: @secured_expose(check_api_key=True, check_configlock=True) def eval_rss_feed(self, *args, **kwargs): - """ Re-apply the filters to the feed """ + """Re-apply the filters to the feed""" if "feed" in kwargs: self.__refresh_download = False self.__refresh_force = False @@ -2064,7 +2064,7 @@ class ConfigRss: @secured_expose(check_api_key=True, check_configlock=True) def download(self, **kwargs): - """ Download NZB from provider (Download button) """ + """Download NZB from provider (Download button)""" feed = kwargs.get("feed") url = kwargs.get("url") nzbname = kwargs.get("nzbname") @@ -2083,13 +2083,13 @@ class ConfigRss: @secured_expose(check_api_key=True, check_configlock=True) def rss_now(self, *args, **kwargs): - """ Run an automatic RSS run now """ + """Run an automatic RSS run now""" sabnzbd.Scheduler.force_rss() raise Raiser(self.__root) def ConvertSpecials(p): - """ Convert None to 'None' and 'Default' to '' """ + """Convert None to 'None' and 'Default' to ''""" if p is None: p = "None" elif p.lower() == T("Default").lower(): @@ -2098,12 +2098,12 @@ def ConvertSpecials(p): def IsNone(value): - """ Return True if either None, 'None' or '' """ + """Return True if either None, 'None' or ''""" return value is None or value == "" or value.lower() == "none" def Strip(txt): - """ Return stripped string, can handle None """ + """Return stripped string, can handle None""" try: return txt.strip() except: @@ -2619,7 +2619,7 @@ def orphan_add_all(): def badParameterResponse(msg, ajax=None): - """ Return a html page with error message and a 'back' button """ + """Return a html page with error message and a 'back' button""" if ajax: return sabnzbd.api.report("json", error=msg) else: @@ -2646,7 +2646,7 @@ def badParameterResponse(msg, ajax=None): def ShowString(name, msg): - """ Return a html page listing a file and a 'back' button """ + """Return a html page listing a file and a 'back' button""" return """ diff --git a/sabnzbd/lang.py b/sabnzbd/lang.py index 7400285..6e7c170 100644 --- a/sabnzbd/lang.py +++ b/sabnzbd/lang.py @@ -45,14 +45,14 @@ _LOCALEDIR = "" # Holds path to the translation base folder def set_locale_info(domain, localedir): - """ Setup the domain and localedir for translations """ + """Setup the domain and localedir for translations""" global _DOMAIN, _LOCALEDIR _DOMAIN = domain _LOCALEDIR = localedir def set_language(language=None): - """ Activate language, empty language will set default texts. """ + """Activate language, empty language will set default texts.""" if not language: language = "" diff --git a/sabnzbd/misc.py b/sabnzbd/misc.py index 22f79a0..9a58ef5 100644 --- a/sabnzbd/misc.py +++ b/sabnzbd/misc.py @@ -69,7 +69,7 @@ if sabnzbd.DARWIN: def time_format(fmt): - """ Return time-format string adjusted for 12/24 hour clock setting """ + """Return time-format string adjusted for 12/24 hour clock setting""" if cfg.ampm() and HAVE_AMPM: return fmt.replace("%H:%M:%S", "%I:%M:%S %p").replace("%H:%M", "%I:%M %p") else: @@ -111,7 +111,7 @@ def calc_age(date: datetime.datetime, trans=False) -> str: def safe_lower(txt: Any) -> str: - """ Return lowercased string. Return '' for None """ + """Return lowercased string. Return '' for None""" if txt: return txt.lower() else: @@ -131,7 +131,7 @@ def cmp(x, y): def name_to_cat(fname, cat=None): - """ Retrieve category from file name, but only if "cat" is None. """ + """Retrieve category from file name, but only if "cat" is None.""" if cat is None and fname.startswith("{{"): n = fname.find("}}") if n > 2: @@ -176,7 +176,7 @@ def cat_to_opts(cat, pp=None, script=None, priority=None) -> Tuple[str, int, str def pp_to_opts(pp: int) -> Tuple[bool, bool, bool]: - """ Convert numeric processing options to (repair, unpack, delete) """ + """Convert numeric processing options to (repair, unpack, delete)""" # Convert the pp to an int pp = sabnzbd.interface.int_conv(pp) if pp == 0: @@ -189,7 +189,7 @@ def pp_to_opts(pp: int) -> Tuple[bool, bool, bool]: def opts_to_pp(repair: bool, unpack: bool, delete: bool) -> int: - """ Convert (repair, unpack, delete) to numeric process options """ + """Convert (repair, unpack, delete) to numeric process options""" pp = 0 if repair: pp = 1 @@ -219,7 +219,7 @@ _wildcard_to_regex = { def wildcard_to_re(text): - """ Convert plain wildcard string (with '*' and '?') to regex. """ + """Convert plain wildcard string (with '*' and '?') to regex.""" return "".join([_wildcard_to_regex.get(ch, ch) for ch in text]) @@ -299,7 +299,7 @@ _SERVICE_PARM = "CommandLine" def get_serv_parms(service): - """ Get the service command line parameters from Registry """ + """Get the service command line parameters from Registry""" import winreg service_parms = [] @@ -320,7 +320,7 @@ def get_serv_parms(service): def set_serv_parms(service, args): - """ Set the service command line parameters in Registry """ + """Set the service command line parameters in Registry""" import winreg serv = [] @@ -339,7 +339,7 @@ def set_serv_parms(service, args): def get_from_url(url: str) -> Optional[str]: - """ Retrieve URL and return content """ + """Retrieve URL and return content""" try: req = urllib.request.Request(url) req.add_header("User-Agent", "SABnzbd/%s" % sabnzbd.__version__) @@ -350,7 +350,7 @@ def get_from_url(url: str) -> Optional[str]: def convert_version(text): - """ Convert version string to numerical value and a testversion indicator """ + """Convert version string to numerical value and a testversion indicator""" version = 0 test = True m = RE_VERSION.search(ubtou(text)) @@ -456,7 +456,7 @@ def check_latest_version(): def upload_file_to_sabnzbd(url, fp): - """ Function for uploading nzbs to a running SABnzbd instance """ + """Function for uploading nzbs to a running SABnzbd instance""" try: fp = urllib.parse.quote_plus(fp) url = "%s&mode=addlocalfile&name=%s" % (url, fp) @@ -477,7 +477,7 @@ def upload_file_to_sabnzbd(url, fp): def from_units(val: str) -> float: - """ Convert K/M/G/T/P notation to float """ + """Convert K/M/G/T/P notation to float""" val = str(val).strip().upper() if val == "-1": return float(val) @@ -555,7 +555,7 @@ def caller_name(skip=2): def exit_sab(value: int): - """ Leave the program after flushing stderr/stdout """ + """Leave the program after flushing stderr/stdout""" sys.stderr.flush() sys.stdout.flush() # Cannot use sys.exit as it will not work inside the macOS-runner-thread @@ -563,7 +563,7 @@ def exit_sab(value: int): def split_host(srv): - """ Split host:port notation, allowing for IPV6 """ + """Split host:port notation, allowing for IPV6""" if not srv: return None, None @@ -623,7 +623,7 @@ def get_cache_limit(): def get_windows_memory(): - """ Use ctypes to extract available memory """ + """Use ctypes to extract available memory""" class MEMORYSTATUSEX(ctypes.Structure): _fields_ = [ @@ -649,13 +649,13 @@ def get_windows_memory(): def get_darwin_memory(): - """ Use system-call to extract total memory on macOS """ + """Use system-call to extract total memory on macOS""" system_output = run_command(["sysctl", "hw.memsize"]) return float(system_output.split()[1]) def on_cleanup_list(filename, skip_nzb=False): - """ Return True if a filename matches the clean-up list """ + """Return True if a filename matches the clean-up list""" lst = cfg.cleanup_list() if lst: name, ext = os.path.splitext(filename) @@ -692,7 +692,7 @@ _HAVE_STATM = _PAGE_SIZE and memory_usage() def loadavg(): - """ Return 1, 5 and 15 minute load average of host or "" if not supported """ + """Return 1, 5 and 15 minute load average of host or "" if not supported""" p = "" if not sabnzbd.WIN32 and not sabnzbd.DARWIN: opt = cfg.show_sysload() @@ -707,7 +707,7 @@ def loadavg(): def format_time_string(seconds): - """ Return a formatted and translated time string """ + """Return a formatted and translated time string""" def unit(single, n): # Seconds and minutes are special due to historical reasons @@ -743,7 +743,7 @@ def format_time_string(seconds): def int_conv(value: Any) -> int: - """ Safe conversion to int (can handle None) """ + """Safe conversion to int (can handle None)""" try: value = int(value) except: @@ -752,7 +752,7 @@ def int_conv(value: Any) -> int: def create_https_certificates(ssl_cert, ssl_key): - """ Create self-signed HTTPS certificates and store in paths 'ssl_cert' and 'ssl_key' """ + """Create self-signed HTTPS certificates and store in paths 'ssl_cert' and 'ssl_key'""" try: from sabnzbd.utils.certgen import generate_key, generate_local_cert @@ -768,7 +768,7 @@ def create_https_certificates(ssl_cert, ssl_key): def get_all_passwords(nzo): - """ Get all passwords, from the NZB, meta and password file """ + """Get all passwords, from the NZB, meta and password file""" if nzo.password: logging.info("Found a password that was set by the user: %s", nzo.password) passwords = [nzo.password.strip()] @@ -817,7 +817,7 @@ def get_all_passwords(nzo): def find_on_path(targets): - """ Search the PATH for a program and return full path """ + """Search the PATH for a program and return full path""" if sabnzbd.WIN32: paths = os.getenv("PATH").split(";") else: @@ -835,7 +835,7 @@ def find_on_path(targets): def is_ipv4_addr(ip: str) -> bool: - """ Determine if the ip is an IPv4 address """ + """Determine if the ip is an IPv4 address""" try: return ipaddress.ip_address(ip).version == 4 except ValueError: @@ -843,7 +843,7 @@ def is_ipv4_addr(ip: str) -> bool: def is_ipv6_addr(ip: str) -> bool: - """ Determine if the ip is an IPv6 address; square brackets ([2001::1]) are OK """ + """Determine if the ip is an IPv6 address; square brackets ([2001::1]) are OK""" try: return ipaddress.ip_address(ip.strip("[]")).version == 6 except (ValueError, AttributeError): @@ -851,7 +851,7 @@ def is_ipv6_addr(ip: str) -> bool: def is_loopback_addr(ip: str) -> bool: - """ Determine if the ip is an IPv4 or IPv6 local loopback address """ + """Determine if the ip is an IPv4 or IPv6 local loopback address""" try: if ip.find(".") < 0: ip = ip.strip("[]") @@ -861,12 +861,12 @@ def is_loopback_addr(ip: str) -> bool: def is_localhost(value: str) -> bool: - """ Determine if the input is some variety of 'localhost' """ + """Determine if the input is some variety of 'localhost'""" return (value == "localhost") or is_loopback_addr(value) def is_lan_addr(ip: str) -> bool: - """ Determine if the ip is a local area network address """ + """Determine if the ip is a local area network address""" try: return ( ip not in ("0.0.0.0", "255.255.255.255", "::") @@ -878,7 +878,7 @@ def is_lan_addr(ip: str) -> bool: def ip_extract() -> List[str]: - """ Return list of IP addresses of this system """ + """Return list of IP addresses of this system""" ips = [] program = find_on_path("ip") if program: @@ -908,7 +908,7 @@ def ip_extract() -> List[str]: def get_server_addrinfo(host: str, port: int) -> socket.getaddrinfo: - """ Return processed getaddrinfo() """ + """Return processed getaddrinfo()""" try: int(port) except: @@ -959,7 +959,7 @@ def get_base_url(url: str) -> str: def match_str(text: AnyStr, matches: Tuple[AnyStr, ...]) -> Optional[AnyStr]: - """ Return first matching element of list 'matches' in 'text', otherwise None """ + """Return first matching element of list 'matches' in 'text', otherwise None""" for match in matches: if match in text: return match @@ -967,7 +967,7 @@ def match_str(text: AnyStr, matches: Tuple[AnyStr, ...]) -> Optional[AnyStr]: def nntp_to_msg(text: Union[List[AnyStr], str]) -> str: - """ Format raw NNTP bytes data for display """ + """Format raw NNTP bytes data for display""" if isinstance(text, list): text = text[0] @@ -981,7 +981,7 @@ def nntp_to_msg(text: Union[List[AnyStr], str]) -> str: def list2cmdline(lst: List[str]) -> str: - """ convert list to a cmd.exe-compatible command string """ + """convert list to a cmd.exe-compatible command string""" nlst = [] for arg in lst: if not arg: @@ -1053,7 +1053,7 @@ def build_and_run_command(command: List[str], flatten_command=False, **kwargs): def run_command(cmd: List[str], **kwargs): - """ Run simple external command and return output as a string. """ + """Run simple external command and return output as a string.""" with build_and_run_command(cmd, **kwargs) as p: txt = platform_btou(p.stdout.read()) p.wait() diff --git a/sabnzbd/newsunpack.py b/sabnzbd/newsunpack.py index 834b0c6..dedf811 100644 --- a/sabnzbd/newsunpack.py +++ b/sabnzbd/newsunpack.py @@ -88,7 +88,7 @@ RAR_VERSION = 0 def find_programs(curdir): - """ Find external programs """ + """Find external programs""" def check(path, program): p = os.path.abspath(os.path.join(path, program)) @@ -169,7 +169,7 @@ ENV_NZO_FIELDS = [ def external_processing(extern_proc, nzo: NzbObject, complete_dir, nicename, status): - """ Run a user postproc script, return console output and exit value """ + """Run a user postproc script, return console output and exit value""" failure_url = nzo.nzo_info.get("failure", "") # Items can be bool or null, causing POpen to fail command = [ @@ -229,7 +229,7 @@ def external_processing(extern_proc, nzo: NzbObject, complete_dir, nicename, sta def unpack_magic( nzo: NzbObject, workdir, workdir_complete, dele, one_folder, joinables, zips, rars, sevens, ts, depth=0 ): - """ Do a recursive unpack from all archives in 'workdir' to 'workdir_complete' """ + """Do a recursive unpack from all archives in 'workdir' to 'workdir_complete'""" if depth > 5: logging.warning(T("Unpack nesting too deep [%s]"), nzo.final_name) return False, [] @@ -333,7 +333,7 @@ def unpack_magic( # Filejoin Functions ############################################################################## def match_ts(file): - """ Return True if file is a joinable TS file """ + """Return True if file is a joinable TS file""" match = TS_RE.search(file) if not match: return False, "", 0 @@ -348,7 +348,7 @@ def match_ts(file): def clean_up_joinables(names): - """ Remove joinable files and their .1 backups """ + """Remove joinable files and their .1 backups""" for name in names: if os.path.exists(name): try: @@ -364,7 +364,7 @@ def clean_up_joinables(names): def get_seq_number(name): - """ Return sequence number if name as an int """ + """Return sequence number if name as an int""" head, tail = os.path.splitext(name) if tail == ".ts": match, set, num = match_ts(name) @@ -907,7 +907,7 @@ def unzip(nzo: NzbObject, workdir, workdir_complete, delete, one_folder, zips): def ZIP_Extract(zipfile, extraction_path, one_folder): - """ Unzip single zip set 'zipfile' to 'extraction_path' """ + """Unzip single zip set 'zipfile' to 'extraction_path'""" command = ["%s" % ZIP_COMMAND, "-o", "-Pnone", "%s" % clip_path(zipfile), "-d%s" % extraction_path] if one_folder or cfg.flat_unpack(): @@ -1080,7 +1080,7 @@ def seven_extract_core(sevenset, extensions, extraction_path, one_folder, delete # PAR2 Functions ############################################################################## def par2_repair(parfile_nzf: NzbFile, nzo: NzbObject, workdir, setname, single): - """ Try to repair a set, return readd or correctness """ + """Try to repair a set, return readd or correctness""" # Check if file exists, otherwise see if another is done parfile_path = os.path.join(workdir, parfile_nzf.filename) if not os.path.exists(parfile_path) and nzo.extrapars[setname]: @@ -1206,7 +1206,7 @@ _RE_LOADED_PAR2 = re.compile(r"Loaded (\d+) new packets") def PAR_Verify(parfile, nzo: NzbObject, setname, joinables, single=False): - """ Run par2 on par-set """ + """Run par2 on par-set""" used_joinables = [] used_for_repair = [] # set the current nzo status to "Verifying...". Used in History @@ -1518,7 +1518,7 @@ _RE_FILENAME = re.compile(r'"([^"]+)"') def MultiPar_Verify(parfile, nzo: NzbObject, setname, joinables, single=False): - """ Run par2 on par-set """ + """Run par2 on par-set""" parfolder = os.path.split(parfile)[0] used_joinables = [] used_for_repair = [] @@ -1980,7 +1980,7 @@ def rar_volumelist(rarfile_path, password, known_volumes): # Sort the various RAR filename formats properly :\ def rar_sort(a, b): - """ Define sort method for rar file names """ + """Define sort method for rar file names""" aext = a.split(".")[-1] bext = b.split(".")[-1] @@ -2040,7 +2040,7 @@ def build_filelists(workdir, workdir_complete=None, check_both=False, check_rar= def quick_check_set(set, nzo): - """ Check all on-the-fly md5sums of a set """ + """Check all on-the-fly md5sums of a set""" md5pack = nzo.md5packs.get(set) if md5pack is None: return False @@ -2132,7 +2132,7 @@ def unrar_check(rar): def par2_mt_check(par2_path): - """ Detect if we have multicore par2 variants """ + """Detect if we have multicore par2 variants""" try: par2_version = run_command([par2_path, "-h"]) # Look for a threads option @@ -2144,7 +2144,7 @@ def par2_mt_check(par2_path): def is_sfv_file(myfile): - """ Checks if given file is a SFV file, and returns result as boolean """ + """Checks if given file is a SFV file, and returns result as boolean""" # based on https://stackoverflow.com/a/7392391/5235502 textchars = bytearray({7, 8, 9, 10, 12, 13, 27} | set(range(0x20, 0x100)) - {0x7F}) is_ascii_string = lambda input_bytes: not bool(input_bytes.translate(None, textchars)) @@ -2188,7 +2188,7 @@ def is_sfv_file(myfile): def sfv_check(sfvs, nzo: NzbObject, workdir): - """ Verify files using SFV files """ + """Verify files using SFV files""" # Update status nzo.status = Status.VERIFYING nzo.set_action_line(T("Trying SFV verification"), "...") @@ -2271,7 +2271,7 @@ def sfv_check(sfvs, nzo: NzbObject, workdir): def parse_sfv(sfv_filename): - """ Parse SFV file and return dictonary of crc32's and filenames """ + """Parse SFV file and return dictonary of crc32's and filenames""" results = {} with open(sfv_filename, mode="rb") as sfv_list: for sfv_item in sfv_list: @@ -2287,7 +2287,7 @@ def parse_sfv(sfv_filename): def crc_calculate(path): - """ Calculate crc32 of the given file """ + """Calculate crc32 of the given file""" crc = 0 with open(path, "rb") as fp: while 1: @@ -2299,7 +2299,7 @@ def crc_calculate(path): def analyse_show(name): - """ Do a quick SeasonSort check and return basic facts """ + """Do a quick SeasonSort check and return basic facts""" job = SeriesSorter(None, name, None, None) job.match(force=True) if job.is_match(): @@ -2386,18 +2386,18 @@ def pre_queue(nzo: NzbObject, pp, cat): def is_sevenfile(path): - """ Return True if path has proper extension and 7Zip is installed """ + """Return True if path has proper extension and 7Zip is installed""" return SEVEN_COMMAND and os.path.splitext(path)[1].lower() == ".7z" class SevenZip: - """ Minimal emulation of ZipFile class for 7Zip """ + """Minimal emulation of ZipFile class for 7Zip""" def __init__(self, path): self.path = path def namelist(self): - """ Return list of names in 7Zip """ + """Return list of names in 7Zip""" names = [] # Future extension: use '-sccUTF-8' to get names in UTF8 encoding command = [SEVEN_COMMAND, "l", "-p", "-y", "-slt", self.path] @@ -2414,11 +2414,11 @@ class SevenZip: return names def read(self, name): - """ Read named file from 7Zip and return data """ + """Read named file from 7Zip and return data""" command = [SEVEN_COMMAND, "e", "-p", "-y", "-so", self.path, name] # Ignore diagnostic output, otherwise it will be appended to content return run_command(command, stderr=subprocess.DEVNULL) def close(self): - """ Close file """ + """Close file""" pass diff --git a/sabnzbd/newswrapper.py b/sabnzbd/newswrapper.py index d563db1..827189c 100644 --- a/sabnzbd/newswrapper.py +++ b/sabnzbd/newswrapper.py @@ -78,14 +78,14 @@ class NewsWrapper: @property def status_code(self) -> Optional[int]: - """ Shorthand to get the code """ + """Shorthand to get the code""" try: return int(self.data[0][:3]) except: return None def init_connect(self): - """ Setup the connection in NNTP object """ + """Setup the connection in NNTP object""" # Server-info is normally requested by initialization of # servers in Downloader, but not when testing servers if self.blocking and not self.server.info: @@ -96,7 +96,7 @@ class NewsWrapper: self.timeout = time.time() + self.server.timeout def finish_connect(self, code: int): - """ Perform login options """ + """Perform login options""" if not (self.server.username or self.server.password or self.force_login): self.connected = True self.user_sent = True @@ -151,7 +151,7 @@ class NewsWrapper: self.timeout = time.time() + self.server.timeout def body(self): - """ Request the body of the article """ + """Request the body of the article""" self.timeout = time.time() + self.server.timeout if self.article.nzf.nzo.precheck: if self.server.have_stat: @@ -166,14 +166,14 @@ class NewsWrapper: self.data = [] def send_group(self, group: str): - """ Send the NNTP GROUP command """ + """Send the NNTP GROUP command""" self.timeout = time.time() + self.server.timeout command = utob("GROUP %s\r\n" % group) self.nntp.sock.sendall(command) self.data = [] def recv_chunk(self, block: bool = False) -> Tuple[int, bool, bool]: - """ Receive data, return #bytes, done, skip """ + """Receive data, return #bytes, done, skip""" self.timeout = time.time() + self.server.timeout while 1: try: @@ -213,17 +213,17 @@ class NewsWrapper: return chunk_len, False, False def soft_reset(self): - """ Reset for the next article """ + """Reset for the next article""" self.timeout = None self.article = None self.clear_data() def clear_data(self): - """ Clear the stored raw data """ + """Clear the stored raw data""" self.data = [] def hard_reset(self, wait: bool = True, send_quit: bool = True): - """ Destroy and restart """ + """Destroy and restart""" if self.nntp: try: if send_quit: diff --git a/sabnzbd/notifier.py b/sabnzbd/notifier.py index c40ef42..cf25b7d 100644 --- a/sabnzbd/notifier.py +++ b/sabnzbd/notifier.py @@ -79,12 +79,12 @@ def get_icon(): def have_ntfosd(): - """ Return if any PyNotify (notify2) support is present """ + """Return if any PyNotify (notify2) support is present""" return bool(_HAVE_NTFOSD) def check_classes(gtype, section): - """ Check if `gtype` is enabled in `section` """ + """Check if `gtype` is enabled in `section`""" try: return sabnzbd.config.get_config(section, "%s_prio_%s" % (section, gtype))() > 0 except TypeError: @@ -93,7 +93,7 @@ def check_classes(gtype, section): def get_prio(gtype, section): - """ Check prio of `gtype` in `section` """ + """Check prio of `gtype` in `section`""" try: return sabnzbd.config.get_config(section, "%s_prio_%s" % (section, gtype))() except TypeError: @@ -118,7 +118,7 @@ def check_cat(section, job_cat, keyword=None): def send_notification(title, msg, gtype, job_cat=None): - """ Send Notification message """ + """Send Notification message""" logging.info("Sending notification: %s - %s (type=%s, job_cat=%s)", title, msg, gtype, job_cat) # Notification Center if sabnzbd.DARWIN and sabnzbd.cfg.ncenter_enable(): @@ -163,7 +163,7 @@ _NTFOSD = False def send_notify_osd(title, message): - """ Send a message to NotifyOSD """ + """Send a message to NotifyOSD""" global _NTFOSD if not _HAVE_NTFOSD: return T("Not available") # : Function is not available on this OS @@ -193,7 +193,7 @@ def send_notify_osd(title, message): def send_notification_center(title, msg, gtype): - """ Send message to macOS Notification Center """ + """Send message to macOS Notification Center""" try: NSUserNotification = objc.lookUpClass("NSUserNotification") NSUserNotificationCenter = objc.lookUpClass("NSUserNotificationCenter") @@ -211,7 +211,7 @@ def send_notification_center(title, msg, gtype): def send_prowl(title, msg, gtype, force=False, test=None): - """ Send message to Prowl """ + """Send message to Prowl""" if test: apikey = test.get("prowl_apikey") @@ -244,7 +244,7 @@ def send_prowl(title, msg, gtype, force=False, test=None): def send_pushover(title, msg, gtype, force=False, test=None): - """ Send message to pushover """ + """Send message to pushover""" if test: apikey = test.get("pushover_token") @@ -311,7 +311,7 @@ def do_send_pushover(body): def send_pushbullet(title, msg, gtype, force=False, test=None): - """ Send message to Pushbullet """ + """Send message to Pushbullet""" if test: apikey = test.get("pushbullet_apikey") @@ -346,7 +346,7 @@ def send_pushbullet(title, msg, gtype, force=False, test=None): def send_nscript(title, msg, gtype, force=False, test=None): - """ Run user's notification script """ + """Run user's notification script""" if test: script = test.get("nscript_script") nscript_parameters = test.get("nscript_parameters") diff --git a/sabnzbd/nzbqueue.py b/sabnzbd/nzbqueue.py index 49cd7dc..4c15e08 100644 --- a/sabnzbd/nzbqueue.py +++ b/sabnzbd/nzbqueue.py @@ -59,7 +59,7 @@ import sabnzbd.notifier as notifier class NzbQueue: - """ Singleton NzbQueue """ + """Singleton NzbQueue""" def __init__(self): self.__top_only: bool = cfg.top_only() @@ -165,7 +165,7 @@ class NzbQueue: return result def repair_job(self, repair_folder, new_nzb=None, password=None): - """ Reconstruct admin for a single job folder, optionally with new NZB """ + """Reconstruct admin for a single job folder, optionally with new NZB""" # Check if folder exists if not repair_folder or not os.path.exists(repair_folder): return None @@ -207,7 +207,7 @@ class NzbQueue: @NzbQueueLocker def send_back(self, old_nzo: NzbObject): - """ Send back job to queue after successful pre-check """ + """Send back job to queue after successful pre-check""" try: nzb_path = globber_full(old_nzo.admin_path, "*.gz")[0] except: @@ -229,7 +229,7 @@ class NzbQueue: @NzbQueueLocker def save(self, save_nzo: Union[NzbObject, None, bool] = None): - """ Save queue, all nzo's or just the specified one """ + """Save queue, all nzo's or just the specified one""" logging.info("Saving queue") nzo_ids = [] @@ -250,7 +250,7 @@ class NzbQueue: self.__top_only = value def generate_future(self, msg, pp=None, script=None, cat=None, url=None, priority=DEFAULT_PRIORITY, nzbname=None): - """ Create and return a placeholder nzo object """ + """Create and return a placeholder nzo object""" logging.debug("Creating placeholder NZO") future_nzo = NzbObject( filename=msg, @@ -417,7 +417,7 @@ class NzbQueue: @NzbQueueLocker def remove_all(self, search: str = "") -> List[str]: - """ Remove NZO's that match the search-pattern """ + """Remove NZO's that match the search-pattern""" nzo_ids = [] search = safe_lower(search) for nzo_id, nzo in self.__nzo_table.items(): @@ -598,7 +598,7 @@ class NzbQueue: @NzbQueueLocker def __set_priority(self, nzo_id, priority): - """ Sets the priority on the nzo and places it in the queue at the appropriate position """ + """Sets the priority on the nzo and places it in the queue at the appropriate position""" try: priority = int_conv(priority) nzo = self.__nzo_table[nzo_id] @@ -686,7 +686,7 @@ class NzbQueue: @staticmethod def reset_try_lists(article: Article, article_reset=True): - """ Let article get new fetcher and reset trylists """ + """Let article get new fetcher and reset trylists""" article.fetcher = None if article_reset: article.reset_try_list() @@ -771,7 +771,7 @@ class NzbQueue: @NzbQueueLocker def end_job(self, nzo: NzbObject): - """ Send NZO to the post-processing queue """ + """Send NZO to the post-processing queue""" # Notify assembler to call postprocessor if not nzo.deleted: logging.info("[%s] Ending job %s", caller_name(), nzo.final_name) @@ -857,7 +857,7 @@ class NzbQueue: return empty def stop_idle_jobs(self): - """ Detect jobs that have zero files left and send them to post processing """ + """Detect jobs that have zero files left and send them to post processing""" empty = [] for nzo in self.__nzo_list: if not nzo.futuretype and not nzo.files and nzo.status not in (Status.PAUSED, Status.GRABBING): @@ -906,7 +906,7 @@ class NzbQueue: nzo.status = Status.QUEUED def get_urls(self): - """ Return list of future-types needing URL """ + """Return list of future-types needing URL""" lst = [] for nzo_id in self.__nzo_table: nzo = self.__nzo_table[nzo_id] diff --git a/sabnzbd/nzbstuff.py b/sabnzbd/nzbstuff.py index e582426..13c5854 100644 --- a/sabnzbd/nzbstuff.py +++ b/sabnzbd/nzbstuff.py @@ -115,23 +115,23 @@ class TryList: self.fetcher_priority: int = 0 def server_in_try_list(self, server: Server): - """ Return whether specified server has been tried """ + """Return whether specified server has been tried""" with TRYLIST_LOCK: return server in self.try_list def add_to_try_list(self, server: Server): - """ Register server as having been tried already """ + """Register server as having been tried already""" with TRYLIST_LOCK: if server not in self.try_list: self.try_list.append(server) def reset_try_list(self): - """ Clean the list """ + """Clean the list""" with TRYLIST_LOCK: self.try_list = [] def __getstate__(self): - """ Save the servers """ + """Save the servers""" return [server.id for server in self.try_list] def __setstate__(self, servers_ids: List[str]): @@ -148,7 +148,7 @@ ArticleSaver = ("article", "art_id", "bytes", "lowest_partnum", "decoded", "on_d class Article(TryList): - """ Representation of one article """ + """Representation of one article""" # Pre-define attributes to save memory __slots__ = ArticleSaver + ("fetcher", "fetcher_priority", "tries") @@ -166,7 +166,7 @@ class Article(TryList): self.nzf: NzbFile = nzf def get_article(self, server: Server, servers: List[Server]): - """ Return article when appropriate for specified server """ + """Return article when appropriate for specified server""" log = sabnzbd.LOG_ALL if not self.fetcher and not self.server_in_try_list(server): if log: @@ -229,7 +229,7 @@ class Article(TryList): return None def get_art_id(self): - """ Return unique article storage name, create if needed """ + """Return unique article storage name, create if needed""" if not self.art_id: self.art_id = sabnzbd.get_new_id("article", self.nzf.nzo.admin_path) return self.art_id @@ -251,7 +251,7 @@ class Article(TryList): return False def __getstate__(self): - """ Save to pickle file, selecting attributes """ + """Save to pickle file, selecting attributes""" dict_ = {} for item in ArticleSaver: dict_[item] = getattr(self, item) @@ -259,7 +259,7 @@ class Article(TryList): return dict_ def __setstate__(self, dict_): - """ Load from pickle file, selecting attributes """ + """Load from pickle file, selecting attributes""" for item in ArticleSaver: try: setattr(self, item, dict_[item]) @@ -272,7 +272,7 @@ class Article(TryList): self.tries = 0 def __eq__(self, other): - """ Articles with the same usenet address are the same """ + """Articles with the same usenet address are the same""" return self.article == other.article def __hash__(self): @@ -315,13 +315,13 @@ NzbFileSaver = ( class NzbFile(TryList): - """ Representation of one file consisting of multiple articles """ + """Representation of one file consisting of multiple articles""" # Pre-define attributes to save memory __slots__ = NzbFileSaver + ("md5",) def __init__(self, date, subject, raw_article_db, file_bytes, nzo): - """ Setup object """ + """Setup object""" super().__init__() self.date: datetime.datetime = date @@ -376,7 +376,7 @@ class NzbFile(TryList): self.import_finished = True def finish_import(self): - """ Load the article objects from disk """ + """Load the article objects from disk""" logging.debug("Finishing import on %s", self.filename) raw_article_db = sabnzbd.load_data(self.nzf_id, self.nzo.admin_path, remove=False) if raw_article_db: @@ -395,14 +395,14 @@ class NzbFile(TryList): self.import_finished = True def add_article(self, article_info): - """ Add article to object database and return article object """ + """Add article to object database and return article object""" article = Article(article_info[0], article_info[1], self) self.articles.append(article) self.decodetable.append(article) return article def remove_article(self, article: Article, success: bool) -> int: - """ Handle completed article, possibly end of file """ + """Handle completed article, possibly end of file""" if article in self.articles: self.articles.remove(article) if success: @@ -410,14 +410,14 @@ class NzbFile(TryList): return len(self.articles) def set_par2(self, setname, vol, blocks): - """ Designate this this file as a par2 file """ + """Designate this this file as a par2 file""" self.is_par2 = True self.setname = setname self.vol = vol self.blocks = int_conv(blocks) def get_article(self, server: Server, servers: List[Server]) -> Optional[Article]: - """ Get next article to be downloaded """ + """Get next article to be downloaded""" for article in self.articles: article = article.get_article(server, servers) if article: @@ -425,13 +425,13 @@ class NzbFile(TryList): self.add_to_try_list(server) def reset_all_try_lists(self): - """ Clear all lists of visited servers """ + """Clear all lists of visited servers""" for art in self.articles: art.reset_try_list() self.reset_try_list() def prepare_filepath(self): - """ Do all checks before making the final path """ + """Do all checks before making the final path""" if not self.filepath: self.nzo.verify_nzf_filename(self) filename = sanitize_filename(self.filename) @@ -441,11 +441,11 @@ class NzbFile(TryList): @property def completed(self): - """ Is this file completed? """ + """Is this file completed?""" return self.import_finished and not bool(self.articles) def remove_admin(self): - """ Remove article database from disk (sabnzbd_nzf_)""" + """Remove article database from disk (sabnzbd_nzf_)""" try: logging.debug("Removing article database for %s", self.nzf_id) remove_file(os.path.join(self.nzo.admin_path, self.nzf_id)) @@ -453,7 +453,7 @@ class NzbFile(TryList): pass def __getstate__(self): - """ Save to pickle file, selecting attributes """ + """Save to pickle file, selecting attributes""" dict_ = {} for item in NzbFileSaver: dict_[item] = getattr(self, item) @@ -461,7 +461,7 @@ class NzbFile(TryList): return dict_ def __setstate__(self, dict_): - """ Load from pickle file, selecting attributes """ + """Load from pickle file, selecting attributes""" for item in NzbFileSaver: try: setattr(self, item, dict_[item]) @@ -990,7 +990,7 @@ class NzbObject(TryList): @synchronized(NZO_LOCK) def postpone_pars(self, nzf: NzbFile, parset: str): - """ Move all vol-par files matching 'parset' to the extrapars table """ + """Move all vol-par files matching 'parset' to the extrapars table""" # Create new extrapars if it didn't already exist # For example if created when the first par2 file was missing if parset not in self.extrapars: @@ -1024,7 +1024,7 @@ class NzbObject(TryList): @synchronized(NZO_LOCK) def handle_par2(self, nzf: NzbFile, filepath): - """ Check if file is a par2 and build up par2 collection """ + """Check if file is a par2 and build up par2 collection""" # Need to remove it from the other set it might be in self.remove_extrapar(nzf) @@ -1132,7 +1132,7 @@ class NzbObject(TryList): @synchronized(NZO_LOCK) def remove_article(self, article: Article, success: bool): - """ Remove article from the NzbFile and do check if it can succeed""" + """Remove article from the NzbFile and do check if it can succeed""" job_can_succeed = True nzf = article.nzf @@ -1210,7 +1210,7 @@ class NzbObject(TryList): pass def check_existing_files(self, wdir: str): - """ Check if downloaded files already exits, for these set NZF to complete """ + """Check if downloaded files already exits, for these set NZF to complete""" fix_unix_encoding(wdir) # Get a list of already present files, ignore folders @@ -1299,7 +1299,7 @@ class NzbObject(TryList): self.abort_direct_unpacker() def set_priority(self, value: Any): - """ Check if this is a valid priority """ + """Check if this is a valid priority""" # When unknown (0 is a known one), set to DEFAULT if value == "" or value is None: self.priority = DEFAULT_PRIORITY @@ -1343,7 +1343,7 @@ class NzbObject(TryList): @property def labels(self): - """ Return (translated) labels of job """ + """Return (translated) labels of job""" labels = [] if self.duplicate: labels.append(T("DUPLICATE")) @@ -1433,7 +1433,7 @@ class NzbObject(TryList): @synchronized(NZO_LOCK) def remove_extrapar(self, parfile: NzbFile): - """ Remove par file from any/all sets """ + """Remove par file from any/all sets""" for _set in self.extrapars: if parfile in self.extrapars[_set]: self.extrapars[_set].remove(parfile) @@ -1459,18 +1459,18 @@ class NzbObject(TryList): self.reset_try_list() def add_to_direct_unpacker(self, nzf: NzbFile): - """ Start or add to DirectUnpacker """ + """Start or add to DirectUnpacker""" if not self.direct_unpacker: sabnzbd.directunpacker.DirectUnpacker(self) self.direct_unpacker.add(nzf) def abort_direct_unpacker(self): - """ Abort any running DirectUnpackers """ + """Abort any running DirectUnpackers""" if self.direct_unpacker: self.direct_unpacker.abort() def check_availability_ratio(self): - """ Determine if we are still meeting the required ratio """ + """Determine if we are still meeting the required ratio""" availability_ratio = req_ratio = cfg.req_completion_rate() # Rare case where the NZB only consists of par2 files @@ -1510,7 +1510,7 @@ class NzbObject(TryList): @synchronized(NZO_LOCK) def set_download_report(self): - """ Format the stats for the history information """ + """Format the stats for the history information""" # Pretty-format the per-server stats if self.servercount: # Sort the servers first @@ -1564,7 +1564,7 @@ class NzbObject(TryList): @synchronized(NZO_LOCK) def increase_bad_articles_counter(self, article_type): - """ Record information about bad articles """ + """Record information about bad articles""" if article_type not in self.nzo_info: self.nzo_info[article_type] = 0 self.nzo_info[article_type] += 1 @@ -1690,7 +1690,7 @@ class NzbObject(TryList): self.files[pos] = tmp_nzf def verify_nzf_filename(self, nzf: NzbFile, yenc_filename: Optional[str] = None): - """ Get filename from par2-info or from yenc """ + """Get filename from par2-info or from yenc""" # Already done? if nzf.filename_checked: return @@ -1783,12 +1783,12 @@ class NzbObject(TryList): @property def admin_path(self): - """ Return the full path for my job-admin folder """ + """Return the full path for my job-admin folder""" return long_path(get_admin_path(self.work_name, self.futuretype)) @property def download_path(self): - """ Return the full path for the download folder """ + """Return the full path for the download folder""" if self.futuretype: return "" else: @@ -1803,12 +1803,12 @@ class NzbObject(TryList): @property def remaining(self): - """ Return remaining bytes """ + """Return remaining bytes""" return self.bytes - self.bytes_tried @synchronized(NZO_LOCK) def purge_data(self, delete_all_data=True): - """ Remove (all) job data """ + """Remove (all) job data""" logging.info( "[%s] Purging data for job %s (delete_all_data=%s)", caller_name(), self.final_name, delete_all_data ) @@ -1903,13 +1903,13 @@ class NzbObject(TryList): @synchronized(NZO_LOCK) def save_to_disk(self): - """ Save job's admin to disk """ + """Save job's admin to disk""" self.save_attribs() if self.nzo_id and not self.is_gone(): sabnzbd.save_data(self, self.nzo_id, self.admin_path) def save_attribs(self): - """ Save specific attributes for Retry """ + """Save specific attributes for Retry""" attribs = {} for attrib in NzoAttributeSaver: attribs[attrib] = getattr(self, attrib) @@ -1917,7 +1917,7 @@ class NzbObject(TryList): sabnzbd.save_data(attribs, ATTRIB_FILE, self.admin_path, silent=True) def load_attribs(self) -> Tuple[Optional[str], Optional[int], Optional[str]]: - """ Load saved attributes and return them to be parsed """ + """Load saved attributes and return them to be parsed""" attribs = sabnzbd.load_data(ATTRIB_FILE, self.admin_path, remove=False) logging.debug("Loaded attributes %s for %s", attribs, self.final_name) @@ -2000,11 +2000,11 @@ class NzbObject(TryList): return res, series def is_gone(self): - """ Is this job still going somehow? """ + """Is this job still going somehow?""" return self.status in (Status.COMPLETED, Status.DELETED, Status.FAILED) def __getstate__(self): - """ Save to pickle file, selecting attributes """ + """Save to pickle file, selecting attributes""" dict_ = {} for item in NzbObjectSaver: dict_[item] = getattr(self, item) @@ -2012,7 +2012,7 @@ class NzbObject(TryList): return dict_ def __setstate__(self, dict_): - """ Load from pickle file, selecting attributes """ + """Load from pickle file, selecting attributes""" for item in NzbObjectSaver: try: setattr(self, item, dict_[item]) @@ -2097,7 +2097,7 @@ def nzf_cmp_name(nzf1: NzbFile, nzf2: NzbFile): def create_work_name(name: str) -> str: - """ Remove ".nzb" and ".par(2)" and sanitize, skip URL's """ + """Remove ".nzb" and ".par(2)" and sanitize, skip URL's""" if name.find("://") < 0: # In case it was one of these, there might be more # Need to remove any invalid characters before starting @@ -2112,7 +2112,7 @@ def create_work_name(name: str) -> str: def scan_password(name: str) -> Tuple[str, Optional[str]]: - """ Get password (if any) from the title """ + """Get password (if any) from the title""" if "http://" in name or "https://" in name: return name, None @@ -2152,7 +2152,7 @@ def scan_password(name: str) -> Tuple[str, Optional[str]]: def name_extractor(subject: str) -> str: - """ Try to extract a file name from a subject line, return `subject` if in doubt """ + """Try to extract a file name from a subject line, return `subject` if in doubt""" result = subject # Filename nicely wrapped in quotes for name in re.findall(RE_SUBJECT_FILENAME_QUOTES, subject): @@ -2172,7 +2172,7 @@ def name_extractor(subject: str) -> str: def matcher(pattern, txt): - """ Return True if `pattern` is sufficiently equal to `txt` """ + """Return True if `pattern` is sufficiently equal to `txt`""" if txt.endswith(pattern): txt = txt[: txt.rfind(pattern)].strip() return (not txt) or txt.endswith('"') diff --git a/sabnzbd/panic.py b/sabnzbd/panic.py index 5f7da86..bd75002 100644 --- a/sabnzbd/panic.py +++ b/sabnzbd/panic.py @@ -148,7 +148,7 @@ def MSG_SQLITE(): def panic_message(panic_code, a=None, b=None): - """ Create the panic message from templates """ + """Create the panic message from templates""" if sabnzbd.WIN32: os_str = T("Press Startkey+R and type the line (example):") prog_path = '"%s"' % sabnzbd.MY_FULLNAME @@ -222,7 +222,7 @@ def panic(reason, remedy=""): def launch_a_browser(url, force=False): - """ Launch a browser pointing to the URL """ + """Launch a browser pointing to the URL""" if not force and not cfg.autobrowser() or sabnzbd.DAEMON: return @@ -259,7 +259,7 @@ def show_error_dialog(msg): def error_page_401(status, message, traceback, version): - """ Custom handler for 401 error """ + """Custom handler for 401 error""" title = T("Access denied") body = T("Error %s: You need to provide a valid username and password.") % status return r""" @@ -279,7 +279,7 @@ def error_page_401(status, message, traceback, version): def error_page_404(status, message, traceback, version): - """ Custom handler for 404 error, redirect to main page """ + """Custom handler for 404 error, redirect to main page""" return ( r""" diff --git a/sabnzbd/par2file.py b/sabnzbd/par2file.py index 9187795..51b271f 100644 --- a/sabnzbd/par2file.py +++ b/sabnzbd/par2file.py @@ -130,7 +130,7 @@ def parse_par2_file(fname: str, md5of16k: Dict[bytes, str]) -> Dict[str, bytes]: def parse_par2_file_packet(f, header) -> Tuple[Optional[str], Optional[bytes], Optional[bytes]]: - """ Look up and analyze a FileDesc package """ + """Look up and analyze a FileDesc package""" nothing = None, None, None diff --git a/sabnzbd/postproc.py b/sabnzbd/postproc.py index 4c4e9d7..0c27558 100644 --- a/sabnzbd/postproc.py +++ b/sabnzbd/postproc.py @@ -98,10 +98,10 @@ RE_SAMPLE = re.compile(sample_match, re.I) class PostProcessor(Thread): - """ PostProcessor thread, designed as Singleton """ + """PostProcessor thread, designed as Singleton""" def __init__(self): - """ Initialize PostProcessor thread """ + """Initialize PostProcessor thread""" super().__init__() # This history queue is simply used to log what active items to display in the web_ui @@ -130,12 +130,12 @@ class PostProcessor(Thread): self.paused = False def save(self): - """ Save postproc queue """ + """Save postproc queue""" logging.info("Saving postproc queue") sabnzbd.save_admin((POSTPROC_QUEUE_VERSION, self.history_queue), POSTPROC_QUEUE_FILE_NAME) def load(self): - """ Save postproc queue """ + """Save postproc queue""" logging.info("Loading postproc queue") data = sabnzbd.load_admin(POSTPROC_QUEUE_FILE_NAME) if data is None: @@ -151,7 +151,7 @@ class PostProcessor(Thread): logging.info("Traceback: ", exc_info=True) def delete(self, nzo_id, del_files=False): - """ Remove a job from the post processor queue """ + """Remove a job from the post processor queue""" for nzo in self.history_queue: if nzo.nzo_id == nzo_id: if nzo.status in (Status.FAILED, Status.COMPLETED): @@ -164,7 +164,7 @@ class PostProcessor(Thread): break def process(self, nzo: NzbObject): - """ Push on finished job in the queue """ + """Push on finished job in the queue""" # Make sure we return the status "Waiting" nzo.status = Status.QUEUED if nzo not in self.history_queue: @@ -179,7 +179,7 @@ class PostProcessor(Thread): sabnzbd.history_updated() def remove(self, nzo: NzbObject): - """ Remove given nzo from the queue """ + """Remove given nzo from the queue""" try: self.history_queue.remove(nzo) except: @@ -188,13 +188,13 @@ class PostProcessor(Thread): sabnzbd.history_updated() def stop(self): - """ Stop thread after finishing running job """ + """Stop thread after finishing running job""" self.__stop = True self.slow_queue.put(None) self.fast_queue.put(None) def cancel_pp(self, nzo_id): - """ Change the status, so that the PP is canceled """ + """Change the status, so that the PP is canceled""" for nzo in self.history_queue: if nzo.nzo_id == nzo_id: nzo.abort_direct_unpacker() @@ -210,22 +210,22 @@ class PostProcessor(Thread): return None def empty(self): - """ Return True if pp queue is empty """ + """Return True if pp queue is empty""" return self.slow_queue.empty() and self.fast_queue.empty() and not self.__busy def get_queue(self): - """ Return list of NZOs that still need to be processed """ + """Return list of NZOs that still need to be processed""" return [nzo for nzo in self.history_queue if nzo.work_name] def get_path(self, nzo_id): - """ Return download path for given nzo_id or None when not found """ + """Return download path for given nzo_id or None when not found""" for nzo in self.history_queue: if nzo.nzo_id == nzo_id: return nzo.download_path return None def run(self): - """ Postprocessor loop """ + """Postprocessor loop""" # First we do a dircheck complete_dir = sabnzbd.cfg.complete_dir.get_path() if sabnzbd.utils.checkdir.isFAT(complete_dir): @@ -309,7 +309,7 @@ class PostProcessor(Thread): def process_job(nzo: NzbObject): - """ Process one job """ + """Process one job""" start = time.time() # keep track of whether we can continue @@ -734,7 +734,7 @@ def prepare_extraction_path(nzo: NzbObject): def parring(nzo: NzbObject, workdir: str): - """ Perform par processing. Returns: (par_error, re_add) """ + """Perform par processing. Returns: (par_error, re_add)""" logging.info("Starting verification and repair of %s", nzo.final_name) par_error = False re_add = False @@ -892,7 +892,7 @@ def try_rar_check(nzo: NzbObject, rars): def rar_renamer(nzo: NzbObject, workdir): - """ Deobfuscate rar file names: Use header and content information to give RAR-files decent names """ + """Deobfuscate rar file names: Use header and content information to give RAR-files decent names""" nzo.status = Status.VERIFYING nzo.set_unpack_info("Repair", T("Trying RAR renamer")) nzo.set_action_line(T("Trying RAR renamer"), "...") @@ -1028,7 +1028,7 @@ def rar_renamer(nzo: NzbObject, workdir): def handle_empty_queue(): - """ Check if empty queue calls for action """ + """Check if empty queue calls for action""" if sabnzbd.NzbQueue.actives() == 0: sabnzbd.save_state() notifier.send_notification("SABnzbd", T("Queue finished"), "queue_done") @@ -1116,7 +1116,7 @@ def nzb_redirect(wdir, nzbname, pp, script, cat, priority): def one_file_or_folder(folder): - """ If the dir only contains one file or folder, join that file/folder onto the path """ + """If the dir only contains one file or folder, join that file/folder onto the path""" if os.path.exists(folder) and os.path.isdir(folder): try: cont = os.listdir(folder) @@ -1133,7 +1133,7 @@ TAG_RE = re.compile(r"<[^>]+>") def get_last_line(txt): - """ Return last non-empty line of a text, trim to 150 max """ + """Return last non-empty line of a text, trim to 150 max""" # First we remove HTML code in a basic way txt = TAG_RE.sub(" ", txt) @@ -1201,7 +1201,7 @@ def rename_and_collapse_folder(oldpath, newpath, files): def set_marker(folder): - """ Set marker file and return name """ + """Set marker file and return name""" name = cfg.marker_file() if name: path = os.path.join(folder, name) @@ -1217,7 +1217,7 @@ def set_marker(folder): def del_marker(path): - """ Remove marker file """ + """Remove marker file""" if path and os.path.exists(path): logging.debug("Removing marker file %s", path) try: @@ -1237,7 +1237,7 @@ def remove_from_list(name, lst): def try_alt_nzb(nzo): - """ Try to get a new NZB if available """ + """Try to get a new NZB if available""" url = nzo.nzo_info.get("failure") if url and cfg.new_nzb_on_failure(): sabnzbd.add_url(url, nzo.pp, nzo.script, nzo.cat, nzo.priority) diff --git a/sabnzbd/powersup.py b/sabnzbd/powersup.py index 32aa298..f4b0f9a 100644 --- a/sabnzbd/powersup.py +++ b/sabnzbd/powersup.py @@ -37,7 +37,7 @@ except ImportError: def win_power_privileges(): - """ To do any power-options, the process needs higher privileges """ + """To do any power-options, the process needs higher privileges""" flags = ntsecuritycon.TOKEN_ADJUST_PRIVILEGES | ntsecuritycon.TOKEN_QUERY htoken = win32security.OpenProcessToken(win32api.GetCurrentProcess(), flags) id_ = win32security.LookupPrivilegeValue(None, ntsecuritycon.SE_SHUTDOWN_NAME) @@ -46,7 +46,7 @@ def win_power_privileges(): def win_hibernate(): - """ Hibernate Windows system, returns after wakeup """ + """Hibernate Windows system, returns after wakeup""" try: win_power_privileges() win32api.SetSystemPowerState(False, True) @@ -56,7 +56,7 @@ def win_hibernate(): def win_standby(): - """ Standby Windows system, returns after wakeup """ + """Standby Windows system, returns after wakeup""" try: win_power_privileges() win32api.SetSystemPowerState(True, True) @@ -66,7 +66,7 @@ def win_standby(): def win_shutdown(): - """ Shutdown Windows system, never returns """ + """Shutdown Windows system, never returns""" try: win_power_privileges() win32api.InitiateSystemShutdown("", "", 30, 1, 0) @@ -80,7 +80,7 @@ def win_shutdown(): def osx_shutdown(): - """ Shutdown macOS system, never returns """ + """Shutdown macOS system, never returns""" try: subprocess.call(["osascript", "-e", 'tell app "System Events" to shut down']) except: @@ -90,7 +90,7 @@ def osx_shutdown(): def osx_standby(): - """ Make macOS system sleep, returns after wakeup """ + """Make macOS system sleep, returns after wakeup""" try: subprocess.call(["osascript", "-e", 'tell app "System Events" to sleep']) time.sleep(10) @@ -100,7 +100,7 @@ def osx_standby(): def osx_hibernate(): - """ Make macOS system sleep, returns after wakeup """ + """Make macOS system sleep, returns after wakeup""" osx_standby() @@ -131,7 +131,7 @@ _LOGIND_SUCCESSFUL_RESULT = "yes" def _get_sessionproxy(): - """ Return (proxy-object, interface), (None, None) if not available """ + """Return (proxy-object, interface), (None, None) if not available""" name = "org.freedesktop.PowerManagement" path = "/org/freedesktop/PowerManagement" interface = "org.freedesktop.PowerManagement" @@ -143,7 +143,7 @@ def _get_sessionproxy(): def _get_systemproxy(method): - """ Return (proxy-object, interface, pinterface), (None, None, None) if not available """ + """Return (proxy-object, interface, pinterface), (None, None, None) if not available""" if method == "ConsoleKit": name = "org.freedesktop.ConsoleKit" path = "/org/freedesktop/ConsoleKit/Manager" @@ -173,7 +173,7 @@ def _get_systemproxy(method): def linux_shutdown(): - """ Make Linux system shutdown, never returns """ + """Make Linux system shutdown, never returns""" if not HAVE_DBUS: os._exit(0) @@ -201,7 +201,7 @@ def linux_shutdown(): def linux_hibernate(): - """ Make Linux system go into hibernate, returns after wakeup """ + """Make Linux system go into hibernate, returns after wakeup""" if not HAVE_DBUS: return @@ -230,7 +230,7 @@ def linux_hibernate(): def linux_standby(): - """ Make Linux system go into standby, returns after wakeup """ + """Make Linux system go into standby, returns after wakeup""" if not HAVE_DBUS: return diff --git a/sabnzbd/rss.py b/sabnzbd/rss.py index fc74310..45619b2 100644 --- a/sabnzbd/rss.py +++ b/sabnzbd/rss.py @@ -43,7 +43,7 @@ import feedparser def notdefault(item): - """ Return True if not 'Default|''|*' """ + """Return True if not 'Default|''|*'""" return bool(item) and str(item).lower() not in ("default", "*", "", str(DEFAULT_PRIORITY)) @@ -132,7 +132,7 @@ class RSSReader: @synchronized(RSS_LOCK) def run_feed(self, feed=None, download=False, ignoreFirst=False, force=False, readout=True): - """ Run the query for one URI and apply filters """ + """Run the query for one URI and apply filters""" self.shutdown = False if not feed: @@ -469,7 +469,7 @@ class RSSReader: return msg def run(self): - """ Run all the URI's and filters """ + """Run all the URI's and filters""" if not sabnzbd.PAUSED_ALL: active = False if self.next_run < time.time(): @@ -630,7 +630,7 @@ def _HandleLink( priority=DEFAULT_PRIORITY, rule=0, ): - """ Process one link """ + """Process one link""" if script == "": script = None if pp == "": @@ -746,7 +746,7 @@ def _get_link(entry): def special_rss_site(url): - """ Return True if url describes an RSS site with odd titles """ + """Return True if url describes an RSS site with odd titles""" return cfg.rss_filenames() or match_str(url, cfg.rss_odd_titles()) diff --git a/sabnzbd/sabtray.py b/sabnzbd/sabtray.py index 94c1b36..c3615ec 100644 --- a/sabnzbd/sabtray.py +++ b/sabnzbd/sabtray.py @@ -86,14 +86,14 @@ class SABTrayThread(SysTrayIconThread): super().__init__(self.sabicons["default"], "SABnzbd", menu_options, None, 0, "SabTrayIcon") def set_texts(self): - """ Cache texts for performance, doUpdates is called often """ + """Cache texts for performance, doUpdates is called often""" self.txt_idle = T("Idle") self.txt_paused = T("Paused") self.txt_remaining = T("Remaining") # called every few ms by SysTrayIconThread def doUpdates(self): - """ Update menu info, once every 10 calls """ + """Update menu info, once every 10 calls""" self.counter += 1 if self.counter > 10: self.sabpaused, bytes_left, bpsnow, time_left = api.fast_queue() @@ -143,7 +143,7 @@ class SABTrayThread(SysTrayIconThread): self.pause() def pausefor(self, minutes): - """ Need function for each pause-timer """ + """Need function for each pause-timer""" sabnzbd.Scheduler.plan_resume(minutes) def pausefor5min(self, icon): diff --git a/sabnzbd/sabtraylinux.py b/sabnzbd/sabtraylinux.py index 4db49c8..db28e55 100644 --- a/sabnzbd/sabtraylinux.py +++ b/sabnzbd/sabtraylinux.py @@ -116,7 +116,7 @@ class StatusIcon(Thread): return 1 def right_click_event(self, icon, button, time): - """ menu """ + """menu""" menu = Gtk.Menu() maddnzb = Gtk.MenuItem(label=T("Add NZB")) @@ -151,7 +151,7 @@ class StatusIcon(Thread): menu.popup(None, None, None, self.statusicon, button, time) def addnzb(self, icon): - """ menu handlers """ + """menu handlers""" dialog = Gtk.FileChooserDialog(title="SABnzbd - " + T("Add NZB"), action=Gtk.FileChooserAction.OPEN) dialog.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK) dialog.set_select_multiple(True) diff --git a/sabnzbd/scheduler.py b/sabnzbd/scheduler.py index d497659..ecd2565 100644 --- a/sabnzbd/scheduler.py +++ b/sabnzbd/scheduler.py @@ -47,16 +47,16 @@ class Scheduler: self.load_schedules() def start(self): - """ Start the scheduler """ + """Start the scheduler""" self.scheduler.start() def stop(self): - """ Stop the scheduler, destroy instance """ + """Stop the scheduler, destroy instance""" logging.debug("Stopping scheduler") self.scheduler.stop() def restart(self, plan_restart=True): - """ Stop and start scheduler """ + """Stop and start scheduler""" if plan_restart: self.restart_scheduler = True elif self.restart_scheduler: @@ -73,7 +73,7 @@ class Scheduler: self.scheduler.running = False def is_alive(self): - """ Thread-like check if we are doing fine """ + """Thread-like check if we are doing fine""" if self.scheduler.thread: return self.scheduler.thread.is_alive() return False @@ -336,11 +336,11 @@ class Scheduler: config.save_config() def scheduler_restart_guard(self): - """ Set flag for scheduler restart """ + """Set flag for scheduler restart""" self.restart_scheduler = True def scheduled_resume(self): - """ Scheduled resume, only when no oneshot resume is active """ + """Scheduled resume, only when no oneshot resume is active""" if self.pause_end is None: sabnzbd.unpause_all() @@ -356,7 +356,7 @@ class Scheduler: logging.debug("Ignoring cancelled resume") def plan_resume(self, interval): - """ Set a scheduled resume after the interval """ + """Set a scheduled resume after the interval""" if interval > 0: self.pause_end = time.time() + (interval * 60) logging.debug("Schedule resume at %s", self.pause_end) @@ -367,7 +367,7 @@ class Scheduler: sabnzbd.unpause_all() def __check_diskspace(self, full_dir: str, required_space: float): - """ Resume if there is sufficient available space """ + """Resume if there is sufficient available space""" if not cfg.fulldisk_autoresume(): self.cancel_resume_task() return @@ -384,7 +384,7 @@ class Scheduler: self.cancel_resume_task() def plan_diskspace_resume(self, full_dir: str, required_space: float): - """ Create regular check for free disk space """ + """Create regular check for free disk space""" self.cancel_resume_task() logging.info("Will resume when %s has more than %d GB free space", full_dir, required_space) self.resume_task = self.scheduler.add_interval_task( @@ -392,14 +392,14 @@ class Scheduler: ) def cancel_resume_task(self): - """ Cancel the current auto resume task """ + """Cancel the current auto resume task""" if self.resume_task: logging.debug("Cancelling existing resume_task '%s'", self.resume_task.name) self.scheduler.cancel(self.resume_task) self.resume_task = None def pause_int(self) -> str: - """ Return minutes:seconds until pause ends """ + """Return minutes:seconds until pause ends""" if self.pause_end is None: return "0" else: @@ -414,18 +414,18 @@ class Scheduler: return "%s%d:%02d" % (sign, mins, sec) def pause_check(self): - """ Unpause when time left is negative, compensate for missed schedule """ + """Unpause when time left is negative, compensate for missed schedule""" if self.pause_end is not None and (self.pause_end - time.time()) < 0: self.pause_end = None logging.debug("Force resume, negative timer") sabnzbd.unpause_all() def plan_server(self, action, parms, interval): - """ Plan to re-activate server after 'interval' minutes """ + """Plan to re-activate server after 'interval' minutes""" self.scheduler.add_single_task(action, "", interval * 60, args=parms) def force_rss(self): - """ Add a one-time RSS scan, one second from now """ + """Add a one-time RSS scan, one second from now""" self.scheduler.add_single_task(sabnzbd.RSSReader.run, "RSS", 1) diff --git a/sabnzbd/sorting.py b/sabnzbd/sorting.py index d551529..ee28e95 100644 --- a/sabnzbd/sorting.py +++ b/sabnzbd/sorting.py @@ -118,14 +118,14 @@ COUNTRY_REP = ( def ends_in_file(path): - """ Return True when path ends with '.%ext' or '%fn' """ + """Return True when path ends with '.%ext' or '%fn'""" _RE_ENDEXT = re.compile(r"\.%ext[{}]*$", re.I) _RE_ENDFN = re.compile(r"%fn[{}]*$", re.I) return bool(_RE_ENDEXT.search(path) or _RE_ENDFN.search(path)) def move_to_parent_folder(workdir): - """ Move all in 'workdir' into 'workdir/..' """ + """Move all in 'workdir' into 'workdir/..'""" # Determine 'folder'/.. workdir = os.path.abspath(os.path.normpath(workdir)) dest = os.path.abspath(os.path.normpath(os.path.join(workdir, ".."))) @@ -148,7 +148,7 @@ def move_to_parent_folder(workdir): class Sorter: - """ Generic Sorter class """ + """Generic Sorter class""" def __init__(self, nzo: Optional[NzbObject], cat): self.sorter = None @@ -159,7 +159,7 @@ class Sorter: self.ext = "" def detect(self, job_name, complete_dir): - """ Detect which kind of sort applies """ + """Detect which kind of sort applies""" self.sorter = SeriesSorter(self.nzo, job_name, complete_dir, self.cat) if self.sorter.matched: complete_dir = self.sorter.get_final_path() @@ -185,12 +185,12 @@ class Sorter: return complete_dir def rename(self, newfiles, workdir_complete): - """ Rename files of the job """ + """Rename files of the job""" if self.sorter.rename_or_not: self.sorter.rename(newfiles, workdir_complete) def rename_with_ext(self, workdir_complete): - """ Special renamer for %ext """ + """Special renamer for %ext""" if self.sorter.rename_or_not and "%ext" in workdir_complete and self.ext: # Replace %ext with extension newpath = workdir_complete.replace("%ext", self.ext) @@ -232,7 +232,7 @@ class Sorter: class SeriesSorter: - """ Methods for Series Sorting """ + """Methods for Series Sorting""" def __init__(self, nzo: Optional[NzbObject], job_name, path, cat): self.matched = False @@ -258,7 +258,7 @@ class SeriesSorter: self.match() def match(self, force=False): - """ Checks the regex for a match, if so set self.match to true """ + """Checks the regex for a match, if so set self.match to true""" if force or (cfg.enable_tv_sorting() and cfg.tv_sort_string()): if ( force @@ -273,11 +273,11 @@ class SeriesSorter: self.matched = True def is_match(self): - """ Returns whether there was a match or not """ + """Returns whether there was a match or not""" return self.matched def get_final_path(self): - """ Collect and construct all the variables such as episode name, show names """ + """Collect and construct all the variables such as episode name, show names""" if self.get_values(): # Get the final path path = self.construct_path() @@ -289,7 +289,7 @@ class SeriesSorter: @staticmethod def get_multi_ep_naming(one, two, extras): - """ Returns a list of unique values joined into a string and separated by - (ex:01-02-03-04) """ + """Returns a list of unique values joined into a string and separated by - (ex:01-02-03-04)""" extra_list = [one] extra2_list = [two] for extra in extras: @@ -303,7 +303,7 @@ class SeriesSorter: return one, two def get_shownames(self): - """ Get the show name from the match object and format it """ + """Get the show name from the match object and format it""" # Get the formatted title and alternate title formats self.show_info["show_tname"], self.show_info["show_tname_two"], self.show_info["show_tname_three"] = get_titles( self.nzo, self.match_obj, self.original_job_name, True @@ -313,7 +313,7 @@ class SeriesSorter: ) def get_seasons(self): - """ Get the season number from the match object and format it """ + """Get the season number from the match object and format it""" try: season = self.match_obj.group(1).strip("_") # season number except AttributeError: @@ -333,7 +333,7 @@ class SeriesSorter: self.show_info["season_num_alt"] = season2 def get_episodes(self): - """ Get the episode numbers from the match object, format and join them """ + """Get the episode numbers from the match object, format and join them""" try: ep_no = self.match_obj.group(2) # episode number except AttributeError: @@ -355,7 +355,7 @@ class SeriesSorter: self.show_info["episode_num_alt"] = ep_no2 def get_showdescriptions(self): - """ Get the show descriptions from the match object and format them """ + """Get the show descriptions from the match object and format them""" self.show_info["ep_name"], self.show_info["ep_name_two"], self.show_info["ep_name_three"] = get_descriptions( self.nzo, self.match_obj, self.original_job_name ) @@ -364,7 +364,7 @@ class SeriesSorter: self.show_info["resolution"] = get_resolution(self.original_job_name) def get_values(self): - """ Collect and construct all the values needed for path replacement """ + """Collect and construct all the values needed for path replacement""" try: # - Show Name self.get_shownames() @@ -389,7 +389,7 @@ class SeriesSorter: return False def construct_path(self): - """ Replaces the sort string with real values such as Show Name and Episode Number """ + """Replaces the sort string with real values such as Show Name and Episode Number""" sorter = self.sort_string.replace("\\", "/") mapping = [] @@ -463,7 +463,7 @@ class SeriesSorter: return head def rename(self, files, current_path): - """ Rename for Series """ + """Rename for Series""" logging.debug("Renaming Series") largest = (None, None, 0) @@ -522,7 +522,7 @@ _RE_MULTIPLE = ( def check_for_multiple(files): - """ Return list of files that looks like a multi-part post """ + """Return list of files that looks like a multi-part post""" for regex in _RE_MULTIPLE: matched_files = check_for_sequence(regex, files) if matched_files: @@ -531,7 +531,7 @@ def check_for_multiple(files): def check_for_sequence(regex, files): - """ Return list of files that looks like a sequence, using 'regex' """ + """Return list of files that looks like a sequence, using 'regex'""" matches = {} prefix = None # Build up a dictionary of matches @@ -581,7 +581,7 @@ def check_for_sequence(regex, files): class MovieSorter: - """ Methods for Generic Sorting """ + """Methods for Generic Sorting""" def __init__(self, nzo: Optional[NzbObject], job_name, path, cat): self.matched = False @@ -607,7 +607,7 @@ class MovieSorter: self.match() def match(self, force=False): - """ Checks the category for a match, if so set self.match to true """ + """Checks the category for a match, if so set self.match to true""" if force or (cfg.enable_movie_sorting() and self.sort_string): # First check if the show matches TV episode regular expressions. Returns regex match object if force or (self.cat and self.cat.lower() in self.cats) or (not self.cat and "None" in self.cats): @@ -615,7 +615,7 @@ class MovieSorter: self.matched = True def get_final_path(self): - """ Collect and construct all the variables such as episode name, show names """ + """Collect and construct all the variables such as episode name, show names""" if self.get_values(): # Get the final path path = self.construct_path() @@ -626,7 +626,7 @@ class MovieSorter: return os.path.join(self.original_path, self.original_job_name) def get_values(self): - """ Collect and construct all the values needed for path replacement """ + """Collect and construct all the values needed for path replacement""" # - Get Year if self.nzo: year = self.nzo.nzo_info.get("year") @@ -663,7 +663,7 @@ class MovieSorter: return True def construct_path(self): - """ Return path reconstructed from original and sort expression """ + """Return path reconstructed from original and sort expression""" sorter = self.sort_string.replace("\\", "/") mapping = [] @@ -731,7 +731,7 @@ class MovieSorter: return head def rename(self, _files, current_path): - """ Rename for Generic files """ + """Rename for Generic files""" logging.debug("Renaming Generic file") def filter_files(_file, current_path): @@ -801,7 +801,7 @@ class MovieSorter: class DateSorter: - """ Methods for Date Sorting """ + """Methods for Date Sorting""" def __init__(self, nzo: Optional[NzbObject], job_name, path, cat): self.matched = False @@ -827,7 +827,7 @@ class DateSorter: self.match() def match(self, force=False): - """ Checks the category for a match, if so set self.matched to true """ + """Checks the category for a match, if so set self.matched to true""" if force or (cfg.enable_date_sorting() and self.sort_string): # First check if the show matches TV episode regular expressions. Returns regex match object if force or (self.cat and self.cat.lower() in self.cats) or (not self.cat and "None" in self.cats): @@ -837,11 +837,11 @@ class DateSorter: self.matched = True def is_match(self): - """ Returns whether there was a match or not """ + """Returns whether there was a match or not""" return self.matched def get_final_path(self): - """ Collect and construct all the variables such as episode name, show names """ + """Collect and construct all the variables such as episode name, show names""" if self.get_values(): # Get the final path path = self.construct_path() @@ -852,7 +852,7 @@ class DateSorter: return os.path.join(self.original_path, self.original_job_name) def get_values(self): - """ Collect and construct all the values needed for path replacement """ + """Collect and construct all the values needed for path replacement""" # 2008-10-16 if self.date_type == 1: @@ -889,7 +889,7 @@ class DateSorter: return True def construct_path(self): - """ Return path reconstructed from original and sort expression """ + """Return path reconstructed from original and sort expression""" sorter = self.sort_string.replace("\\", "/") mapping = [] @@ -973,7 +973,7 @@ class DateSorter: return head def rename(self, files, current_path): - """ Renaming Date file """ + """Renaming Date file""" logging.debug("Renaming Date file") # find the master file to rename for file in files: @@ -1103,7 +1103,7 @@ def get_titles(nzo: NzbObject, match, name, titleing=False): def replace_word(word_input, one, two): - """ Regex replace on just words """ + """Regex replace on just words""" regex = re.compile(r"\W(%s)(\W|$)" % one, re.I) matches = regex.findall(word_input) if matches: @@ -1138,7 +1138,7 @@ def get_descriptions(nzo: NzbObject, match, name): def get_decades(year): - """ Return 4 digit and 2 digit decades given 'year' """ + """Return 4 digit and 2 digit decades given 'year'""" if year: try: decade = year[2:3] + "0" @@ -1163,7 +1163,7 @@ def get_resolution(job_name): def check_for_folder(path): - """ Return True if any folder is found in the tree at 'path' """ + """Return True if any folder is found in the tree at 'path'""" for _root, dirs, _files in os.walk(path): if dirs: return True @@ -1171,7 +1171,7 @@ def check_for_folder(path): def to_lowercase(path): - """ Lowercases any characters enclosed in {} """ + """Lowercases any characters enclosed in {}""" _RE_LOWERCASE = re.compile(r"{([^{]*)}") while True: m = _RE_LOWERCASE.search(path) @@ -1197,7 +1197,7 @@ def strip_folders(path): f.insert(0, "") def strip_all(x): - """ Strip all leading/trailing underscores also dots for Windows """ + """Strip all leading/trailing underscores also dots for Windows""" x = x.strip().strip("_") if sabnzbd.WIN32: # macOS and Linux should keep dots, because leading dots are significant @@ -1287,7 +1287,7 @@ def check_for_date(filename, matcher): def is_full_path(file): - """ Return True if path is absolute """ + """Return True if path is absolute""" if file.startswith("\\") or file.startswith("/"): return True try: @@ -1299,7 +1299,7 @@ def is_full_path(file): def eval_sort(sorttype, expression, name=None, multipart=""): - """ Preview a sort expression, to be used by API """ + """Preview a sort expression, to be used by API""" from sabnzbd.api import Ttemplate path = "" diff --git a/sabnzbd/urlgrabber.py b/sabnzbd/urlgrabber.py index cbf1205..3f3f094 100644 --- a/sabnzbd/urlgrabber.py +++ b/sabnzbd/urlgrabber.py @@ -68,7 +68,7 @@ class URLGrabber(Thread): self.shutdown = False def add(self, url: str, future_nzo: NzbObject, when: Optional[int] = None): - """ Add an URL to the URLGrabber queue, 'when' is seconds from now """ + """Add an URL to the URLGrabber queue, 'when' is seconds from now""" if future_nzo and when: # Always increase counter future_nzo.url_tries += 1 diff --git a/sabnzbd/utils/apireg.py b/sabnzbd/utils/apireg.py index eb30732..e3def7e 100644 --- a/sabnzbd/utils/apireg.py +++ b/sabnzbd/utils/apireg.py @@ -23,7 +23,7 @@ import winreg def reg_info(user): - """ Return the reg key for API """ + """Return the reg key for API""" if user: # Normally use the USER part of the registry section = winreg.HKEY_CURRENT_USER @@ -64,7 +64,7 @@ def get_connection_info(user=True): def set_connection_info(url, user=True): - """ Set API info in register """ + """Set API info in register""" section, keypath = reg_info(user) try: hive = winreg.ConnectRegistry(None, section) @@ -85,7 +85,7 @@ def set_connection_info(url, user=True): def del_connection_info(user=True): - """ Remove API info from register """ + """Remove API info from register""" section, keypath = reg_info(user) try: hive = winreg.ConnectRegistry(None, section) @@ -100,7 +100,7 @@ def del_connection_info(user=True): def get_install_lng(): - """ Return language-code used by the installer """ + """Return language-code used by the installer""" lng = 0 try: hive = winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER) diff --git a/sabnzbd/utils/checkdir.py b/sabnzbd/utils/checkdir.py index 0ba5c11..b56b6bb 100644 --- a/sabnzbd/utils/checkdir.py +++ b/sabnzbd/utils/checkdir.py @@ -11,7 +11,7 @@ debug = False def getcmdoutput(cmd): - """ execectue cmd, and give back output lines as array """ + """execectue cmd, and give back output lines as array""" with os.popen(cmd) as p: outputlines = p.readlines() return outputlines diff --git a/sabnzbd/utils/internetspeed.py b/sabnzbd/utils/internetspeed.py index 8fb778d..d43f22b 100755 --- a/sabnzbd/utils/internetspeed.py +++ b/sabnzbd/utils/internetspeed.py @@ -18,7 +18,7 @@ SIZE_URL_LIST = [ def measure_speed_from_url(url: str) -> float: - """ Download the specified url (pointing to a file), and report back MB/s (as a float) """ + """Download the specified url (pointing to a file), and report back MB/s (as a float)""" logging.debug("URL is %s", url) start = time.time() downloaded_bytes = 0 # default @@ -38,12 +38,12 @@ def measure_speed_from_url(url: str) -> float: def bytes_to_bits(megabytes_per_second: float) -> float: - """ convert bytes (per second) to bits (per second), taking into a account network overhead""" + """convert bytes (per second) to bits (per second), taking into a account network overhead""" return 8.05 * megabytes_per_second # bits def internetspeed() -> float: - """ Report Internet speed in MB/s as a float """ + """Report Internet speed in MB/s as a float""" # Do basic test with a small download logging.debug("Basic measurement, with small download:") urlbasic = SIZE_URL_LIST[0][1] # get first URL, which is smallest download diff --git a/sabnzbd/utils/servertests.py b/sabnzbd/utils/servertests.py index 9808218..e70cc69 100644 --- a/sabnzbd/utils/servertests.py +++ b/sabnzbd/utils/servertests.py @@ -64,7 +64,7 @@ def test_nntp_server_dict(kwargs): def test_nntp_server(host, port, server=None, username=None, password=None, ssl=None, ssl_verify=1, ssl_ciphers=None): - """ Will connect (blocking) to the nttp server and report back any errors """ + """Will connect (blocking) to the nttp server and report back any errors""" timeout = 4.0 if "*" in password and not password.strip("*"): # If the password is masked, try retrieving it from the config diff --git a/sabnzbd/utils/sleepless.py b/sabnzbd/utils/sleepless.py index ccde50f..a99754e 100644 --- a/sabnzbd/utils/sleepless.py +++ b/sabnzbd/utils/sleepless.py @@ -58,7 +58,7 @@ def keep_awake(reason): def allow_sleep(): - """ Allow OS to go to sleep """ + """Allow OS to go to sleep""" global assertion_id if assertion_id: IOPMAssertionRelease(assertion_id) diff --git a/sabnzbd/zconfig.py b/sabnzbd/zconfig.py index 2580ced..2c34ffe 100644 --- a/sabnzbd/zconfig.py +++ b/sabnzbd/zconfig.py @@ -55,7 +55,7 @@ def _zeroconf_callback(sdRef, flags, errorCode, name, regtype, domain): def set_bonjour(host=None, port=None): - """ Publish host/port combo through Bonjour """ + """Publish host/port combo through Bonjour""" global _HOST_PORT, _BONJOUR_OBJECT if not _HAVE_BONJOUR or not cfg.enable_broadcast(): @@ -109,7 +109,7 @@ def _bonjour_server(refObject): def remove_server(): - """ Remove Bonjour registration """ + """Remove Bonjour registration""" global _BONJOUR_OBJECT if _BONJOUR_OBJECT: _BONJOUR_OBJECT.close() diff --git a/scripts/Deobfuscate.py b/scripts/Deobfuscate.py index 05fca0a..9ee002d 100755 --- a/scripts/Deobfuscate.py +++ b/scripts/Deobfuscate.py @@ -84,7 +84,7 @@ STRUCT_FILE_DESC_PACKET = struct.Struct( # Supporting functions def print_splitter(): - """ Simple helper function """ + """Simple helper function""" print("\n------------------------\n") diff --git a/tests/conftest.py b/tests/conftest.py index ac002da..6b5c847 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -123,7 +123,7 @@ def run_sabnzbd(clean_cache_dir): @pytest.fixture(scope="session") def run_sabnews_and_selenium(request): - """ Start SABNews and Selenium/Chromedriver, shared across the pytest session. """ + """Start SABNews and Selenium/Chromedriver, shared across the pytest session.""" # We only try Chrome for consistent results driver_options = ChromeOptions() @@ -171,7 +171,7 @@ def run_sabnews_and_selenium(request): @pytest.fixture(scope="class") def generate_fake_history(request): - """ Add fake entries to the history db """ + """Add fake entries to the history db""" history_size = randint(42, 81) try: history_db = os.path.join(SAB_CACHE_DIR, DEF_ADMIN_DIR, DB_HISTORY_NAME) @@ -189,7 +189,7 @@ def generate_fake_history(request): @pytest.fixture(scope="function") def update_history_specs(request): - """ Update the history size at the start of every test """ + """Update the history size at the start of every test""" if request.function.__name__.startswith("test_"): json = get_api_result( "history", diff --git a/tests/test_api_and_interface.py b/tests/test_api_and_interface.py index 61dfb0d..68973a8 100644 --- a/tests/test_api_and_interface.py +++ b/tests/test_api_and_interface.py @@ -28,7 +28,7 @@ import sabnzbd.interface as interface class TestApiInternals: - """ Test internal functions of the API """ + """Test internal functions of the API""" def test_empty(self): with pytest.raises(TypeError): @@ -68,13 +68,13 @@ class TestApiInternals: def set_remote_host_or_ip(hostname: str = "localhost", remote_ip: str = "127.0.0.1"): - """ Change CherryPy's "Host" and "remote.ip"-values """ + """Change CherryPy's "Host" and "remote.ip"-values""" cherrypy.request.headers["Host"] = hostname cherrypy.request.remote.ip = remote_ip class TestSecuredExpose: - """ Test the security handling """ + """Test the security handling""" main_page = sabnzbd.interface.MainPage() diff --git a/tests/test_config.py b/tests/test_config.py index c591939..3ece048 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -30,7 +30,7 @@ class TestValidators: """ def assert_allowed(inp_value): - """ Helper function to check for block """ + """Helper function to check for block""" msg, value = config.clean_nice_ionice_parameters(inp_value) assert msg is None assert value == inp_value @@ -62,10 +62,10 @@ class TestValidators: assert_allowed("-t -n9 -c7") def test_clean_nice_ionice_parameters_blocked(self): - """ Should all be blocked """ + """Should all be blocked""" def assert_blocked(inp_value): - """ Helper function to check for block """ + """Helper function to check for block""" msg, value = config.clean_nice_ionice_parameters(inp_value) assert msg assert msg.startswith("Incorrect parameter") diff --git a/tests/test_functional_adding_nzbs.py b/tests/test_functional_adding_nzbs.py index 7fe306c..e869252 100644 --- a/tests/test_functional_adding_nzbs.py +++ b/tests/test_functional_adding_nzbs.py @@ -172,7 +172,7 @@ class TestAddingNZBs: assert VAR.SCRIPT_DIR in json["config"]["misc"]["script_dir"] def _customize_pre_queue_script(self, priority, category): - """ Add a script that accepts the job and sets priority & category """ + """Add a script that accepts the job and sets priority & category""" script_name = "SCRIPT%s.py" % SCRIPT_RANDOM try: script_path = os.path.join(VAR.SCRIPT_DIR, script_name) @@ -255,7 +255,7 @@ class TestAddingNZBs: return self._create_random_nzb(metadata={"category": cat_meta}) def _expected_results(self, STAGES, return_state=None): - """ Figure out what priority and state the job should end up with """ + """Figure out what priority and state the job should end up with""" # Define a bunch of helpers def sanitize_stages(hit_stage, STAGES): # Fallback is always category-based, so nix any explicit priorities (stages 1, 3). @@ -275,7 +275,7 @@ class TestAddingNZBs: return STAGES def handle_state_prio(hit_stage, STAGES, return_state): - """ Find the priority that should to be set after changing the job state """ + """Find the priority that should to be set after changing the job state""" # Keep record of the priority that caused the initial hit (for verification of the job state later on) if not return_state: return_state = STAGES[hit_stage] @@ -318,7 +318,7 @@ class TestAddingNZBs: return self._expected_results(STAGES, return_state) def handle_default_cat(hit_stage, STAGES, return_state): - """ Figure out the (category) default priority """ + """Figure out the (category) default priority""" STAGES = sanitize_stages(hit_stage, STAGES) # Strip the current -100 hit before recursing @@ -509,7 +509,7 @@ class TestAddingNZBs: ], ) def test_adding_nzbs_malformed(self, keep_first, keep_last, strip_first, strip_last, should_work): - """ Test adding broken, empty, or otherwise malformed NZB file """ + """Test adding broken, empty, or otherwise malformed NZB file""" if not VAR.NZB_FILE: VAR.NZB_FILE = self._create_random_nzb() @@ -549,7 +549,7 @@ class TestAddingNZBs: @pytest.mark.parametrize("prio_def_cat", sample(VALID_DEFAULT_PRIORITIES, 1)) @pytest.mark.parametrize("prio_add", PRIO_OPTS_ADD) def test_adding_nzbs_size_limit(self, prio_meta_cat, prio_def_cat, prio_add): - """ Verify state and priority of a job exceeding the size_limit """ + """Verify state and priority of a job exceeding the size_limit""" # Set size limit json = get_api_result( mode="set_config", extra_arguments={"section": "misc", "keyword": "size_limit", "value": MIN_FILESIZE - 1} diff --git a/tests/test_functional_api.py b/tests/test_functional_api.py index bed2056..eaa2cc6 100644 --- a/tests/test_functional_api.py +++ b/tests/test_functional_api.py @@ -35,22 +35,22 @@ from tests.testhelper import * class ApiTestFunctions: - """ Collection of (wrapper) functions for API testcases """ + """Collection of (wrapper) functions for API testcases""" def _get_api_json(self, mode, extra_args={}): - """ Wrapper for API calls with json output """ + """Wrapper for API calls with json output""" extra = {"output": "json", "apikey": SAB_APIKEY} extra.update(extra_args) return get_api_result(mode=mode, host=SAB_HOST, port=SAB_PORT, extra_arguments=extra) def _get_api_text(self, mode, extra_args={}): - """ Wrapper for API calls with text output """ + """Wrapper for API calls with text output""" extra = {"output": "text", "apikey": SAB_APIKEY} extra.update(extra_args) return get_api_result(mode=mode, host=SAB_HOST, port=SAB_PORT, extra_arguments=extra) def _get_api_xml(self, mode, extra_args={}): - """ Wrapper for API calls with xml output """ + """Wrapper for API calls with xml output""" extra = {"output": "xml", "apikey": SAB_APIKEY} extra.update(extra_args) return get_api_result(mode=mode, host=SAB_HOST, port=SAB_PORT, extra_arguments=extra) @@ -84,14 +84,14 @@ class ApiTestFunctions: self._get_api_json("set_config", extra_args=script_dir_extra) def _record_slots(self, keys): - """ Return a list of dicts, storing queue info for the items in iterable 'keys' """ + """Return a list of dicts, storing queue info for the items in iterable 'keys'""" record = [] for slot in self._get_api_json("queue")["queue"]["slots"]: record.append({key: slot[key] for key in keys}) return record def _run_tavern(self, test_name, extra_vars=None): - """ Run tavern tests in ${test_name}.yaml """ + """Run tavern tests in ${test_name}.yaml""" vars = [ ("SAB_HOST", SAB_HOST), ("SAB_PORT", SAB_PORT), @@ -111,7 +111,7 @@ class ApiTestFunctions: assert result is result.OK def _get_api_history(self, extra={}): - """ Wrapper for history-related api calls """ + """Wrapper for history-related api calls""" # Set a higher default limit; the default is 10 via cfg(history_limit) if "limit" not in extra.keys() and "name" not in extra.keys(): # History calls that use 'name' don't need the limit parameter @@ -172,21 +172,21 @@ class ApiTestFunctions: warn("Failed to remove %s" % job_dir) def _purge_queue(self, del_files=0): - """ Clear the entire queue """ + """Clear the entire queue""" self._get_api_json("queue", extra_args={"name": "purge", "del_files": del_files}) assert len(self._get_api_json("queue")["queue"]["slots"]) == 0 @pytest.mark.usefixtures("run_sabnzbd") class TestOtherApi(ApiTestFunctions): - """ Test API function not directly involving either history or queue """ + """Test API function not directly involving either history or queue""" def test_api_version_testhelper(self): - """ Check the version, testhelper style """ + """Check the version, testhelper style""" assert "version" in get_api_result("version", SAB_HOST, SAB_PORT) def test_api_version_tavern(self): - """ Same same, tavern style """ + """Same same, tavern style""" self._run_tavern("api_version") def test_api_version_json(self): @@ -199,7 +199,7 @@ class TestOtherApi(ApiTestFunctions): assert self._get_api_xml("version")["version"] == sabnzbd.__version__ def test_api_server_stats(self): - """ Verify server stats format """ + """Verify server stats format""" self._run_tavern("api_server_stats") @pytest.mark.parametrize("extra_args", [{}, {"name": "change_complete_action", "value": ""}]) @@ -403,10 +403,10 @@ class TestOtherApi(ApiTestFunctions): @pytest.mark.usefixtures("run_sabnzbd") class TestQueueApi(ApiTestFunctions): - """ Test queue-related API responses """ + """Test queue-related API responses""" def test_api_queue_empty_format(self): - """ Verify formatting, presence of fields for empty queue """ + """Verify formatting, presence of fields for empty queue""" self._purge_queue() self._run_tavern("api_queue_empty") @@ -566,7 +566,7 @@ class TestQueueApi(ApiTestFunctions): self._get_api_json("queue", extra_args={"name": "change_complete_action", "value": ""}) def test_api_queue_single_format(self): - """ Verify formatting, presence of fields for single queue entry """ + """Verify formatting, presence of fields for single queue entry""" self._create_random_queue(minimum_size=1) self._run_tavern("api_queue_format") @@ -845,7 +845,7 @@ class TestQueueApi(ApiTestFunctions): assert changed[row] == original[row] def test_api_queue_get_files_format(self): - """ Verify formatting, presence of fields for mode=get_files """ + """Verify formatting, presence of fields for mode=get_files""" self._create_random_queue(minimum_size=1) nzo_id = self._get_api_json("queue")["queue"]["slots"][0]["nzo_id"] # Pass the nzo_id this way rather than fetching it in a tavern stage, as @@ -896,10 +896,10 @@ class TestQueueApi(ApiTestFunctions): @pytest.mark.usefixtures("run_sabnzbd", "generate_fake_history", "update_history_specs") class TestHistoryApi(ApiTestFunctions): - """ Test history-related API responses """ + """Test history-related API responses""" def test_api_history_format(self): - """ Verify formatting, presence of expected history fields """ + """Verify formatting, presence of expected history fields""" # Checks all output styles: json, text and xml self._run_tavern("api_history_format") @@ -974,7 +974,7 @@ class TestHistoryApi(ApiTestFunctions): assert len(json["history"]["slots"]) == 0 def test_api_history_restrict_cat_and_search_and_limit(self): - """ Combine search, category and limits requirements into a single query """ + """Combine search, category and limits requirements into a single query""" limit_sum = 0 slot_sum = 0 limits = [randint(1, ceil(self.history_size / 10)) for _ in range(0, len(self.history_distro_names))] @@ -1111,6 +1111,6 @@ class TestHistoryApiPart2(ApiTestFunctions): assert json["history"]["noofslots"] == 0 def test_api_history_empty_format(self): - """ Verify formatting, presence of fields for empty history """ + """Verify formatting, presence of fields for empty history""" # Checks all output styles: json, text and xml self._run_tavern("api_history_empty") diff --git a/tests/test_functional_misc.py b/tests/test_functional_misc.py index 6ac5264..42f4ca2 100644 --- a/tests/test_functional_misc.py +++ b/tests/test_functional_misc.py @@ -30,7 +30,7 @@ from tests.testhelper import * class TestShowLogging(SABnzbdBaseTest): def test_showlog(self): - """ Test the output of the filtered-log button """ + """Test the output of the filtered-log button""" # Basic URL-fetching, easier than Selenium file download log_result = get_url_result("status/showlog") @@ -92,7 +92,7 @@ class TestQueueRepair(SABnzbdBaseTest): class TestSamplePostProc: def test_sample_post_proc(self): - """ Make sure we don't break things """ + """Make sure we don't break things""" # Set parameters script_params = [ "somedir222", @@ -127,7 +127,7 @@ class TestSamplePostProc: class TestExtractPot: def test_extract_pot(self): - """ Simple test if translation extraction still works """ + """Simple test if translation extraction still works""" script_call = [sys.executable, "tools/extract_pot.py"] # Run script and check output diff --git a/tests/test_misc.py b/tests/test_misc.py index f4ee9aa..35add3a 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -224,7 +224,7 @@ class TestMisc: ], ) def test_list_to_cmd(self, test_input, expected_output): - """ Test to convert list to a cmd.exe-compatible command string """ + """Test to convert list to a cmd.exe-compatible command string""" res = misc.list2cmdline(test_input) # Make sure the output is cmd.exe-compatible diff --git a/tests/test_rss.py b/tests/test_rss.py index 5b03d1e..91b3804 100644 --- a/tests/test_rss.py +++ b/tests/test_rss.py @@ -29,7 +29,7 @@ import sabnzbd.config class TestRSS: @staticmethod def setup_rss(feed_name, feed_url): - """ Setup the basic settings to get things going""" + """Setup the basic settings to get things going""" # Setup the config settings sabnzbd.config.CFG = configobj.ConfigObj() sabnzbd.config.ConfigRSS(feed_name, {"uri": feed_url}) diff --git a/tests/test_utils/test_diskspeed.py b/tests/test_utils/test_diskspeed.py index e42ab6e..3def545 100644 --- a/tests/test_utils/test_diskspeed.py +++ b/tests/test_utils/test_diskspeed.py @@ -28,10 +28,10 @@ from tests.testhelper import SAB_CACHE_DIR @pytest.mark.usefixtures("clean_cache_dir") class TestDiskSpeed: - """ test sabnzbd.utils.diskspeed """ + """test sabnzbd.utils.diskspeed""" def test_disk_speed(self): - """ Test the normal use case: writable directory""" + """Test the normal use case: writable directory""" speed = diskspeedmeasure(SAB_CACHE_DIR) assert speed > 0.0 assert isinstance(speed, float) @@ -40,7 +40,7 @@ class TestDiskSpeed: assert not os.path.exists(os.path.join(SAB_CACHE_DIR, "outputTESTING.txt")) def test_non_existing_dir(self): - """ testing a non-existing dir should result in 0""" + """testing a non-existing dir should result in 0""" speed = diskspeedmeasure("such_a_dir_does_not_exist") assert speed == 0 @@ -54,7 +54,7 @@ class TestDiskSpeed: assert speed == 0 def test_file_not_dir_specified(self): - """ testing a file should result in 0""" + """testing a file should result in 0""" with tempfile.NamedTemporaryFile() as temp_file: speed = diskspeedmeasure(temp_file.name) assert speed == 0 diff --git a/tests/test_utils/test_pystone.py b/tests/test_utils/test_pystone.py index cd43cc7..a65efc6 100644 --- a/tests/test_utils/test_pystone.py +++ b/tests/test_utils/test_pystone.py @@ -24,7 +24,7 @@ from sabnzbd.utils.pystone import pystones class TestPystone: def test_pystone(self): - """ Tests for performance with various loop sizes """ + """Tests for performance with various loop sizes""" loops = [10, 1000, 50000, 100000] for loop in loops: benchtime, stones = pystones(loop) diff --git a/tests/test_win_utils.py b/tests/test_win_utils.py index 368f0c6..14ac98e 100644 --- a/tests/test_win_utils.py +++ b/tests/test_win_utils.py @@ -45,5 +45,5 @@ class TestAPIReg: assert not ar.get_connection_info(True) def test_get_install_lng(self): - """ Not much to test yet.. """ + """Not much to test yet..""" assert ar.get_install_lng() == "en" diff --git a/tests/testhelper.py b/tests/testhelper.py index 8cb2dae..71e120f 100644 --- a/tests/testhelper.py +++ b/tests/testhelper.py @@ -65,7 +65,7 @@ SAB_NEWSSERVER_PORT = 8888 def set_config(settings_dict): - """ Change config-values on the fly, per test""" + """Change config-values on the fly, per test""" def set_config_decorator(func): def wrapper_func(*args, **kwargs): @@ -87,7 +87,7 @@ def set_config(settings_dict): def set_platform(platform): - """ Change config-values on the fly, per test""" + """Change config-values on the fly, per test""" def set_platform_decorator(func): def wrapper_func(*args, **kwargs): @@ -121,13 +121,13 @@ def set_platform(platform): def get_url_result(url="", host=SAB_HOST, port=SAB_PORT): - """ Do basic request to web page """ + """Do basic request to web page""" arguments = {"apikey": SAB_APIKEY} return requests.get("http://%s:%s/%s/" % (host, port, url), params=arguments).text def get_api_result(mode, host=SAB_HOST, port=SAB_PORT, extra_arguments={}): - """ Build JSON request to SABnzbd """ + """Build JSON request to SABnzbd""" arguments = {"apikey": SAB_APIKEY, "output": "json", "mode": mode} arguments.update(extra_arguments) r = requests.get("http://%s:%s/api" % (host, port), params=arguments) @@ -139,13 +139,13 @@ def get_api_result(mode, host=SAB_HOST, port=SAB_PORT, extra_arguments={}): def create_nzb(nzb_dir, metadata=None): - """ Create NZB from directory using SABNews """ + """Create NZB from directory using SABNews""" nzb_dir_full = os.path.join(SAB_DATA_DIR, nzb_dir) return tests.sabnews.create_nzb(nzb_dir=nzb_dir_full, metadata=metadata) def create_and_read_nzb(nzbdir): - """ Create NZB, return data and delete file """ + """Create NZB, return data and delete file""" # Create NZB-file to import nzb_path = create_nzb(nzbdir) with open(nzb_path, "r") as nzb_data_fp: @@ -179,7 +179,7 @@ class FakeHistoryDB(db.HistoryDB): super().__init__() def add_fake_history_jobs(self, number_of_entries=1): - """ Generate a history db with any number of fake entries """ + """Generate a history db with any number of fake entries""" for _ in range(0, number_of_entries): nzo = mock.Mock() @@ -246,7 +246,7 @@ class SABnzbdBaseTest: @staticmethod def selenium_wrapper(func, *args): - """ Wrapper with retries for more stable Selenium """ + """Wrapper with retries for more stable Selenium""" for i in range(3): try: return func(*args) diff --git a/tools/extract_pot.py b/tools/extract_pot.py index 471d205..04611be 100755 --- a/tools/extract_pot.py +++ b/tools/extract_pot.py @@ -64,7 +64,7 @@ RE_CONTEXT = re.compile(r"#:\s*(.*)$") def get_a_line(line_src, number): - """ Retrieve line 'number' from file 'src' with caching """ + """Retrieve line 'number' from file 'src' with caching""" global FILE_CACHE if line_src not in FILE_CACHE: FILE_CACHE[line_src] = [] @@ -79,7 +79,7 @@ def get_a_line(line_src, number): def get_context(ctx_line): - """ Read context info from source file and append to line. """ + """Read context info from source file and append to line.""" if not ctx_line.startswith("#:"): return ctx_line @@ -125,7 +125,7 @@ def get_context(ctx_line): def add_tmpl_to_pot(prefix, dst_file): - """ Append english template to open POT file 'dst' """ + """Append english template to open POT file 'dst'""" with open(EMAIL_DIR + "/%s-en.tmpl" % prefix, "r") as tmpl_src: dst_file.write("#: email/%s.tmpl:1\n" % prefix) dst_file.write('msgid ""\n') diff --git a/tools/make_mo.py b/tools/make_mo.py index eb46b9a..b8147c1 100755 --- a/tools/make_mo.py +++ b/tools/make_mo.py @@ -140,7 +140,7 @@ RE_LANG = re.compile(r'"Language-Description:\s([^"]+)\\n') def run(cmd): - """ Run system command, returns exit-code and stdout """ + """Run system command, returns exit-code and stdout""" try: txt = subprocess.check_output(cmd, universal_newlines=True) ret = 0 @@ -152,7 +152,7 @@ def run(cmd): def process_po_folder(domain, folder, extra=""): - """ Process each PO file in folder """ + """Process each PO file in folder""" result = True for fname in glob.glob(os.path.join(folder, "*.po")): basename = os.path.split(fname)[1] @@ -180,7 +180,7 @@ def process_po_folder(domain, folder, extra=""): def remove_mo_files(): - """ Remove MO files in locale """ + """Remove MO files in locale""" for root, dirs, files in os.walk(MO_DIR, topdown=False): for f in files: if not f.startswith(DOMAIN): @@ -188,7 +188,7 @@ def remove_mo_files(): def translate_tmpl(prefix, lng): - """ Translate template 'prefix' into language 'lng' """ + """Translate template 'prefix' into language 'lng'""" # Open the original file with open(EMAIL_DIR + "/%s-en.tmpl" % prefix, "r", encoding="utf-8") as src: data = src.read() @@ -204,7 +204,7 @@ def translate_tmpl(prefix, lng): def make_templates(): - """ Create email templates """ + """Create email templates""" if not os.path.exists("email"): os.makedirs("email") for path in glob.glob(os.path.join(MO_DIR, "*")): @@ -224,7 +224,7 @@ def make_templates(): def patch_nsis(): - """ Patch translation into the NSIS script """ + """Patch translation into the NSIS script""" RE_NSIS = re.compile(r'^(\s*LangString\s+)(\w+)(\s+\$\{LANG_)(\w+)\}\s+(".*)', re.I) languages = [os.path.split(path)[1] for path in glob.glob(os.path.join(MO_DIR, "*"))] diff --git a/tools/msgfmt.py b/tools/msgfmt.py index 2ec1e22..1e14419 100755 --- a/tools/msgfmt.py +++ b/tools/msgfmt.py @@ -53,7 +53,7 @@ def usage(code, msg=""): def add(id, str, fuzzy): - """ Add a non-fuzzy translation to the dictionary. """ + """Add a non-fuzzy translation to the dictionary.""" global MESSAGES, nonewlines, RE_HTML if not fuzzy and str: if id.count(b"%s") == str.count(b"%s"):