diff --git a/.flake8 b/.flake8 deleted file mode 100755 index da976db..0000000 --- a/.flake8 +++ /dev/null @@ -1,7 +0,0 @@ -[flake8] -extend-ignore = - # E722 Do not use bare except, specify exception instead - E722, - # E402 module level import not at top of file - E402, -max-line-length = 130 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ca3ceef..92576db 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,3 +28,12 @@ jobs: - name: Run pre-commit version check run: | pre-commit run increase-version --all-files + + ruff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/ruff-action@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + command: 'ruff check' diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1bfe951..00d8eb2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,18 +8,11 @@ repos: - id: check-merge-conflict - id: check-json - id: check-yaml - - id: debug-statements - id: requirements-txt-fixer - id: check-added-large-files - id: fix-byte-order-marker - - id: fix-encoding-pragma - args: [--remove] - id: pretty-format-json args: [--autofix, --indent, '4', --no-sort-keys] - - repo: https://github.com/hhatto/autopep8 - rev: v2.3.2 - hooks: - - id: autopep8 - repo: https://github.com/adrienverge/yamllint.git rev: v1.35.1 # or higher tag hooks: @@ -31,28 +24,15 @@ repos: hooks: - id: yamlfix exclude: ^.github/ - - repo: https://github.com/pycqa/isort - rev: 6.0.0 + - repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.9.10 hooks: - - id: isort - name: isort (python) - args: [--force-single-line-imports, --profile, black] - - repo: https://github.com/asottile/pyupgrade - rev: v3.19.1 - hooks: - - id: pyupgrade - args: [--py3-plus] - - repo: https://github.com/psf/black - rev: 25.1.0 - hooks: - - id: black - language_version: python3 - args: [--line-length, '130'] - - repo: https://github.com/PyCQA/flake8 - rev: 7.1.2 - hooks: - - id: flake8 - args: [--config=.flake8] + # Run the linter. + - id: ruff + args: [--fix] + # Run the formatter. + - id: ruff-format - repo: local hooks: - id: increase-version diff --git a/CHANGELOG b/CHANGELOG index c01466e..7537085 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,9 +1,8 @@ # New Updates -- Removes deprecated cross-seed command/function (#758) -- Adds ability to tag stalled downloads (#757) -- Adds ability to customize a list of status to ignore during rem_unregistered command (#756) +- Adds new command to filter for completed torrents only for rem_unregistered (#747) +- Replace flake8/black with ruff for lint and formatting # Bug Fixes -- Fixes bug in Windows during category updates (#755) +- Fixes bug in tagging `stalledDL` torrents when set to False (#764) -**Full Changelog**: https://github.com/StuffAnThings/qbit_manage/compare/v4.1.18...v4.2.0 +**Full Changelog**: https://github.com/StuffAnThings/qbit_manage/compare/v4.2.0...v4.2.1 diff --git a/README.md b/README.md index b5ad7cc..dff8d3f 100755 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![Ghcr packages](https://img.shields.io/badge/ghcr.io-packages?style=plastic&label=packages)](https://ghcr.io/StuffAnThings/qbit_manage) [![Docker Pulls](https://img.shields.io/docker/pulls/bobokun/qbit_manage?style=plastic)](https://hub.docker.com/r/bobokun/qbit_manage) [![Sponsor or Donate](https://img.shields.io/badge/-Sponsor_or_Donate-blueviolet?style=plastic)](https://github.com/sponsors/bobokun) - +[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) This is a program used to manage your qBittorrent instance such as: * Tag torrents based on tracker URLs diff --git a/VERSION b/VERSION index 6aba2b2..fae6e3d 100755 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.2.0 +4.2.1 diff --git a/config/config.yml.sample b/config/config.yml.sample index 18332f4..d7d5661 100755 --- a/config/config.yml.sample +++ b/config/config.yml.sample @@ -39,6 +39,7 @@ settings: cat_filter_completed: True # Filters for completed torrents only when running cat_update command share_limits_filter_completed: True # Filters for completed torrents only when running share_limits command tag_nohardlinks_filter_completed: True # Filters for completed torrents only when running tag_nohardlinks command + rem_unregistered_filter_completed: False # Filters for completed torrents only when running rem_unregistered command cat_update_all: True # Checks and updates all torrent categories if set to True when running cat_update command, otherwise only update torrents that are uncategorized disable_qbt_default_share_limits: True # Allows QBM to handle share limits by disabling qBittorrents default Share limits. Only active when the share_limits command is set to True tag_stalled_torrents: True # Tags any downloading torrents that are stalled with the `stalledDL` tag when running the tag_update command diff --git a/modules/config.py b/modules/config.py index aa16759..eb54434 100755 --- a/modules/config.py +++ b/modules/config.py @@ -223,6 +223,9 @@ class Config: "tag_nohardlinks_filter_completed": self.util.check_for_attribute( self.data, "tag_nohardlinks_filter_completed", parent="settings", var_type="bool", default=True ), + "rem_unregistered_filter_completed": self.util.check_for_attribute( + self.data, "rem_unregistered_filter_completed", parent="settings", var_type="bool", default=False + ), "cat_update_all": self.util.check_for_attribute( self.data, "cat_update_all", parent="settings", var_type="bool", default=True ), @@ -847,7 +850,8 @@ class Config: try: fileStats = os.stat(file) filename = os.path.basename(file) - last_modified = fileStats[stat.ST_MTIME] # in seconds (last modified time) + # in seconds (last modified time) + last_modified = fileStats[stat.ST_MTIME] except FileNotFoundError: ex = logger.print_line( f"{location} Warning - FileNotFound: No such file or directory: {file} ", "WARNING" diff --git a/modules/core/category.py b/modules/core/category.py index d378362..9245a12 100644 --- a/modules/core/category.py +++ b/modules/core/category.py @@ -84,7 +84,7 @@ class Category: else: title = "Updating Categories" body += logger.print_line(logger.insert_space(f"New Category: {new_cat}", 3), self.config.loglevel) - body += logger.print_line(logger.insert_space(f'Tracker: {tracker["url"]}', 8), self.config.loglevel) + body += logger.print_line(logger.insert_space(f"Tracker: {tracker['url']}", 8), self.config.loglevel) attr = { "function": "cat_update", "title": title, diff --git a/modules/core/recheck.py b/modules/core/recheck.py index e0aaa39..93ac3fa 100644 --- a/modules/core/recheck.py +++ b/modules/core/recheck.py @@ -14,7 +14,8 @@ class ReCheck: self.stats_rechecked = 0 self.torrents_updated_recheck = [] # List of torrents updated - self.notify_attr_recheck = [] # List of single torrent attributes to send to notifiarr + # List of single torrent attributes to send to notifiarr + self.notify_attr_recheck = [] self.torrents_updated_resume = [] # List of torrents updated self.notify_attr_resume = [] # List of single torrent attributes to send to notifiarr diff --git a/modules/core/remove_unregistered.py b/modules/core/remove_unregistered.py index e425860..3f61f27 100644 --- a/modules/core/remove_unregistered.py +++ b/modules/core/remove_unregistered.py @@ -22,6 +22,7 @@ class RemoveUnregistered: self.cfg_rem_unregistered = self.config.commands["rem_unregistered"] self.cfg_tag_error = self.config.commands["tag_tracker_error"] self.rem_unregistered_ignore_list = self.config.settings["rem_unregistered_ignore_list"] + self.filter_completed = self.config.settings["rem_unregistered_filter_completed"] tag_error_msg = "Tagging Torrents with Tracker Errors" if self.cfg_tag_error else "" rem_unregistered_msg = "Removing Unregistered Torrents" if self.cfg_rem_unregistered else "" @@ -56,7 +57,7 @@ class RemoveUnregistered: ) body += logger.print_line(logger.insert_space(f"Torrent Name: {t_name}", 3), self.config.loglevel) body += logger.print_line(logger.insert_space(f"Removed Tag: {self.tag_error}", 4), self.config.loglevel) - body += logger.print_line(logger.insert_space(f'Tracker: {tracker["url"]}', 8), self.config.loglevel) + body += logger.print_line(logger.insert_space(f"Tracker: {tracker['url']}", 8), self.config.loglevel) if not self.config.dry_run: torrent.remove_tags(tags=self.tag_error) attr = { @@ -108,6 +109,8 @@ class RemoveUnregistered: self.t_status = self.qbt.torrentinfo[self.t_name]["status"] check_tags = util.get_list(torrent.tags) try: + if self.filter_completed and not torrent.state_enum.is_complete: + continue tracker_working = False for trk in torrent.trackers: if ( @@ -190,7 +193,7 @@ class RemoveUnregistered: tor_error = "" tor_error += logger.insert_space(f"Torrent Name: {self.t_name}", 3) + "\n" tor_error += logger.insert_space(f"Status: {msg}", 9) + "\n" - tor_error += logger.insert_space(f'Tracker: {tracker["url"]}', 8) + "\n" + tor_error += logger.insert_space(f"Tracker: {tracker['url']}", 8) + "\n" tor_error += logger.insert_space(f"Added Tag: {self.tag_error}", 6) + "\n" self.tor_error_summary += tor_error self.stats_tagged += 1 @@ -215,7 +218,7 @@ class RemoveUnregistered: body = [] body += logger.print_line(logger.insert_space(f"Torrent Name: {self.t_name}", 3), self.config.loglevel) body += logger.print_line(logger.insert_space(f"Status: {msg}", 9), self.config.loglevel) - body += logger.print_line(logger.insert_space(f'Tracker: {tracker["url"]}', 8), self.config.loglevel) + body += logger.print_line(logger.insert_space(f"Tracker: {tracker['url']}", 8), self.config.loglevel) attr = { "function": "rem_unregistered", "title": "Removing Unregistered Torrents", diff --git a/modules/core/share_limits.py b/modules/core/share_limits.py index 7a37a26..7bddddb 100644 --- a/modules/core/share_limits.py +++ b/modules/core/share_limits.py @@ -21,17 +21,24 @@ class ShareLimits: # meets the criteria for ratio limit/seed limit for deletion including contents \ self.status_filter = "completed" if self.config.settings["share_limits_filter_completed"] else "all" - self.tdel_dict = {} # dictionary to track the torrent names and content path that meet the deletion criteria + # dictionary to track the torrent names and content path that meet the deletion criteria + self.tdel_dict = {} self.root_dir = qbit_manager.config.root_dir # root directory of torrents self.remote_dir = qbit_manager.config.remote_dir # remote directory of torrents - self.share_limits_config = qbit_manager.config.share_limits # configuration of share limits + # configuration of share limits + self.share_limits_config = qbit_manager.config.share_limits self.torrents_updated = [] # list of torrents that have been updated - self.torrent_hash_checked = [] # list of torrent hashes that have been checked for share limits + # list of torrent hashes that have been checked for share limits + self.torrent_hash_checked = [] self.share_limits_tag = qbit_manager.config.share_limits_tag # tag for share limits - self.share_limits_custom_tags = qbit_manager.config.share_limits_custom_tags # All possible custom share limits tags - self.min_seeding_time_tag = qbit_manager.config.share_limits_min_seeding_time_tag # tag for min seeding time - self.min_num_seeds_tag = qbit_manager.config.share_limits_min_num_seeds_tag # tag for min num seeds - self.last_active_tag = qbit_manager.config.share_limits_last_active_tag # tag for last active + # All possible custom share limits tags + self.share_limits_custom_tags = qbit_manager.config.share_limits_custom_tags + # tag for min seeding time + self.min_seeding_time_tag = qbit_manager.config.share_limits_min_seeding_time_tag + # tag for min num seeds + self.min_num_seeds_tag = qbit_manager.config.share_limits_min_num_seeds_tag + # tag for last active + self.last_active_tag = qbit_manager.config.share_limits_last_active_tag self.group_tag = None # tag for the share limit group self.update_share_limits() @@ -87,7 +94,7 @@ class ShareLimits: tracker = self.qbt.get_tags(self.qbt.get_tracker_urls(torrent.trackers)) body = [] body += logger.print_line(logger.insert_space(f"Torrent Name: {t_name}", 3), self.config.loglevel) - body += logger.print_line(logger.insert_space(f'Tracker: {tracker["url"]}', 8), self.config.loglevel) + body += logger.print_line(logger.insert_space(f"Tracker: {tracker['url']}", 8), self.config.loglevel) body += logger.print_line(torrent_dict["body"], self.config.loglevel) body += logger.print_line( logger.insert_space("Cleanup: True [Meets Share Limits]", 8), @@ -215,7 +222,8 @@ class ShareLimits: else: share_limits_not_yet_tagged = False - check_multiple_share_limits_tag = False # Default assume no multiple share limits tag + # Default assume no multiple share limits tag + check_multiple_share_limits_tag = False # Check if any of the previous share limits custom tags are there for custom_tag in self.share_limits_custom_tags: @@ -296,7 +304,7 @@ class ShareLimits: or check_multiple_share_limits_tag ): logger.print_line(logger.insert_space(f"Torrent Name: {t_name}", 3), self.config.loglevel) - logger.print_line(logger.insert_space(f'Tracker: {tracker["url"]}', 8), self.config.loglevel) + logger.print_line(logger.insert_space(f"Tracker: {tracker['url']}", 8), self.config.loglevel) if self.group_tag: logger.print_line(logger.insert_space(f"Added Tag: {self.group_tag}", 8), self.config.loglevel) self.tag_and_update_share_limits_for_torrent(torrent, group_config) diff --git a/modules/core/tag_nohardlinks.py b/modules/core/tag_nohardlinks.py index 8b05d6d..369e099 100644 --- a/modules/core/tag_nohardlinks.py +++ b/modules/core/tag_nohardlinks.py @@ -9,7 +9,8 @@ class TagNoHardLinks: self.config = qbit_manager.config self.client = qbit_manager.client self.stats_tagged = 0 # counter for the number of torrents that has no hardlinks - self.stats_untagged = 0 # counter for number of torrents that previously had no hardlinks but now have hardlinks + # counter for number of torrents that previously had no hardlinks but now have hardlinks + self.stats_untagged = 0 self.root_dir = qbit_manager.config.root_dir self.remote_dir = qbit_manager.config.remote_dir @@ -20,7 +21,8 @@ class TagNoHardLinks: self.notify_attr_tagged = [] # List of single torrent attributes to send to notifiarr self.torrents_updated_untagged = [] # List of torrents updated - self.notify_attr_untagged = [] # List of single torrent attributes to send to notifiarr + # List of single torrent attributes to send to notifiarr + self.notify_attr_untagged = [] self.status_filter = "completed" if self.config.settings["tag_nohardlinks_filter_completed"] else "all" @@ -35,7 +37,7 @@ class TagNoHardLinks: body.append(logger.insert_space(f"Torrent Name: {torrent.name}", 3)) body.append(logger.insert_space(f"Added Tag: {self.nohardlinks_tag}", 6)) title = "Tagging Torrents with No Hardlinks" - body.append(logger.insert_space(f'Tracker: {tracker["url"]}', 8)) + body.append(logger.insert_space(f"Tracker: {tracker['url']}", 8)) if not self.config.dry_run: torrent.add_tags(self.nohardlinks_tag) self.stats_tagged += 1 @@ -67,7 +69,7 @@ class TagNoHardLinks: self.config.loglevel, ) body += logger.print_line(logger.insert_space(f"Removed Tag: {self.nohardlinks_tag}", 6), self.config.loglevel) - body += logger.print_line(logger.insert_space(f'Tracker: {tracker["url"]}', 8), self.config.loglevel) + body += logger.print_line(logger.insert_space(f"Tracker: {tracker['url']}", 8), self.config.loglevel) if not self.config.dry_run: torrent.remove_tags(tags=self.nohardlinks_tag) attr = { diff --git a/modules/core/tags.py b/modules/core/tags.py index 8ddff85..5a813ab 100644 --- a/modules/core/tags.py +++ b/modules/core/tags.py @@ -9,10 +9,12 @@ class Tags: self.config = qbit_manager.config self.client = qbit_manager.client self.stats = 0 - self.share_limits_tag = qbit_manager.config.share_limits_tag # suffix tag for share limits + # suffix tag for share limits + self.share_limits_tag = qbit_manager.config.share_limits_tag self.torrents_updated = [] # List of torrents updated self.notify_attr = [] # List of single torrent attributes to send to notifiarr self.stalled_tag = "stalledDL" + self.tag_stalled_torrents = self.config.settings["tag_stalled_torrents"] self.tags() self.config.webhooks_factory.notify(self.torrents_updated, self.notify_attr, group_by="tag") @@ -24,12 +26,16 @@ class Tags: tracker = self.qbt.get_tags(self.qbt.get_tracker_urls(torrent.trackers)) # Remove stalled_tag if torrent is no longer stalled - if util.is_tag_in_torrent(self.stalled_tag, torrent.tags) and torrent.state != "stalledDL": + if ( + self.tag_stalled_torrents + and util.is_tag_in_torrent(self.stalled_tag, torrent.tags) + and torrent.state != "stalledDL" + ): t_name = torrent.name body = [] body += logger.print_line(logger.insert_space(f"Torrent Name: {t_name}", 3), self.config.loglevel) body += logger.print_line(logger.insert_space(f"Removing Tag: {self.stalled_tag}", 3), self.config.loglevel) - body += logger.print_line(logger.insert_space(f'Tracker: {tracker["url"]}', 8), self.config.loglevel) + body += logger.print_line(logger.insert_space(f"Tracker: {tracker['url']}", 8), self.config.loglevel) if not self.config.dry_run: torrent.remove_tags(self.stalled_tag) if ( @@ -38,7 +44,7 @@ class Tags: or (torrent.state == "stalledDL" and not util.is_tag_in_torrent(self.stalled_tag, torrent.tags)) ): stalled = False - if torrent.state == "stalledDL": + if self.tag_stalled_torrents and torrent.state == "stalledDL": stalled = True tracker["tag"].append(self.stalled_tag) if tracker["tag"] or stalled: @@ -47,10 +53,10 @@ class Tags: body = [] body += logger.print_line(logger.insert_space(f"Torrent Name: {t_name}", 3), self.config.loglevel) body += logger.print_line( - logger.insert_space(f'New Tag{"s" if len(tracker["tag"]) > 1 else ""}: {", ".join(tracker["tag"])}', 8), + logger.insert_space(f"New Tag{'s' if len(tracker['tag']) > 1 else ''}: {', '.join(tracker['tag'])}", 8), self.config.loglevel, ) - body += logger.print_line(logger.insert_space(f'Tracker: {tracker["url"]}', 8), self.config.loglevel) + body += logger.print_line(logger.insert_space(f"Tracker: {tracker['url']}", 8), self.config.loglevel) if not self.config.dry_run: torrent.add_tags(tracker["tag"]) category = self.qbt.get_category(torrent.save_path)[0] if torrent.category == "" else torrent.category diff --git a/modules/logs.py b/modules/logs.py index 70bc43d..f450dbd 100755 --- a/modules/logs.py +++ b/modules/logs.py @@ -85,7 +85,7 @@ class MyLogger: def _formatter(self, handler=None, border=True, log_only=False, space=False): """Format log message""" console = f"| %(message)-{self.screen_width - 2}s |" if border else f"%(message)-{self.screen_width - 2}s" - file = f"{' '*65}" if space else "[%(asctime)s] %(filename)-27s %(levelname)-10s " + file = f"{' ' * 65}" if space else "[%(asctime)s] %(filename)-27s %(levelname)-10s " handlers = [handler] if handler else self._logger.handlers for h in handlers: if not log_only or isinstance(h, RotatingFileHandler): diff --git a/modules/qbittorrent.py b/modules/qbittorrent.py index 3544510..91cd972 100755 --- a/modules/qbittorrent.py +++ b/modules/qbittorrent.py @@ -390,7 +390,7 @@ class Qbt: self.config.data["tracker"][default_tag]["tag"] = [default_tag] except Exception: self.config.data["tracker"][default_tag] = {"tag": [default_tag]} - e = f'No tags matched for {tracker["url"]}. Please check your config.yml file. Setting tag to {default_tag}' + e = f"No tags matched for {tracker['url']}. Please check your config.yml file. Setting tag to {default_tag}" self.config.notify(e, "Tag", False) logger.warning(e) return tracker @@ -448,8 +448,10 @@ class Qbt: else: recycle_path = self.config.recycle_dir # Create recycle bin if not exists - torrent_path = os.path.join(recycle_path, "torrents") # Export torrent/fastresume from BT_backup - torrent_export_path = os.path.join(recycle_path, "torrents_export") # Exported torrent file (qbittorrent v4.5.0+) + # Export torrent/fastresume from BT_backup + torrent_path = os.path.join(recycle_path, "torrents") + # Exported torrent file (qbittorrent v4.5.0+) + torrent_export_path = os.path.join(recycle_path, "torrents_export") torrents_json_path = os.path.join(recycle_path, "torrents_json") torrent_name = info["torrents"][0] torrent_exportable = self.current_version >= "v4.5.0" @@ -472,7 +474,8 @@ class Qbt: dot_torrent_files = [] # Exporting torrent via Qbit API (v4.5.0+) if torrent_exportable: - hash_suffix = f"{info_hash[-8:]}" # Get the last 8 hash characters of the torrent + # Get the last 8 hash characters of the torrent + hash_suffix = f"{info_hash[-8:]}" torrent_export_file = os.path.join(torrent_export_path, f"{torrent_name} [{hash_suffix}].torrent") truncated_torrent_export_file = util.truncate_filename(torrent_export_file, offset=11) try: diff --git a/qbit_manage.py b/qbit_manage.py index c79dbc3..c38a48d 100755 --- a/qbit_manage.py +++ b/qbit_manage.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """qBittorrent Manager.""" + import argparse import glob import math @@ -27,8 +28,8 @@ current_version = sys.version_info if current_version < (REQUIRED_VERSION): print( - "Version Error: Version: %s.%s.%s incompatible with qbit_manage please use Python %s+" - % (current_version[0], current_version[1], current_version[2], REQUIRED_VERSION_STR) + f"Version Error: Version: {current_version[0]}.{current_version[1]}.{current_version[2]} incompatible with " + f"qbit_manage please use Python {REQUIRED_VERSION_STR}+" ) sys.exit(1) @@ -450,7 +451,8 @@ def start(): end_time = datetime.now() run_time = str(end_time - start_time).split(".", maxsplit=1)[0] if run is False: - if is_valid_cron_syntax(sch): # Simple check to guess if it's a cron syntax + # Simple check to guess if it's a cron syntax + if is_valid_cron_syntax(sch): next_run_time = schedule_from_cron(sch) else: delta = timedelta(minutes=sch) @@ -652,7 +654,8 @@ if __name__ == "__main__": logger.info(run_mode_message) start_loop(True) else: - if is_valid_cron_syntax(sch): # Simple check to guess if it's a cron syntax + # Simple check to guess if it's a cron syntax + if is_valid_cron_syntax(sch): run_mode_message = f" Scheduled Mode: Running cron '{sch}'" next_run_time = schedule_from_cron(sch) next_run = calc_next_run(next_run_time) diff --git a/requirements-dev.txt b/requirements-dev.txt index e896497..f5a2604 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,2 +1,3 @@ -flake8==7.1.2 + pre-commit==4.1.0 +ruff==0.10.0 diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 0000000..7dc0d23 --- /dev/null +++ b/ruff.toml @@ -0,0 +1,22 @@ +line-length = 130 + +[lint] +select = [ + "I", # isort - import order + "UP", # pyupgrade + "T10", # debugger + "E", # pycodestyle errors + "W", # pycodestyle warnings + "F", # pyflakes +] + +ignore = [ + "E722", # E722 Do not use bare except, specify exception instead + "E402", # E402 module level import not at top of file +] + +[lint.isort] +force-single-line = true + +[format] +line-ending = "auto" diff --git a/scripts/delete_torrents_on_low_disk_space.py b/scripts/delete_torrents_on_low_disk_space.py index 3b6f875..ae55f73 100755 --- a/scripts/delete_torrents_on_low_disk_space.py +++ b/scripts/delete_torrents_on_low_disk_space.py @@ -14,16 +14,21 @@ import qbittorrentapi """===Config===""" # qBittorrent WebUi Login qbt_login = {"host": "localhost", "port": 8080, "username": "???", "password": "???"} -PATH = "M:" # Path of drive to monitor. Only torrents with paths that start with this may be deleted. +# Path of drive to monitor. Only torrents with paths that start with this may be deleted. +PATH = "M:" MIN_FREE_SPACE = 10 # In GB. Min free space on drive. MIN_FREE_USAGE = 0 # In decimal percentage, 0 to 1. Min % free space on drive. -MIN_TORRENT_SHARE_RATIO = 0 # In decimal percentage, 0 to inf. Min seeding ratio of torrent to delete. -MIN_TORRENT_AGE = 30 # In days, min age of torrent to delete. Uses seeding time. +# In decimal percentage, 0 to inf. Min seeding ratio of torrent to delete. +MIN_TORRENT_SHARE_RATIO = 0 +# In days, min age of torrent to delete. Uses seeding time. +MIN_TORRENT_AGE = 30 ALLOW_INCOMPLETE_TORRENT_DELETIONS = ( - False # Also delete torrents that haven't finished downloading. MIN_TORRENT_AGE now based on time active. + # Also delete torrents that haven't finished downloading. MIN_TORRENT_AGE now based on time active. + False ) PREFER_PRIVATE_TORRENTS = ( - True # Will delete public torrents before private ones regardless of seed difference. See is_torrent_public(). + # Will delete public torrents before private ones regardless of seed difference. See is_torrent_public(). + True ) """===End Config===""" @@ -171,7 +176,8 @@ def main(): qbt_client.torrents_delete(torrent_hashes=torrent_hash, delete_files=True) deleted_torrents.append(torrent_name) print(f"--- {torrent_name}") - time.sleep(1) # Sleep a bit after each deletion to make sure disk usage is updated. + # Sleep a bit after each deletion to make sure disk usage is updated. + time.sleep(1) # Print results print_free_space() diff --git a/scripts/edit_tracker.py b/scripts/edit_tracker.py index 63af9f0..a945a5c 100644 --- a/scripts/edit_tracker.py +++ b/scripts/edit_tracker.py @@ -9,7 +9,8 @@ qbt_host = "qbittorrent:8080" qbt_user = None qbt_pass = None OLD_TRACKER = "https://blutopia.xyz" # This is the tracker you want to replace -NEW_TRACKER = "https://blutopia.cc" # This is the tracker you want to replace it with +# This is the tracker you want to replace it with +NEW_TRACKER = "https://blutopia.cc" # --DEFINE VARIABLES--# # --START SCRIPT--# diff --git a/scripts/pre-commit/increase_version.sh b/scripts/pre-commit/increase_version.sh index 3f166ab..8319b37 100755 --- a/scripts/pre-commit/increase_version.sh +++ b/scripts/pre-commit/increase_version.sh @@ -10,6 +10,9 @@ fi if git diff --cached --name-only | grep -q "VERSION"; then echo "The VERSION file is already modified. Skipping version update." exit 0 +elif git diff --name-only | grep -q "VERSION"; then + echo "The VERSION file has unstaged changes. Please stage them before committing." + exit 0 fi # Read the current version from the VERSION file diff --git a/tox.ini b/tox.ini index aa93143..49672e7 100755 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py39,py310,py311,py312,pre-commit +envlist = py39,py310,py311,py312,py313,pre-commit skip_missing_interpreters = true tox_pip_extensions_ext_pip_custom_platform = true tox_pip_extensions_ext_venv_update = true @@ -27,13 +27,6 @@ commands = pre-commit install -f --install-hooks pre-commit run --all-files -[flake8] -max-line-length = 130 - -[pep8] -extend-ignore = E722,E402 - -[tool.isort] -add_imports = ["from __future__ import annotations"] -force_single_line = true -profile = "black" +[testenv:ruff] +deps = ruff +commands = ruff check .