-
Notifications
You must be signed in to change notification settings - Fork 118
dynamic import of trackers for use with custom trackers. #981
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
WalkthroughClass-level boolean flags (is_http, is_api, is_other_api) were added to many tracker classes; a small unused local variable was added in TTG.download_new_torrent; trackersetup.py was refactored to dynamically discover, import, categorize, and register tracker classes at module import time. Changes
Sequence Diagram(s)sequenceDiagram
participant Setup as trackersetup.py
participant FS as FileSystem
participant Importer as importlib
participant Inspector as inspect
participant Module as ModuleObj
participant ClassObj as TrackerClass
Setup->>FS: list modules in src/trackers/
FS-->>Setup: module names
loop each module (skips excluded)
Setup->>Importer: import module
Importer-->>Setup: ModuleObj
Setup->>Inspector: inspect ModuleObj for classes
Inspector-->>Setup: ClassObj(s)
Setup->>ClassObj: read flags (is_http / is_api / is_other_api)
ClassObj-->>Setup: flag values
alt is_http == True
Setup->>Setup: register in http_trackers (map)
else is_api == True
Setup->>Setup: register in api_trackers (map)
else is_other_api == True
Setup->>Setup: register in other_api_trackers (map)
else
Setup->>Setup: register in tracker_class_map only
end
Setup->>ClassObj: optionally instantiate with config
ClassObj-->>Setup: instance (or None)
end
Note right of Setup: COMMON accessed via tracker_class_map.get('COMMON')
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🧰 Additional context used🧠 Learnings (1)📚 Learning: 2025-11-11T08:09:03.381ZApplied to files:
🔇 Additional comments (2)
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (2)
src/trackers/NBL.py (1)
32-32: LGTM: Flag added for dynamic tracker categorization.The
is_other_apiflag has been added to enable dynamic tracker discovery, consistent with the PR's objective. Consider adding a brief comment explaining the purpose of this flag for future maintainers.+ # Flag for dynamic tracker categorization in trackersetup self.is_other_api = Truesrc/trackers/FL.py (1)
29-29: LGTM - Simple flag addition for dynamic tracker categorization.The
is_httpflag is added consistently with the broader pattern across trackers to support dynamic loading.Consider adding a brief docstring or inline comment explaining the purpose of this flag for future maintainers, e.g.:
# Flag for dynamic tracker categorization (http vs api) self.is_http = True
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (30)
src/trackers/ANT.py(1 hunks)src/trackers/AR.py(1 hunks)src/trackers/ASC.py(1 hunks)src/trackers/AZ.py(1 hunks)src/trackers/BHD.py(1 hunks)src/trackers/BHDTV.py(1 hunks)src/trackers/BJS.py(1 hunks)src/trackers/BT.py(1 hunks)src/trackers/CZ.py(1 hunks)src/trackers/DC.py(1 hunks)src/trackers/FF.py(1 hunks)src/trackers/FL.py(1 hunks)src/trackers/GPW.py(1 hunks)src/trackers/HDB.py(1 hunks)src/trackers/HDS.py(1 hunks)src/trackers/HDT.py(1 hunks)src/trackers/IS.py(1 hunks)src/trackers/MTV.py(1 hunks)src/trackers/NBL.py(1 hunks)src/trackers/PHD.py(1 hunks)src/trackers/PTER.py(1 hunks)src/trackers/PTS.py(1 hunks)src/trackers/RTF.py(1 hunks)src/trackers/SN.py(1 hunks)src/trackers/SPD.py(1 hunks)src/trackers/TL.py(1 hunks)src/trackers/TTG.py(1 hunks)src/trackers/TVC.py(2 hunks)src/trackers/UNIT3D.py(1 hunks)src/trackersetup.py(3 hunks)
🔇 Additional comments (22)
src/trackers/HDT.py (1)
35-35: LGTM! Dynamic tracker categorization flag added.The addition of
self.is_http = Truecorrectly categorizes this tracker for the dynamic loading system. The flag appropriately reflects that this tracker uses HTTP with cookie-based authentication.src/trackers/BHDTV.py (1)
30-30: LGTM! API tracker flag added correctly.The
self.is_other_api = Trueflag correctly categorizes this API-based tracker for dynamic discovery.src/trackers/HDB.py (1)
32-32: LGTM! HTTP tracker flag added.The
self.is_http = Trueflag is correctly added for this HTTP-based tracker.src/trackers/IS.py (1)
28-28: LGTM! HTTP tracker categorization added.The
self.is_http = Trueflag correctly categorizes this cookie-authenticated HTTP tracker.src/trackers/AR.py (1)
36-36: LGTM! HTTP tracker flag initialized.The addition of
self.is_http = Truecorrectly identifies this as an HTTP-based tracker for dynamic loading.src/trackers/RTF.py (1)
32-32: LGTM! API tracker flag added.The
self.is_other_api = Trueflag appropriately categorizes this API-based tracker.src/trackers/PHD.py (1)
18-18: LGTM! HTTP tracker flag initialized.The
self.is_http = Trueflag correctly categorizes this HTTP-based tracker that inherits from AZTrackerBase.src/trackers/PTS.py (1)
28-28: LGTM! HTTP tracker flag added.The
self.is_http = Trueflag correctly identifies this HTTP cookie-based tracker for dynamic discovery.Consider verifying that all 28 trackers mentioned in the PR summary have been correctly categorized with the appropriate flag (
is_http,is_api, oris_other_api). You can use the following script to check for consistency:src/trackers/TTG.py (1)
31-31: LGTM: Flag added for dynamic tracker categorization.The
is_httpflag has been added to categorize this tracker as HTTP-based for dynamic discovery, aligning with the PR's objectives.src/trackers/SPD.py (1)
33-33: LGTM: Flag added for dynamic tracker categorization.The
is_other_apiflag has been added for dynamic tracker discovery, consistent with the PR pattern.src/trackers/BHD.py (1)
32-32: LGTM: Flag added for dynamic tracker categorization.The
is_apiflag has been added for dynamic tracker discovery. Note that the codebase now has three flag types (is_http,is_api,is_other_api), and the distinction betweenis_apiandis_other_apimay warrant documentation in trackersetup.py.src/trackers/CZ.py (1)
18-18: LGTM: Flag added for dynamic tracker categorization.The
is_httpflag has been added to enable dynamic tracker discovery, consistent with the PR's objectives.src/trackers/PTER.py (1)
32-32: LGTM: Flag added for dynamic tracker categorization.The
is_httpflag has been added for dynamic tracker discovery, aligning with the PR's objectives.src/trackers/ASC.py (1)
35-35: LGTM: Flag added for dynamic tracker categorization.The
is_httpflag has been added to enable dynamic tracker discovery, consistent with the PR's objectives.src/trackers/TVC.py (1)
36-36: LGTM: Flag added for dynamic tracker categorization.The
is_other_apiflag has been added for dynamic tracker discovery, consistent with the PR's objectives.src/trackers/MTV.py (1)
48-48: LGTM - Consistent flag addition.The
is_httpflag follows the same pattern as other HTTP-based trackers in this PR.src/trackers/SN.py (1)
19-19: LGTM - API tracker flag added correctly.The
is_other_apiflag appropriately categorizes this as an API-based tracker, distinct from HTTP-based trackers.src/trackers/ANT.py (1)
36-36: LGTM - API tracker categorization.The
is_other_apiflag is correctly added for this API-based tracker.src/trackers/BT.py (1)
36-36: LGTM - HTTP tracker flag added.The
is_httpflag is appropriately placed and consistent with other HTTP-based trackers.src/trackers/GPW.py (1)
47-47: LGTM - API tracker flag correctly added.The
is_other_apiflag follows the established pattern for API-based trackers.src/trackers/DC.py (1)
23-23: LGTM - API flag addition.The
is_other_apiflag is correctly set for this API-based tracker.src/trackers/AZ.py (1)
17-17: LGTM - HTTP tracker flag added consistently.The
is_httpflag is correctly added for this HTTP-based tracker. The flag is set on the instance, so there's no concern about conflicts with the parent classAZTrackerBase.
src/trackers/TVC.py
Outdated
| resolution_id = await self.get_res_id(meta['tv_pack'] if 'tv_pack' in meta else 0, meta['resolution']) | ||
| # this is a different function that common function | ||
| await self.unit3d_edit_desc(meta, self.tracker, self.signature, image_list, approved_image_hosts=approved_image_hosts) | ||
| await self.unit3d_edit_desc(meta, self.tracker, self.signature, image_list) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good fix: Removed invalid parameter from function call.
The unit3d_edit_desc function (defined at line 392) does not accept an approved_image_hosts parameter. Removing this argument fixes a bug where an invalid parameter was being passed, which would have caused a TypeError at runtime.
🤖 Prompt for AI Agents
In src/trackers/TVC.py around line 157, the call to unit3d_edit_desc was passing
an invalid approved_image_hosts parameter; update the call to match the function
signature (as defined at line 392) by removing the extraneous argument so only
the accepted parameters are passed, and scan for other invocations that might
still pass approved_image_hosts to ensure consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (2)
src/trackersetup.py (2)
28-62: Critical: Eager instantiation still crashes on unconfigured trackers.This is the same issue flagged in the previous review. Line 52 instantiates every discovered tracker at import time. Trackers like TL call
self.config['TRACKERS'][self.tracker]in__init__, which raisesKeyErrorif that tracker isn't configured. This forces users to configure every bundled tracker, which is a regression from the static mapping.The previous review suggested deriving the tracker code without instantiating (e.g., via class-level attributes like
tracker = "TL"on the class itself) or wrapping the entire discovery in logic that checks configuration first.Recommended approach: Add class-level metadata to tracker classes so you can read
tracker,is_http,is_api, andis_other_apiwithout instantiation:for mod_name in tracker_module_names: if mod_name == 'AVISTAZ_NETWORK' or mod_name == 'UNIT3D_TEMPLATE' or mod_name == 'UNIT3D': continue # Skip this module entirely full_mod_name = f'src.trackers.{mod_name}' module = importlib.import_module(full_mod_name) for name, obj in inspect.getmembers(module, inspect.isclass): if obj.__module__ == full_mod_name: - # Determine __init__ parameters excluding 'self' - sig = inspect.signature(obj.__init__) - params = sig.parameters - # Prepare args for __init__ - init_args = {} - - # Example: config variable should be defined in your scope - if 'config' in params: - init_args['config'] = config - - if 'tracker_name' in params: - # Provide a value for tracker_name, e.g., class name or tracker_code - init_args['tracker_name'] = name # or some other appropriate string - - # Instantiate with necessary args - instance = obj(**init_args) - - tracker_code = getattr(instance, 'tracker', name).upper() + # Read class-level metadata instead of instantiating + tracker_code = getattr(obj, 'tracker', name).upper() tracker_class_map[tracker_code] = obj - if getattr(instance, 'is_http', False): + if getattr(obj, 'is_http', False): http_trackers[tracker_code] = obj - elif getattr(instance, 'is_api', False): + elif getattr(obj, 'is_api', False): api_trackers[tracker_code] = obj - elif getattr(instance, 'is_other_api', False): + elif getattr(obj, 'is_other_api', False): other_api_trackers[tracker_code] = objThen update all tracker classes to define these as class attributes rather than instance attributes.
28-62: Add error handling to prevent import failures.If any tracker module has a syntax error, import error, or if the instantiation fails for any reason, the entire
trackersetupmodule import fails, breaking the application. Wrap the loop body in try/except to skip problematic trackers gracefully.for mod_name in tracker_module_names: if mod_name == 'AVISTAZ_NETWORK' or mod_name == 'UNIT3D_TEMPLATE' or mod_name == 'UNIT3D': continue # Skip this module entirely + try: full_mod_name = f'src.trackers.{mod_name}' module = importlib.import_module(full_mod_name) for name, obj in inspect.getmembers(module, inspect.isclass): if obj.__module__ == full_mod_name: # ... existing instantiation code ... tracker_class_map[tracker_code] = obj # ... existing categorization code ... + except Exception as e: + console.print(f"[yellow]Warning: Failed to load tracker module '{mod_name}': {e}[/yellow]") + continue
🧹 Nitpick comments (1)
src/trackersetup.py (1)
29-30: Replace hardcoded exclusions with a more maintainable approach.Hardcoding module names to skip is brittle and requires code changes when new templates are added. Consider using a naming convention (e.g., modules ending in
_TEMPLATE) or a module-level flag (e.g.,__tracker_template__ = True).Option 1: Use naming convention:
- if mod_name == 'AVISTAZ_NETWORK' or mod_name == 'UNIT3D_TEMPLATE' or mod_name == 'UNIT3D': - continue # Skip this module entirely + if mod_name.endswith('_TEMPLATE') or mod_name.endswith('_NETWORK') or mod_name == 'UNIT3D': + continue # Skip templates and base classesOption 2: Check for a module-level flag after import:
full_mod_name = f'src.trackers.{mod_name}' module = importlib.import_module(full_mod_name) + + if getattr(module, '__skip_discovery__', False): + continue
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/trackers/TVC.py(1 hunks)src/trackersetup.py(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/trackers/TVC.py
🔇 Additional comments (1)
src/trackersetup.py (1)
227-227: Confirm if SPD removal from banned group checks was intentional.SPD has a complete banned group infrastructure (
banned_urlandbanned_groupsattributes) matching AITHER and LST. The removal at line 227 prevents SPD from performing banned group validation, which appears to be an unintended regression unless this was a deliberate change. Please clarify whether this removal should be reverted.
src/trackersetup.py
Outdated
| tracker_dir = os.path.join(os.path.dirname(__file__), 'trackers') | ||
| tracker_module_names = [ | ||
| f[:-3] for f in os.listdir(tracker_dir) | ||
| if f.endswith('.py') and f != '__init__.py' | ||
| ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add validation that the tracker directory exists.
If the directory structure is malformed or tracker_dir doesn't exist, os.listdir will raise a FileNotFoundError at import time with an unclear error message.
Consider adding a check:
tracker_dir = os.path.join(os.path.dirname(__file__), 'trackers')
+if not os.path.isdir(tracker_dir):
+ raise RuntimeError(f"Tracker directory not found: {tracker_dir}")
tracker_module_names = [
f[:-3] for f in os.listdir(tracker_dir)
if f.endswith('.py') and f != '__init__.py'
]📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| tracker_dir = os.path.join(os.path.dirname(__file__), 'trackers') | |
| tracker_module_names = [ | |
| f[:-3] for f in os.listdir(tracker_dir) | |
| if f.endswith('.py') and f != '__init__.py' | |
| ] | |
| tracker_dir = os.path.join(os.path.dirname(__file__), 'trackers') | |
| if not os.path.isdir(tracker_dir): | |
| raise RuntimeError(f"Tracker directory not found: {tracker_dir}") | |
| tracker_module_names = [ | |
| f[:-3] for f in os.listdir(tracker_dir) | |
| if f.endswith('.py') and f != '__init__.py' | |
| ] |
🤖 Prompt for AI Agents
In src/trackersetup.py around lines 17 to 21, add validation that tracker_dir
exists before calling os.listdir; if not, raise a clear, early error (e.g.,
RuntimeError or FileNotFoundError with a descriptive message stating the
expected trackers directory path and suggesting how to fix the project layout)
so import-time failures are explicit and actionable, then proceed to build
tracker_module_names as before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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/trackersetup.py (1)
79-80: Add None check before instantiating tracker.If
tracker.upper()is not intracker_class_map, line 80 will raiseTypeError: 'NoneType' object is not callablewith an unclear error message.Apply this diff:
tracker_class = tracker_class_map.get(tracker.upper()) + if not tracker_class: + console.print(f"[red]Tracker '{tracker}' not found in tracker_class_map[/red]") + return None tracker_instance = tracker_class(self.config)
♻️ Duplicate comments (1)
src/trackersetup.py (1)
17-21: Add validation that the tracker directory exists.If
tracker_dirdoesn't exist,os.listdirwill raise an unclearFileNotFoundErrorat import time. This past review comment remains unaddressed.Apply this diff:
tracker_dir = os.path.join(os.path.dirname(__file__), 'trackers') +if not os.path.isdir(tracker_dir): + raise RuntimeError(f"Tracker directory not found: {tracker_dir}") tracker_module_names = [ f[:-3] for f in os.listdir(tracker_dir) if f.endswith('.py') and f != '__init__.py' ]
🧹 Nitpick comments (1)
src/trackers/AZ.py (1)
20-20: Remove redundant instance attribute assignment.The class-level
is_http = True(line 8) is sufficient for the dynamic loader intrackersetup.py, which usesgetattr(obj, 'is_http', False)on the class itself. Settingself.is_http = Truehere is redundant.Apply this diff:
self.base_url = 'https://avistaz.to' self.torrent_url = f'{self.base_url}/torrent/' self.requests_url = f'{self.base_url}/requests' - self.is_http = True
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (30)
src/trackers/ANT.py(1 hunks)src/trackers/AR.py(1 hunks)src/trackers/ASC.py(1 hunks)src/trackers/AZ.py(2 hunks)src/trackers/BHD.py(1 hunks)src/trackers/BHDTV.py(1 hunks)src/trackers/BJS.py(1 hunks)src/trackers/BT.py(1 hunks)src/trackers/CZ.py(1 hunks)src/trackers/DC.py(1 hunks)src/trackers/FF.py(1 hunks)src/trackers/FL.py(1 hunks)src/trackers/GPW.py(1 hunks)src/trackers/HDB.py(1 hunks)src/trackers/HDS.py(1 hunks)src/trackers/HDT.py(1 hunks)src/trackers/IS.py(1 hunks)src/trackers/MTV.py(1 hunks)src/trackers/NBL.py(1 hunks)src/trackers/PHD.py(1 hunks)src/trackers/PTER.py(1 hunks)src/trackers/PTS.py(1 hunks)src/trackers/RTF.py(1 hunks)src/trackers/SN.py(1 hunks)src/trackers/SPD.py(1 hunks)src/trackers/TL.py(1 hunks)src/trackers/TTG.py(1 hunks)src/trackers/TVC.py(1 hunks)src/trackers/UNIT3D.py(1 hunks)src/trackersetup.py(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (17)
- src/trackers/TL.py
- src/trackers/TTG.py
- src/trackers/DC.py
- src/trackers/PTER.py
- src/trackers/GPW.py
- src/trackers/RTF.py
- src/trackers/FL.py
- src/trackers/ANT.py
- src/trackers/TVC.py
- src/trackers/ASC.py
- src/trackers/BJS.py
- src/trackers/BHD.py
- src/trackers/BT.py
- src/trackers/IS.py
- src/trackers/CZ.py
- src/trackers/BHDTV.py
- src/trackers/FF.py
🔇 Additional comments (15)
src/trackers/HDB.py (1)
23-24: LGTM! Class-level flag addition looks good.The
is_http = Trueattribute correctly marks this tracker as HTTP-based for dynamic discovery. This is a clean, minimal change that enables the dynamic tracker loading mechanism described in the PR objectives.Since the dynamic discovery mechanism in
src/trackersetup.pyisn't included in this review, please verify that:
- The tracker is correctly categorized as an HTTP tracker during runtime discovery
- All existing HDB functionality continues to work with the new dynamic loading system
You can verify this by testing uploads/searches with HDB after the changes, as mentioned in the PR description.
src/trackers/HDT.py (1)
17-19: LGTM! Consistent with the dynamic tracker pattern.The
is_http = Trueclass attribute correctly identifies HDT as an HTTP-based tracker for the dynamic discovery system.src/trackers/SN.py (1)
11-13: LGTM! API tracker classification looks correct.The
is_other_api = Trueattribute appropriately marks Swarmazon (SN) as using an alternative API pathway rather than standard HTTP cookie-based authentication. This aligns with the tracker's API-based upload mechanism visible in theuploadmethod (line 106 uses the API endpoint).src/trackers/HDS.py (1)
15-17: LGTM! HTTP tracker flag added correctly.The
is_http = Trueclass attribute properly categorizes HD-Space as an HTTP-based tracker for dynamic discovery.src/trackers/AR.py (1)
20-22: LGTM! AlphaRatio correctly flagged as HTTP tracker.The
is_http = Trueattribute is properly placed and aligns with AR's cookie-based authentication mechanism.src/trackers/MTV.py (1)
23-24: LGTM! MTV properly categorized as HTTP tracker.The
is_http = Trueclass attribute correctly identifies MoreThanTV as an HTTP-based tracker for the dynamic loading system.src/trackers/PTS.py (1)
14-16: LGTM! PTSKIT correctly marked as HTTP tracker.The
is_http = Trueclass attribute appropriately categorizes PTSKIT as an HTTP-based tracker.src/trackers/SPD.py (1)
18-20: LGTM! API-based tracker classification is appropriate.The
is_other_api = Trueattribute correctly identifies SpeedApp (SPD) as using an API-based authentication and upload mechanism (visible in the API key usage at line 34 and API endpoint at line 27), distinguishing it from cookie-based HTTP trackers.src/trackers/PHD.py (1)
8-9: LGTM! Class-level flag properly declares HTTP-based tracker.The
is_httpflag correctly marks this tracker for HTTP-based access, enabling the dynamic categorization intrackersetup.py.src/trackers/AZ.py (1)
7-8: LGTM! Class-level flag properly added.The
is_httpclass attribute correctly marks this tracker as HTTP-based for dynamic categorization.src/trackers/NBL.py (1)
11-12: LGTM! Class-level flag properly declares alternative API usage.The
is_other_apiflag correctly marks this tracker as using a non-standard API flow, enabling proper categorization in the dynamic loader.src/trackers/UNIT3D.py (1)
15-16: LGTM! Class-level flag properly declares API-based tracker.The
is_apiflag correctly marks this tracker as API-based, enabling proper categorization during dynamic discovery.src/trackersetup.py (3)
23-26: LGTM! Proper initialization of categorization dictionaries.The four dictionaries are correctly initialized to hold the dynamically discovered tracker classes.
210-210: Verify removal of SPD from banned group check.SPD was removed from the list of trackers that fetch banned groups via API. Ensure this is intentional and that SPD either no longer requires this check or handles banned groups differently.
28-45: The original review comment is incorrect and misrepresents the categorization behavior.The categorization logic works correctly through Python's attribute inheritance. When
getattr(obj, 'is_api', False)is called on tracker classes likeAITHER, it finds the inheritedis_api = Truefrom theUNIT3Dbase class. All UNIT3D subclasses (ACM, AITHER, AL, BLU, etc.) will be properly categorized as API trackers via this inheritance.The initial observation about trackers "without" flags being uncategorized is misleading because the script only looks for flags defined directly in each file, not inherited attributes. Most flagged trackers actually inherit their categorization from their parent class.
COMMON is correctly uncategorized as it's a utility helper class, not a tracker implementation. AVISTAZ_NETWORK is skipped entirely by the import loop (line 29), so it's not added to any maps.
The only potential concern is that PTP and THR are independent tracker implementations with no flags and no parent base class—but whether this is intentional requires clarification from the developer.
Likely an incorrect or invalid review comment.
|
|
||
| # Initialize request log for this tracker | ||
| common = COMMON(config) | ||
| common = tracker_class_map.get('COMMON')(config) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add None check before instantiating COMMON.
If COMMON is not in tracker_class_map (e.g., due to discovery failure), this line will raise TypeError: 'NoneType' object is not callable.
Apply this diff:
- common = tracker_class_map.get('COMMON')(config)
+ common_class = tracker_class_map.get('COMMON')
+ if not common_class:
+ console.print("[red]COMMON tracker class not found in tracker_class_map[/red]")
+ return False
+ common = common_class(config)
log_path = f"{meta['base_dir']}/tmp/{tracker}_request_results.json"Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/trackersetup.py around line 626, the code directly calls
tracker_class_map.get('COMMON')(config) which will raise TypeError if 'COMMON'
is missing; first assign the result of tracker_class_map.get('COMMON') to a
local (e.g., common_cls), check if common_cls is None and handle it (raise a
clear ValueError or log and exit/return), otherwise instantiate with
common_cls(config); ensure the error message explains that COMMON was not
discovered and includes context (config or available keys) to aid debugging.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/trackers/AZ.py (1)
18-18: Remove redundant instance attribute.The
is_httpattribute is set both as an instance attribute in__init__(Line 18) and as a class attribute (Line 181). This duplication is unnecessary since the class-level attribute alone is sufficient and consistent with other tracker implementations.Apply this diff to remove the redundant instance attribute:
self.source_flag = 'AvistaZ' self.banned_groups = [''] self.base_url = 'https://avistaz.to' self.torrent_url = f'{self.base_url}/torrent/' self.requests_url = f'{self.base_url}/requests' - self.is_http = TrueAlso applies to: 179-181
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (29)
src/trackers/ANT.py(2 hunks)src/trackers/AR.py(2 hunks)src/trackers/ASC.py(2 hunks)src/trackers/AZ.py(3 hunks)src/trackers/BHD.py(1 hunks)src/trackers/BHDTV.py(1 hunks)src/trackers/BJS.py(2 hunks)src/trackers/BT.py(2 hunks)src/trackers/CZ.py(2 hunks)src/trackers/DC.py(2 hunks)src/trackers/FF.py(2 hunks)src/trackers/FL.py(1 hunks)src/trackers/GPW.py(2 hunks)src/trackers/HDB.py(1 hunks)src/trackers/HDS.py(2 hunks)src/trackers/HDT.py(2 hunks)src/trackers/IS.py(2 hunks)src/trackers/MTV.py(1 hunks)src/trackers/NBL.py(1 hunks)src/trackers/PHD.py(2 hunks)src/trackers/PTER.py(1 hunks)src/trackers/PTS.py(2 hunks)src/trackers/RTF.py(1 hunks)src/trackers/SN.py(2 hunks)src/trackers/SPD.py(2 hunks)src/trackers/TL.py(2 hunks)src/trackers/TTG.py(1 hunks)src/trackers/TVC.py(1 hunks)src/trackers/UNIT3D.py(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (16)
- src/trackers/BHD.py
- src/trackers/TL.py
- src/trackers/FL.py
- src/trackers/CZ.py
- src/trackers/ANT.py
- src/trackers/SN.py
- src/trackers/TVC.py
- src/trackers/UNIT3D.py
- src/trackers/GPW.py
- src/trackers/NBL.py
- src/trackers/MTV.py
- src/trackers/BJS.py
- src/trackers/HDB.py
- src/trackers/FF.py
- src/trackers/BT.py
- src/trackers/PTS.py
🔇 Additional comments (11)
src/trackers/PHD.py (1)
348-350: LGTM! Class attribute correctly defined for tracker type mapping.The
is_http = Trueattribute is properly defined at class scope to support dynamic tracker discovery.src/trackers/DC.py (1)
320-322: LGTM! Class attribute correctly defined for tracker type mapping.The
is_other_api = Trueattribute is properly defined at class scope to categorize DC as an alternate API tracker during dynamic discovery.src/trackers/IS.py (1)
300-302: LGTM! Class attribute correctly defined for tracker type mapping.The
is_http = Trueattribute is properly defined at class scope to support dynamic tracker discovery.src/trackers/ASC.py (1)
909-911: LGTM! Class attribute correctly defined for tracker type mapping.The
is_http = Trueattribute is properly defined at class scope to support dynamic tracker discovery.src/trackers/RTF.py (1)
236-238: LGTM! Class attribute correctly defined for tracker type mapping.The
is_other_api = Trueattribute is properly defined at class scope to categorize RTF as an alternate API tracker during dynamic discovery.src/trackers/HDS.py (1)
335-337: LGTM! Class attribute correctly defined for tracker type mapping.The
is_http = Trueattribute is properly defined at class scope to support dynamic tracker discovery.src/trackers/AR.py (1)
451-453: LGTM! Class attribute correctly defined for tracker type mapping.The
is_http = Trueattribute is properly defined at class scope to support dynamic tracker discovery.src/trackers/SPD.py (1)
337-339: LGTM!The class-level
is_other_apiattribute is correctly added to support dynamic tracker type mapping.src/trackers/HDT.py (1)
351-353: LGTM!The class-level
is_httpattribute is correctly added to support dynamic tracker type mapping.src/trackers/PTER.py (1)
410-412: LGTM!The class-level
is_httpattribute is correctly added to support dynamic tracker type mapping.src/trackers/BHDTV.py (1)
197-199: LGTM!The class-level
is_other_apiattribute is correctly added to support dynamic tracker type mapping.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (1)
src/trackers/TTG.py (1)
354-355: Critical: Moveis_httpto class level (issue persists from previous review).The
is_httpattribute remains incorrectly scoped inside thedownload_new_torrentmethod. For the dynamic tracker-type mapping introduced in this PR to work,is_httpmust be a class-level attribute accessible to the discovery logic intrackersetup.py. As it stands, TTG will not be categorized correctly.Move the attribute outside the method and align it with other method definitions at class level:
async def download_new_torrent(self, id, torrent_path): download_url = f"https://totheglory.im/dl/{id}/{self.passkey}" r = requests.get(url=download_url) if r.status_code == 200: with open(torrent_path, "wb") as tor: tor.write(r.content) else: console.print("[red]There was an issue downloading the new .torrent from TTG") console.print(r.text) - - # required for tracker type mapping - is_http = True + +# required for tracker type mapping +is_http = True
🧹 Nitpick comments (1)
src/trackers/AZ.py (1)
178-180: Consider moving class attribute to the top of the class definition.The
is_http = Trueattribute works correctly here, and the dynamic tracker mapping approach looks good. However, Python convention typically places class-level attributes at the beginning of the class (right after the class declaration, before__init__), making them easier to discover.Optional refactor to improve discoverability:
class AZ(AZTrackerBase): + # required for tracker type mapping + is_http = True def __init__(self, config):And remove from the end:
return - - # required for tracker type mapping - is_http = True
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/trackersetup.py (2)
49-50: Add None check before instantiating tracker class.If the tracker is not found in
tracker_class_map, this will raiseTypeError: 'NoneType' object is not callable.Apply this diff:
tracker_class = tracker_class_map.get(tracker.upper()) +if not tracker_class: + console.print(f"[red]Tracker {tracker} is not registered in tracker_class_map[/red]") + return None tracker_instance = tracker_class(self.config)
278-279: Add None check before instantiating tracker class.If the tracker is not found in
tracker_class_map, this will raiseTypeError: 'NoneType' object is not callable.Apply this diff:
tracker_class = tracker_class_map.get(tracker.upper()) +if not tracker_class: + console.print(f"[red]Tracker {tracker} is not registered in tracker_class_map[/red]") + return None tracker_instance = tracker_class(self.config)
♻️ Duplicate comments (2)
src/trackersetup.py (2)
596-596: Add None check before instantiating COMMON.If
COMMONis not intracker_class_map(e.g., due to discovery failure), this line will raiseTypeError: 'NoneType' object is not callable.Apply this diff:
- common = tracker_class_map.get('COMMON')(config) + common_class = tracker_class_map.get('COMMON') + if not common_class: + console.print("[red]COMMON tracker class not found in tracker_class_map[/red]") + return False + common = common_class(config)
842-846: Add validation that the tracker directory exists.If the directory structure is malformed or
tracker_dirdoesn't exist,os.listdirwill raise aFileNotFoundErrorat import time with an unclear error message.Apply this diff:
tracker_dir = os.path.join(os.path.dirname(__file__), 'trackers') +if not os.path.isdir(tracker_dir): + raise RuntimeError(f"Tracker directory not found: {tracker_dir}") tracker_module_names = [ f[:-3] for f in os.listdir(tracker_dir) if f.endswith('.py') and f != '__init__.py' ]
🧹 Nitpick comments (1)
src/trackersetup.py (1)
862-863: Consider validating the tracker attribute type.The code falls back to using the class name if the
trackerattribute is missing, but doesn't validate that thetrackerattribute (if present) is a string. If someone accidentally setstrackerto a non-string value, calling.upper()would raise anAttributeError.Consider adding type validation:
- tracker_code = getattr(obj, 'tracker', name).upper() + tracker_attr = getattr(obj, 'tracker', name) + if not isinstance(tracker_attr, str): + console.print(f"[yellow]Warning: {name}.tracker is not a string, using class name instead[/yellow]") + tracker_attr = name + tracker_code = tracker_attr.upper() tracker_class_map[tracker_code] = obj
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/trackersetup.py(4 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-11T08:09:03.381Z
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 991
File: src/trackers/THR.py:263-263
Timestamp: 2025-11-11T08:09:03.381Z
Learning: For src/trackers/THR.py in Audionut's pull requests, do not flag issues about mixing synchronous requests calls (like requests.post, requests.get) with async functions. The file needs a refactor, and these issues should be ignored until then.
Applied to files:
src/trackersetup.py
🔇 Additional comments (2)
src/trackersetup.py (2)
2-2: LGTM! Necessary imports for dynamic tracker loading.The new imports support the dynamic discovery pattern:
importlibfor loading modules,inspectfor introspection, andaiofilesfor async file operations.Also applies to: 9-10
18-22: LGTM! Constructor properly stores config.The addition of the
configparameter aligns with the dynamic tracker loading pattern where config is needed for tracker instantiation.
| for mod_name in tracker_module_names: | ||
| if mod_name in ('AVISTAZ_NETWORK', 'UNIT3D_TEMPLATE', 'UNIT3D'): | ||
| continue # Skip this module entirely | ||
|
|
||
| api_trackers = { | ||
| 'ACM', 'AITHER', 'AL', 'BHD', 'BLU', 'CBR', 'DP', 'EMUW', 'FNP', 'FRIKI', 'HHD', 'HUNO', 'ITT', 'LCD', 'LDU', 'LST', 'LT', | ||
| 'OE', 'OTW', 'PT', 'PTT', 'RAS', 'RF', 'R4E', 'SAM', 'SHRI', 'SP', 'STC', 'TIK', 'TTR', 'ULCX', 'UTP', 'YOINK', 'YUS' | ||
| } | ||
| full_mod_name = f'src.trackers.{mod_name}' | ||
| module = importlib.import_module(full_mod_name) | ||
|
|
||
| other_api_trackers = { | ||
| 'ANT', 'BHDTV', 'DC', 'GPW', 'NBL', 'RTF', 'SN', 'SPD', 'TL', 'TVC' | ||
| } | ||
| for name, obj in inspect.getmembers(module, inspect.isclass): | ||
| if obj.__module__ == full_mod_name: | ||
| tracker_code = getattr(obj, 'tracker', name).upper() | ||
| tracker_class_map[tracker_code] = obj | ||
|
|
||
| http_trackers = { | ||
| 'AR', 'ASC', 'AZ', 'BJS', 'BT', 'CZ', 'FF', 'FL', 'HDB', 'HDS', 'HDT', 'IS', 'MTV', 'PHD', 'PTER', 'PTS', 'TTG' | ||
| } | ||
| if getattr(obj, 'is_http', False): | ||
| http_trackers[tracker_code] = obj | ||
| elif getattr(obj, 'is_api', False): | ||
| api_trackers[tracker_code] = obj | ||
| elif getattr(obj, 'is_other_api', False): | ||
| other_api_trackers[tracker_code] = obj |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add error handling for module imports.
If a tracker module fails to import (e.g., syntax error, missing dependency), the loop continues silently and that tracker won't be available. This makes debugging difficult and could lead to confusing runtime errors when users try to use an unavailable tracker.
Apply this diff to add error handling:
for mod_name in tracker_module_names:
if mod_name in ('AVISTAZ_NETWORK', 'UNIT3D_TEMPLATE', 'UNIT3D'):
continue # Skip this module entirely
full_mod_name = f'src.trackers.{mod_name}'
- module = importlib.import_module(full_mod_name)
+ try:
+ module = importlib.import_module(full_mod_name)
+ except Exception as e:
+ console.print(f"[yellow]Warning: Failed to import tracker module {mod_name}: {e}[/yellow]")
+ continue
for name, obj in inspect.getmembers(module, inspect.isclass):
if obj.__module__ == full_mod_name:
tracker_code = getattr(obj, 'tracker', name).upper()
tracker_class_map[tracker_code] = obj
if getattr(obj, 'is_http', False):
http_trackers[tracker_code] = obj
elif getattr(obj, 'is_api', False):
api_trackers[tracker_code] = obj
elif getattr(obj, 'is_other_api', False):
other_api_trackers[tracker_code] = obj🤖 Prompt for AI Agents
In src/trackersetup.py around lines 853 to 870, the loop imports tracker modules
without error handling so import failures silently skip trackers; wrap the
importlib.import_module(full_mod_name) call in a try/except that catches
Exception, log an error including full_mod_name and the exception/traceback
(using the module logger or existing process logger), and continue to the next
mod_name so the app remains stable and the failure is visible for debugging.
dynamically create the following in trackersetup
tracker_class_map = {}
http_trackers = {}
api_trackers = {}
other_api_trackers = {}
i tested with bhd, ar, huno, bhdtv and 2 custom trackers and it worked as expect.
I expect there could be issues with PTP or an AZ tracker but i can not test with those.
for those of us with custom trackers this makes life a million times easier as we dont have to make any changes when we update UA.
Summary by CodeRabbit