Repository navigation
piece limited tracker improvements - #1121
Conversation
📝 WalkthroughWalkthroughAdds a global semaphore to serialize torrent creation, gates verbose queue prints behind Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant Upload as Upload Script
participant Tracker as Tracker Handler
participant Creator as create_torrent()
participant Sem as Semaphore
User->>Upload: Start upload
Upload->>Upload: Load/derive BASE.torrent piece_mb
Upload->>Upload: Possibly remove MTV (skip_if_rehash)
Upload->>Tracker: Invoke tracker handler (MTV/PTP/HDB)
Tracker->>Tracker: Check meta.base_torrent_piece_mb and nohash
alt Rehash required
Tracker->>Tracker: Await optional cooldown (DEFAULT.rehash_cooldown seconds)
Tracker->>Creator: Request torrent creation (torrent_filename)
Creator->>Sem: Acquire slot
Sem-->>Creator: Grant (or block until available)
Creator->>Creator: Build torrent (mkbrr or fallback)
Creator->>Sem: Release slot
Creator-->>Tracker: Return new torrent filename
Tracker->>Tracker: Call create_torrent_for_upload with torrent_filename
else No rehash
Tracker->>Tracker: Call create_torrent_for_upload (no new filename)
end
Tracker-->>User: Proceed to upload
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/trackers/HDB.py (1)
231-243: Fix double torrent creation and add defensive guard for missingbase_torrent_piece_mb.The
create_torrent_for_upload()call at line 212 is executed unconditionally, but if the piece size check at line 232 triggers a rehash, it's called again at line 242—wasting work on the first call.More critically,
meta['base_torrent_piece_mb']is accessed directly at line 232 without a fallback. Inupload.pylines 920–929, this key is only set if theTorrent.read()succeeds; if it fails silently (exception caught), the key remains absent inmeta, causing aKeyErrorwhenHDB.upload()runs. Usemeta.get('base_torrent_piece_mb', 0)to handle this safely.Suggested fix
- await common.create_torrent_for_upload(meta, self.tracker, self.source_flag) + # Decide whether to rehash before doing torrent creation work + base_piece_mb = meta.get('base_torrent_piece_mb', 0) + + if base_piece_mb > 16 and not meta.get('nohash', False): + console.print("[red]Piece size is OVER 16M and does not work on HDB. Generating a new .torrent") + hdb_config = self.config['TRACKERS'].get('HDB', {}) + tracker_url = hdb_config.get('announce_url', "https://fake.tracker").strip() if isinstance(hdb_config, dict) else "https://fake.tracker" + torrent_create = f"[{self.tracker}]" + if self.config.get('DEFAULT', {}).get('rehash_cooldown', False): + await asyncio.sleep(6) + await create_torrent(meta, str(meta['path']), torrent_create, tracker_url=tracker_url, piece_size=16) + await common.create_torrent_for_upload(meta, self.tracker, self.source_flag, torrent_filename=torrent_create) + else: + await common.create_torrent_for_upload(meta, self.tracker, self.source_flag)
🤖 Fix all issues with AI agents
In @src/torrentcreate.py:
- Around line 322-324: In the except Exception as e block handling mkbrr errors
(the "except Exception as e" handler), replace the incorrect "raise sys.exit(1)"
with a proper exit or exception chaining: either call "sys.exit(1)" directly, or
raise a SystemExit that chains the original exception (e.g., raise SystemExit(1)
from e) so the traceback preserves context; ensure the console.print line
remains and remove the "raise" before sys.exit.
🧹 Nitpick comments (4)
src/queuemanage.py (1)
412-423: Consider printing counts always, and keep per-path listing debug-only.Right now, in non-debug runs you print “Queue changes detected” but hide even the counts; showing counts without listing paths is still low-noise and helps explain why the prompt appears.
Proposed tweak
if new_files: - if meta.get('debug'): - console.print(f"[green]New files found ({len(new_files)}):[/green]") - for file in sorted(new_files): - console.print(f" + {file}") + console.print(f"[green]New files found ({len(new_files)}).[/green]") + if meta.get('debug'): + for file in sorted(new_files): + console.print(f" + {file}") if removed_files: - if meta.get('debug'): - console.print(f"[red]Removed files ({len(removed_files)}):[/red]") - for file in sorted(removed_files): - console.print(f" - {file}") + console.print(f"[red]Removed files ({len(removed_files)}).[/red]") + if meta.get('debug'): + for file in sorted(removed_files): + console.print(f" - {file}")src/trackers/MTV.py (1)
70-92: Ifskip_if_rehashis enabled, return beforecreate_torrent_for_upload().Currently the skip decision happens after Line 73, which likely defeats the purpose (avoid hashing work).
Proposed tweak (keep existing logic, but reorder)
- await common.create_torrent_for_upload(meta, self.tracker, self.source_flag) torrent_file_path = f"{meta['base_dir']}/tmp/{meta['uuid']}/[{self.tracker}].torrent" - if meta['base_torrent_piece_mb'] > 8 and not meta.get('nohash', False): + base_piece_mb = meta.get('base_torrent_piece_mb', 0) + if base_piece_mb > 8 and not meta.get('nohash', False): tracker_config = self.config['TRACKERS'].get(self.tracker, {}) if str(tracker_config.get('skip_if_rehash', 'false')).lower() == "false": console.print("[red]Piece size is OVER 8M and does not work on MTV. Generating a new .torrent") piece_size = 8 tracker_url = str(tracker_config.get('announce_url', "https://fake.tracker")).strip() torrent_create = f"[{self.tracker}]" if self.config.get('DEFAULT', {}).get('rehash_cooldown', False): await asyncio.sleep(6) # Small cooldown before rehashing await create_torrent(meta, str(meta['path']), torrent_create, tracker_url=tracker_url, piece_size=piece_size) await common.create_torrent_for_upload(meta, self.tracker, self.source_flag, torrent_filename=torrent_create) else: console.print("[red]Piece size is OVER 8M and skip_if_rehash enabled. Skipping upload.") return + else: + await common.create_torrent_for_upload(meta, self.tracker, self.source_flag)data/example-config.py (1)
307-311: Consider makingrehash_cooldowna numeric duration (seconds) instead of a boolean.All tracker implementations (MTV, PTP, HDB) currently sleep a fixed 6 seconds when enabled. Allowing users to configure custom durations (e.g.,
0,3,6,10) would provide better flexibility and avoid adding another config knob later if requirements change.src/trackers/PTP.py (1)
1511-1522: Move piece size check before firstcreate_torrent_for_upload()call to avoid regenerating twice.The torrent is created at line 1508, then immediately checked for piece size at line 1512. If size exceeds 16 MiB, the torrent is regenerated and
create_torrent_for_upload()is called again at line 1520. Sincebase_torrent_piece_mbis already available at upload time (set inupload.pybefore this method executes), the piece size should be checked first to avoid the initial wasted work.Additionally, use
meta.get('base_torrent_piece_mb')instead of direct dict access to guard against KeyError if the value is unexpectedly missing.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
data/example-config.pysrc/queuemanage.pysrc/torrentcreate.pysrc/trackers/HDB.pysrc/trackers/MTV.pysrc/trackers/PTP.pyupload.py
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 1118
File: upload.py:1181-1181
Timestamp: 2026-01-11T06:59:14.873Z
Learning: In the Upload-Assistant codebase, particularly in upload.py around line 1181, the hardcoded `successful_trackers = 10` before the optional secondary dupe check (dupe_again) is intentional design. The real threshold check happens earlier (~line 377), and this value ensures uploads proceed when no secondary check is performed. It gets overwritten when dupe_again is True.
Learnt from: Lusephur
Repo: Audionut/Upload-Assistant PR: 1023
File: src/trackers/TVC.py:484-487
Timestamp: 2025-11-23T15:26:45.408Z
Learning: In the Upload-Assistant codebase, particularly for src/trackers/TVC.py, do not mark error handling suggestions as critical severity when the code has been tested and is working successfully across multiple scenarios. The user (Lusephur) has thoroughly tested TVC uploads including TV episodes, TV packs, foreign content, and movies.
📚 Learning: 2025-12-27T13:04:22.071Z
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 1081
File: src/trackers/CBR.py:94-94
Timestamp: 2025-12-27T13:04:22.071Z
Learning: In Python codebases where a dict (e.g., meta) is guaranteed to always include a specific key (e.g., 'tag'), direct dictionary access meta['tag'] is safe and preferred over meta.get('tag') for performance and readability. Ensure the key is indeed always initialized in all code paths; if there's any doubt, consider defensive checks or documentation to avoid KeyError.
Applied to files:
data/example-config.pyupload.pysrc/trackers/PTP.pysrc/queuemanage.pysrc/torrentcreate.pysrc/trackers/HDB.pysrc/trackers/MTV.py
📚 Learning: 2026-01-11T05:07:09.469Z
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 1114
File: src/manualpackage.py:16-23
Timestamp: 2026-01-11T05:07:09.469Z
Learning: In Python type hints for read-only mappings (e.g., DEFAULT_CONFIG, TRACKER_CONFIG), prefer Mapping[str, Any] over Dict[str, Any] to signal immutability intent. Use from typing import Mapping; annotate with Mapping[str, Any] while allowing concrete dicts at runtime. Do not rely on isinstance(value, dict) for immutability checks; this is a type-hint convention, not a runtime guarantee.
Applied to files:
data/example-config.pyupload.pysrc/trackers/PTP.pysrc/queuemanage.pysrc/torrentcreate.pysrc/trackers/HDB.pysrc/trackers/MTV.py
📚 Learning: 2026-01-11T05:07:09.469Z
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 1114
File: src/manualpackage.py:16-23
Timestamp: 2026-01-11T05:07:09.469Z
Learning: In the Upload-Assistant repository, avoid flagging minor or stylistic issues (e.g., ValueError vs TypeError for type validation) unless they represent actual bugs or significant problems. Follow Audionut's preference to focus on substantive issues rather than minor concerns across Python files.
Applied to files:
data/example-config.pyupload.pysrc/trackers/PTP.pysrc/queuemanage.pysrc/torrentcreate.pysrc/trackers/HDB.pysrc/trackers/MTV.py
📚 Learning: 2025-11-23T15:26:45.408Z
Learnt from: Lusephur
Repo: Audionut/Upload-Assistant PR: 1023
File: src/trackers/TVC.py:484-487
Timestamp: 2025-11-23T15:26:45.408Z
Learning: In the Upload-Assistant codebase, particularly for src/trackers/TVC.py, do not mark error handling suggestions as critical severity when the code has been tested and is working successfully across multiple scenarios. The user (Lusephur) has thoroughly tested TVC uploads including TV episodes, TV packs, foreign content, and movies.
Applied to files:
upload.py
📚 Learning: 2025-12-14T00:20:21.219Z
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 1025
File: src/trackers/TVC.py:32-86
Timestamp: 2025-12-14T00:20:21.219Z
Learning: In src/trackers/TVC.py, the genres argument passed to get_cat_id() is a string (comma-separated) rather than a list or other type. Remove or avoid code paths that handle list inputs for this parameter; assume and validate string input, adjust type hints if present, and, if possible, add a unit test to ensure a string is passed.
Applied to files:
src/trackers/PTP.pysrc/queuemanage.pysrc/torrentcreate.pysrc/trackers/HDB.pysrc/trackers/MTV.py
📚 Learning: 2025-12-27T13:04:08.659Z
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 1081
File: src/trackers/CBR.py:84-91
Timestamp: 2025-12-27T13:04:08.659Z
Learning: In tracker modules under src/trackers, meta['aka'] is a guaranteed key and can be accessed directly (meta['aka']) without using get(). This improves clarity and small performance overhead. Only rely on this when you are certain the key is always present; if a tracker could ever omit it, add a guard or a clear default to avoid KeyError.
Applied to files:
src/trackers/PTP.pysrc/trackers/HDB.pysrc/trackers/MTV.py
🧬 Code graph analysis (5)
upload.py (1)
src/torrentcreate.py (2)
piece_size(103-104)piece_size(107-112)
src/trackers/PTP.py (1)
src/torrentcreate.py (2)
piece_size(103-104)piece_size(107-112)
src/torrentcreate.py (3)
upload.py (1)
get_mkbrr_path(1707-1713)web_ui/static/js/app.js (1)
root(672-672)web_ui/server.py (1)
generate(344-452)
src/trackers/HDB.py (1)
src/torrentcreate.py (2)
piece_size(103-104)piece_size(107-112)
src/trackers/MTV.py (1)
src/torrentcreate.py (2)
piece_size(103-104)piece_size(107-112)
🪛 Ruff (0.14.10)
upload.py
178-178: Unused noqa directive (non-enabled: E402)
Remove unused noqa directive
(RUF100)
925-925: Do not catch blind exception: Exception
(BLE001)
src/torrentcreate.py
214-214: Abstract raise to an inner function
(TRY301)
214-214: Avoid specifying long messages outside the exception class
(TRY003)
218-218: Abstract raise to an inner function
(TRY301)
218-218: Avoid specifying long messages outside the exception class
(TRY003)
263-263: subprocess call: check for execution of untrusted input
(S603)
310-310: Abstract raise to an inner function
(TRY301)
310-310: Avoid specifying long messages outside the exception class
(TRY003)
314-314: Abstract raise to an inner function
(TRY301)
314-314: Avoid specifying long messages outside the exception class
(TRY003)
322-322: Do not catch blind exception: Exception
(BLE001)
323-323: Use explicit conversion flag
Replace with conversion flag
(RUF010)
324-324: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
334-334: Loop control variable dirs not used within loop body
Rename unused dirs to _dirs
(B007)
360-360: Probable insecure usage of temporary file or directory: "/tmp/"
(S108)
368-368: Probable insecure usage of temporary file or directory: "/tmp/"
(S108)
🔇 Additional comments (6)
upload.py (2)
178-178: LGTM - Import placement is intentional.The
noqa: E402directive is appropriate here since all imports below line 133 are intentionally placed after config validation to allow early exit on config errors.
914-942: LGTM - Well-structured early MTV exclusion logic.The implementation correctly:
- Uses
asyncio.to_threadfor the blockingTorrent.readcall- Caches piece size only when needed (HDB/MTV/PTP in tracker list)
- Gracefully handles exceptions by falling back to
None- Properly removes MTV and handles the edge case of no remaining trackers
The string-to-bool check on line 932 (
str(...).lower() == 'true') is defensive and handles various config value formats.src/torrentcreate.py (4)
21-24: LGTM - Appropriate concurrency control for torrent hashing.The semaphore with limit 1 effectively serializes torrent creation, preventing resource saturation from concurrent hashing operations as described in the PR objectives. The in-flight counter provides useful debugging visibility.
146-163: Well-implemented semaphore acquisition with diagnostics.The pattern correctly:
- Optionally tracks wait time when the semaphore is already locked
- Acquires the semaphore before incrementing the in-flight counter
- Provides debug visibility into wait times and concurrent state
375-379: Correct cleanup pattern in finally block.The finally block properly ensures the semaphore is released and the in-flight counter decremented regardless of success or failure, preventing resource leaks.
262-304: Subprocess handling is appropriately secured.The subprocess call (flagged by S603) is acceptable here because:
pathis validated to exist on line 213-214mkbrr_binaryis validated on lines 217-218- Command is constructed as a list (not shell string), preventing injection
The
asyncio.to_thread(run_mkbrr)pattern correctly offloads the blocking subprocess to a thread pool.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (4)
src/torrentcreate.py (3)
149-163: Consider using async context manager for cleaner semaphore handling.The current acquire/release pattern works correctly with the try/finally block. For slightly cleaner code, you could use
async with _CREATE_TORRENT_SEMAPHORE:which handles acquire/release automatically.However, the current approach is valid and allows for the wait-time tracking logic before acquisition, so this is more of a stylistic observation than a required change.
182-185: Remove no-op assignment.Line 183
path = pathis a no-op that doesn't modify anything. This appears to be leftover from previous code that may have modified the path for disc cases.♻️ Suggested fix
else: if meta.get('is_disc', False): - path = path include = [] exclude = []
237-240: Remove redundantimport mathstatement.The
mathmodule is already imported at the module level (line 7). This inner import is unnecessary and adds minor overhead.♻️ Suggested fix
try: max_size_bytes = int(piece_size) * 1024 * 1024 # Calculate the appropriate power of 2 (log2) # We want the largest power of 2 that's less than or equal to max_size_bytes - import math power = min(27, max(16, math.floor(math.log2(max_size_bytes))))src/trackers/HDB.py (1)
239-240: Hardcoded cooldown value across trackers.The 6-second cooldown is hardcoded identically in PTP.py, MTV.py, and HDB.py. While this works, consider defining it as a constant (e.g.,
REHASH_COOLDOWN_SECONDS = 6) or making it configurable alongsiderehash_cooldownto allow users to tune it based on their system's capabilities.This is a minor suggestion for maintainability rather than a required change.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/torrentcreate.pysrc/trackers/HDB.pysrc/trackers/MTV.pysrc/trackers/PTP.py
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 1118
File: upload.py:1181-1181
Timestamp: 2026-01-11T06:59:14.873Z
Learning: In the Upload-Assistant codebase, particularly in upload.py around line 1181, the hardcoded `successful_trackers = 10` before the optional secondary dupe check (dupe_again) is intentional design. The real threshold check happens earlier (~line 377), and this value ensures uploads proceed when no secondary check is performed. It gets overwritten when dupe_again is True.
Learnt from: Lusephur
Repo: Audionut/Upload-Assistant PR: 1023
File: src/trackers/TVC.py:484-487
Timestamp: 2025-11-23T15:26:45.408Z
Learning: In the Upload-Assistant codebase, particularly for src/trackers/TVC.py, do not mark error handling suggestions as critical severity when the code has been tested and is working successfully across multiple scenarios. The user (Lusephur) has thoroughly tested TVC uploads including TV episodes, TV packs, foreign content, and movies.
📚 Learning: 2025-12-14T00:20:21.219Z
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 1025
File: src/trackers/TVC.py:32-86
Timestamp: 2025-12-14T00:20:21.219Z
Learning: In src/trackers/TVC.py, the genres argument passed to get_cat_id() is a string (comma-separated) rather than a list or other type. Remove or avoid code paths that handle list inputs for this parameter; assume and validate string input, adjust type hints if present, and, if possible, add a unit test to ensure a string is passed.
Applied to files:
src/trackers/MTV.pysrc/trackers/HDB.pysrc/trackers/PTP.pysrc/torrentcreate.py
📚 Learning: 2025-12-27T13:04:08.659Z
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 1081
File: src/trackers/CBR.py:84-91
Timestamp: 2025-12-27T13:04:08.659Z
Learning: In tracker modules under src/trackers, meta['aka'] is a guaranteed key and can be accessed directly (meta['aka']) without using get(). This improves clarity and small performance overhead. Only rely on this when you are certain the key is always present; if a tracker could ever omit it, add a guard or a clear default to avoid KeyError.
Applied to files:
src/trackers/MTV.pysrc/trackers/HDB.pysrc/trackers/PTP.py
📚 Learning: 2025-12-27T13:04:22.071Z
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 1081
File: src/trackers/CBR.py:94-94
Timestamp: 2025-12-27T13:04:22.071Z
Learning: In Python codebases where a dict (e.g., meta) is guaranteed to always include a specific key (e.g., 'tag'), direct dictionary access meta['tag'] is safe and preferred over meta.get('tag') for performance and readability. Ensure the key is indeed always initialized in all code paths; if there's any doubt, consider defensive checks or documentation to avoid KeyError.
Applied to files:
src/trackers/MTV.pysrc/trackers/HDB.pysrc/trackers/PTP.pysrc/torrentcreate.py
📚 Learning: 2026-01-11T05:07:09.469Z
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 1114
File: src/manualpackage.py:16-23
Timestamp: 2026-01-11T05:07:09.469Z
Learning: In Python type hints for read-only mappings (e.g., DEFAULT_CONFIG, TRACKER_CONFIG), prefer Mapping[str, Any] over Dict[str, Any] to signal immutability intent. Use from typing import Mapping; annotate with Mapping[str, Any] while allowing concrete dicts at runtime. Do not rely on isinstance(value, dict) for immutability checks; this is a type-hint convention, not a runtime guarantee.
Applied to files:
src/trackers/MTV.pysrc/trackers/HDB.pysrc/trackers/PTP.pysrc/torrentcreate.py
📚 Learning: 2026-01-11T05:07:09.469Z
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 1114
File: src/manualpackage.py:16-23
Timestamp: 2026-01-11T05:07:09.469Z
Learning: In the Upload-Assistant repository, avoid flagging minor or stylistic issues (e.g., ValueError vs TypeError for type validation) unless they represent actual bugs or significant problems. Follow Audionut's preference to focus on substantive issues rather than minor concerns across Python files.
Applied to files:
src/trackers/MTV.pysrc/trackers/HDB.pysrc/trackers/PTP.pysrc/torrentcreate.py
🧬 Code graph analysis (3)
src/trackers/MTV.py (2)
src/torrentcreate.py (3)
piece_size(103-104)piece_size(107-112)create_torrent(139-379)src/trackers/COMMON.py (1)
create_torrent_for_upload(49-81)
src/trackers/HDB.py (2)
src/torrentcreate.py (3)
piece_size(103-104)piece_size(107-112)create_torrent(139-379)src/trackers/COMMON.py (1)
create_torrent_for_upload(49-81)
src/torrentcreate.py (1)
upload.py (1)
get_mkbrr_path(1707-1713)
🪛 Ruff (0.14.10)
src/trackers/MTV.py
74-74: Probable insecure usage of temporary file or directory: "/tmp/"
(S108)
src/trackers/HDB.py
230-230: Probable insecure usage of temporary file or directory: "/tmp/"
(S108)
src/trackers/PTP.py
1509-1509: Probable insecure usage of temporary file or directory: "/tmp/"
(S108)
src/torrentcreate.py
214-214: Abstract raise to an inner function
(TRY301)
214-214: Avoid specifying long messages outside the exception class
(TRY003)
218-218: Abstract raise to an inner function
(TRY301)
218-218: Avoid specifying long messages outside the exception class
(TRY003)
263-263: subprocess call: check for execution of untrusted input
(S603)
310-310: Abstract raise to an inner function
(TRY301)
310-310: Avoid specifying long messages outside the exception class
(TRY003)
314-314: Abstract raise to an inner function
(TRY301)
314-314: Avoid specifying long messages outside the exception class
(TRY003)
323-323: Use explicit conversion flag
Replace with conversion flag
(RUF010)
334-334: Loop control variable dirs not used within loop body
Rename unused dirs to _dirs
(B007)
360-360: Probable insecure usage of temporary file or directory: "/tmp/"
(S108)
368-368: Probable insecure usage of temporary file or directory: "/tmp/"
(S108)
🔇 Additional comments (5)
src/trackers/PTP.py (1)
1508-1523: LGTM - Metadata-driven torrent regeneration logic.The transition from
Torrent.read-based inspection to metadata-driven checks usingbase_torrent_piece_mbis clean and consistent with the patterns in HDB.py and MTV.py. The 16 MiB threshold is appropriate for PTP's requirements.One minor observation: the cooldown sleep (6 seconds) is hardcoded. If this value needs tuning in the future, consider extracting it to a config option or constant for easier maintenance across all trackers.
src/torrentcreate.py (2)
21-24: Concurrency control with semaphore looks correct.The semaphore approach effectively serializes torrent creation to prevent resource saturation. The
_create_torrent_inflightcounter provides useful visibility for debugging.Note: Since the semaphore ensures only one execution at a time, the counter modifications are safe without additional locking in this specific pattern.
375-379: LGTM - Proper cleanup in finally block.The finally block correctly releases the semaphore and decrements the in-flight counter, ensuring proper cleanup regardless of how the function exits.
src/trackers/MTV.py (1)
70-93: LGTM - MTV tracker piece size handling.The implementation correctly handles MTV's 8 MiB piece size limit (lower than PTP/HDB's 16 MiB). The
skip_if_rehashcheck is properly preserved, and the conditional branching for rehash cooldown and torrent creation is consistent with the patterns in other tracker files.src/trackers/HDB.py (1)
228-245: LGTM - HDB tracker piece size handling.The implementation mirrors PTP.py with the appropriate 16 MiB threshold. The metadata-driven approach and conditional torrent regeneration logic are correctly implemented.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
src/trackers/HDB.py (1)
229-249: LGTM - Consistent metadata-driven piece size check.The implementation correctly mirrors MTV's pattern with HDB's 16MB threshold. The cooldown parsing pattern is identical across MTV, HDB, and PTP.
Note: The cooldown parsing block (lines 239-244) is duplicated across all three tracker files. This could be extracted to a shared utility function in the future, but it's acceptable for now given the straightforward logic.
src/torrentcreate.py (1)
332-332: Minor: Unused loop variabledirs.The
dirsvariable fromos.walkis not used. Consider renaming to_dirsto indicate it's intentionally unused.Optional fix
- for root, dirs, files in os.walk(path): + for root, _dirs, files in os.walk(path):
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
data/example-config.pysrc/args.pysrc/languages.pysrc/torrentcreate.pysrc/trackers/DP.pysrc/trackers/GPW.pysrc/trackers/HDB.pysrc/trackers/HUNO.pysrc/trackers/MTV.pysrc/trackers/PTP.py
🚧 Files skipped from review as they are similar to previous changes (1)
- data/example-config.py
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 1118
File: upload.py:1181-1181
Timestamp: 2026-01-11T06:59:14.873Z
Learning: In the Upload-Assistant codebase, particularly in upload.py around line 1181, the hardcoded `successful_trackers = 10` before the optional secondary dupe check (dupe_again) is intentional design. The real threshold check happens earlier (~line 377), and this value ensures uploads proceed when no secondary check is performed. It gets overwritten when dupe_again is True.
📚 Learning: 2025-12-14T00:20:21.219Z
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 1025
File: src/trackers/TVC.py:32-86
Timestamp: 2025-12-14T00:20:21.219Z
Learning: In src/trackers/TVC.py, the genres argument passed to get_cat_id() is a string (comma-separated) rather than a list or other type. Remove or avoid code paths that handle list inputs for this parameter; assume and validate string input, adjust type hints if present, and, if possible, add a unit test to ensure a string is passed.
Applied to files:
src/trackers/HUNO.pysrc/trackers/DP.pysrc/args.pysrc/trackers/PTP.pysrc/trackers/HDB.pysrc/languages.pysrc/torrentcreate.pysrc/trackers/GPW.pysrc/trackers/MTV.py
📚 Learning: 2025-12-27T13:04:08.659Z
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 1081
File: src/trackers/CBR.py:84-91
Timestamp: 2025-12-27T13:04:08.659Z
Learning: In tracker modules under src/trackers, meta['aka'] is a guaranteed key and can be accessed directly (meta['aka']) without using get(). This improves clarity and small performance overhead. Only rely on this when you are certain the key is always present; if a tracker could ever omit it, add a guard or a clear default to avoid KeyError.
Applied to files:
src/trackers/HUNO.pysrc/trackers/DP.pysrc/trackers/PTP.pysrc/trackers/HDB.pysrc/trackers/GPW.pysrc/trackers/MTV.py
📚 Learning: 2025-12-27T13:04:22.071Z
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 1081
File: src/trackers/CBR.py:94-94
Timestamp: 2025-12-27T13:04:22.071Z
Learning: In Python codebases where a dict (e.g., meta) is guaranteed to always include a specific key (e.g., 'tag'), direct dictionary access meta['tag'] is safe and preferred over meta.get('tag') for performance and readability. Ensure the key is indeed always initialized in all code paths; if there's any doubt, consider defensive checks or documentation to avoid KeyError.
Applied to files:
src/trackers/HUNO.pysrc/trackers/DP.pysrc/args.pysrc/trackers/PTP.pysrc/trackers/HDB.pysrc/languages.pysrc/torrentcreate.pysrc/trackers/GPW.pysrc/trackers/MTV.py
📚 Learning: 2026-01-11T05:07:09.469Z
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 1114
File: src/manualpackage.py:16-23
Timestamp: 2026-01-11T05:07:09.469Z
Learning: In Python type hints for read-only mappings (e.g., DEFAULT_CONFIG, TRACKER_CONFIG), prefer Mapping[str, Any] over Dict[str, Any] to signal immutability intent. Use from typing import Mapping; annotate with Mapping[str, Any] while allowing concrete dicts at runtime. Do not rely on isinstance(value, dict) for immutability checks; this is a type-hint convention, not a runtime guarantee.
Applied to files:
src/trackers/HUNO.pysrc/trackers/DP.pysrc/args.pysrc/trackers/PTP.pysrc/trackers/HDB.pysrc/languages.pysrc/torrentcreate.pysrc/trackers/GPW.pysrc/trackers/MTV.py
📚 Learning: 2026-01-11T05:07:09.469Z
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 1114
File: src/manualpackage.py:16-23
Timestamp: 2026-01-11T05:07:09.469Z
Learning: In the Upload-Assistant repository, avoid flagging minor or stylistic issues (e.g., ValueError vs TypeError for type validation) unless they represent actual bugs or significant problems. Follow Audionut's preference to focus on substantive issues rather than minor concerns across Python files.
Applied to files:
src/trackers/HUNO.pysrc/trackers/DP.pysrc/args.pysrc/trackers/PTP.pysrc/trackers/HDB.pysrc/languages.pysrc/torrentcreate.pysrc/trackers/GPW.pysrc/trackers/MTV.py
📚 Learning: 2026-01-11T06:59:14.873Z
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 1118
File: upload.py:1181-1181
Timestamp: 2026-01-11T06:59:14.873Z
Learning: In the Upload-Assistant codebase, particularly in upload.py around line 1181, the hardcoded `successful_trackers = 10` before the optional secondary dupe check (dupe_again) is intentional design. The real threshold check happens earlier (~line 377), and this value ensures uploads proceed when no secondary check is performed. It gets overwritten when dupe_again is True.
Applied to files:
src/trackers/DP.py
📚 Learning: 2025-11-23T15:26:45.408Z
Learnt from: Lusephur
Repo: Audionut/Upload-Assistant PR: 1023
File: src/trackers/TVC.py:484-487
Timestamp: 2025-11-23T15:26:45.408Z
Learning: In the Upload-Assistant codebase, particularly for src/trackers/TVC.py, do not mark error handling suggestions as critical severity when the code has been tested and is working successfully across multiple scenarios. The user (Lusephur) has thoroughly tested TVC uploads including TV episodes, TV packs, foreign content, and movies.
Applied to files:
src/trackers/DP.py
🧬 Code graph analysis (4)
src/trackers/PTP.py (2)
src/torrentcreate.py (3)
piece_size(103-104)piece_size(107-112)create_torrent(139-376)src/trackers/COMMON.py (1)
create_torrent_for_upload(49-81)
src/trackers/HDB.py (2)
src/torrentcreate.py (3)
piece_size(103-104)piece_size(107-112)create_torrent(139-376)src/trackers/COMMON.py (1)
create_torrent_for_upload(49-81)
src/torrentcreate.py (1)
upload.py (1)
get_mkbrr_path(1707-1713)
src/trackers/MTV.py (2)
src/torrentcreate.py (3)
piece_size(103-104)piece_size(107-112)create_torrent(139-376)src/trackers/COMMON.py (1)
create_torrent_for_upload(49-81)
🪛 Ruff (0.14.10)
src/trackers/PTP.py
1509-1509: Probable insecure usage of temporary file or directory: "/tmp/"
(S108)
src/trackers/HDB.py
230-230: Probable insecure usage of temporary file or directory: "/tmp/"
(S108)
src/torrentcreate.py
213-213: Abstract raise to an inner function
(TRY301)
213-213: Avoid specifying long messages outside the exception class
(TRY003)
217-217: Abstract raise to an inner function
(TRY301)
217-217: Avoid specifying long messages outside the exception class
(TRY003)
261-261: subprocess call: check for execution of untrusted input
(S603)
308-308: Abstract raise to an inner function
(TRY301)
308-308: Avoid specifying long messages outside the exception class
(TRY003)
312-312: Abstract raise to an inner function
(TRY301)
312-312: Avoid specifying long messages outside the exception class
(TRY003)
320-320: Do not catch blind exception: Exception
(BLE001)
321-321: Use explicit conversion flag
Replace with conversion flag
(RUF010)
332-332: Loop control variable dirs not used within loop body
Rename unused dirs to _dirs
(B007)
358-358: Probable insecure usage of temporary file or directory: "/tmp/"
(S108)
366-366: Probable insecure usage of temporary file or directory: "/tmp/"
(S108)
src/trackers/MTV.py
74-74: Probable insecure usage of temporary file or directory: "/tmp/"
(S108)
🔇 Additional comments (13)
src/trackers/DP.py (1)
61-65: Potential logic gap: unattended mode bypasses hardcoded subs restriction.Unlike other checks in this file (e.g., lines 51-54 for FGT encodes, lines 56-59 for EVO), this check only returns
Falsewhennot meta['unattended']. In unattended mode withhardcoded_subs=True, the function continues and returnsshould_continue(True), effectively allowing the upload.If this is intentional (to allow unattended uploads with hardcoded subs), consider adding a comment explaining the rationale. Otherwise, align with the pattern used elsewhere:
Suggested fix if hardcoded subs should always be blocked
if meta.get('hardcoded_subs', False): if not meta['unattended']: console.print(f"[bold red]{self.tracker} does not allow hardcoded subtitles.") - return False + return Falsesrc/trackers/HUNO.py (1)
187-190: LGTM!The metadata key rename from
hardcoded-substohardcoded_subsis consistent with the argument parser change insrc/args.pyand aligns with Python identifier conventions.src/trackers/GPW.py (1)
776-778: LGTM!The metadata key rename to
hardcoded_subsis consistent with the codebase-wide standardization. The ternary logic forsubtitle_typedetermination remains correct.src/languages.py (1)
327-348: LGTM!Both occurrences of the metadata key have been consistently renamed from
hardcoded-substohardcoded_subs, aligning with the argument parser change and maintaining the existing control flow for hardcoded subtitle handling.src/args.py (1)
159-159: LGTM!Renaming the destination from
hardcoded-substohardcoded_subsfollows Python identifier conventions and ensures consistency with downstream references in tracker modules and language processing. The user-facing CLI flag--hardcoded-subsremains unchanged.src/trackers/MTV.py (2)
73-97: LGTM - Metadata-driven piece size check with rehash cooldown.The implementation correctly:
- Uses
base_torrent_piece_mbfrom metadata instead of reading the torrent file- Applies MTV's 8MB piece size limit (stricter than HDB/PTP's 16MB)
- Handles the cooldown parsing defensively with try/except
- Ensures
create_torrent_for_uploadis called in both branchesThe static analysis hint about
/tmp/(S108) is a false positive since this is an intentional application-specific temp directory path, not an insecure system temp usage.
233-234: LGTM - Debug-gated tonemapped header message.Appropriately gates the verbose "Adding tonemapped header to description" message behind
meta.debug.src/trackers/PTP.py (2)
1397-1397: LGTM - Defensive access for hardcoded_subs.Changed from direct dict access to
meta.get('hardcoded_subs')which is safer if the key might not always be present.
1508-1527: LGTM - Consistent metadata-driven piece size check for PTP.The implementation correctly:
- Uses
base_torrent_piece_mbfrom metadata with 16MB threshold (same as HDB)- Applies the same cooldown parsing pattern
- Ensures
create_torrent_for_uploadis called in both branchesThe pattern is consistent across all three trackers (MTV/HDB/PTP).
src/torrentcreate.py (4)
21-24: Good addition of serialization for torrent creation.The semaphore correctly limits concurrent torrent creation to prevent resource saturation during async uploads. The
_create_torrent_inflightcounter provides useful debug visibility.One consideration: This semaphore only serializes within a single Python process. If multiple Upload-Assistant processes run simultaneously, they would still hash in parallel. This is likely acceptable for the typical use case.
146-163: LGTM - Well-structured semaphore acquisition with observability.The implementation:
- Tracks wait time only when actually queued behind another operation
- Provides useful debug output for understanding torrent creation timing
- Correctly uses
async withfor semaphore lifecycle management
260-323: LGTM - mkbrr subprocess execution with appropriate fallback.The static analysis warnings here are acceptable:
- S603 (subprocess call): The
cmdlist is constructed from validated paths (mkbrr_binaryexistence is checked,pathexistence is validated). This is not untrusted input execution.- BLE001 (broad exception): The broad
except Exceptionis intentional to ensure any mkbrr failure gracefully falls back to CustomTorrent.The subprocess is correctly wrapped in
asyncio.to_threadto avoid blocking the event loop.
373-376: LGTM - Proper cleanup in finally block.The
finallyblock ensures_create_torrent_inflightis decremented regardless of success or exception, maintaining accurate concurrency tracking.
With async uploading, if multiple trackers require rehashing, this could saturate resources as multiple torrent creation are fired at once. This PR adds function tracking, to prevent multiple torrent hashing from occurring simultaneously.
Added a config option,
rehash_cooldown, which will add a small delay to any trackers needing torrent rehashing, helping to prevent the saturation of resources from slowing other tracker uploads.Added an early check for MTV
skip_if_rehash, to remove MTV from the upload process before any tracker calls.Summary by CodeRabbit
New Features
Improvements
Chores
Behavior
✏️ Tip: You can customize this high-level summary in your review settings.