Skip to content

Conversation

@niawag
Copy link

@niawag niawag commented Sep 5, 2025

Considering coderabbit return on previous commit, I changed TVShow to TVEpisode as get_history returns episodes, not shows. I edited it instead of approving coderabbit proposition beacause it added unecessary (IMO) stuff.

It resulted in 2 differents PR, I don't know if I could have done it differently I'm no github pro !

added get_history function
Considering coderabbit return on my first PR, I changed TVShow to TVEpisode as get_history returns episodes, not shows. I edited it instead of approving coderabbit proposition beacause it added unecessary (IMO) stuff.
@coderabbitai
Copy link

coderabbitai bot commented Sep 5, 2025

Walkthrough

Added a new function get_history in trakt/sync.py (decorated with @get) to retrieve sync/history with optional type, id, and time-range filters. It constructs the URI with path segments and query parameters, invokes the API, and maps results to Movie or TVEpisode objects. Query param assembly uses separate ?start_at and ?end_at fragments.

Changes

Cohort / File(s) Summary
Sync history endpoint
trakt/sync.py
Added get_history(list_type=None, id=None, start_at=None, end_at=None): builds sync/history URI with optional type/id segments and start_at/end_at query params (timestamps if not strings), performs GET, maps results to Movie/TVEpisode list.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant C as Client
    participant S as Sync.get_history()
    participant A as Trakt API (sync/history)
    participant M as Mapper (Movie/TVEpisode)

    C->>S: get_history(list_type?, id?, start_at?, end_at?)
    Note right of S: Build URI: /sync/history[/type[/id]]<br/>Append start_at/end_at as query params
    S->>A: GET /sync/history...
    A-->>S: JSON history entries
    S->>M: Map each entry by type
    M-->>S: [Movie | TVEpisode, ...]
    S-->>C: Return list
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

I hopped through time, a timestamp trail,
From movies’ glow to episodes’ tale—
History fetched, neat rows align,
A carrot cursor skims the timeline.
Query by dusk, or query by dawn,
I nibble the logs—and bounce along! 🥕⏳

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@niawag niawag changed the title Niawag patch 2 [Feature] added get_history function #2 Sep 5, 2025
Copy link

@coderabbitai coderabbitai bot left a 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)
trakt/sync.py (2)

533-533: Prefer not shadowing built-in id

Rename the parameter and its usages for clarity.

Apply this diff:

-def get_history(list_type=None, id=None, start_at=None, end_at=None):
+def get_history(list_type=None, item_id=None, start_at=None, end_at=None):
@@
-    if id:
-        uri += '/{}'.format(id)
+    if item_id:
+        uri += '/{}'.format(item_id)

Also applies to: 551-553


533-541: Optional: enforce timezone-aware datetimes

If callers pass naive datetimes, timestamp() will serialize them as-is. Consider normalizing to UTC or documenting the expectation.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e879853 and a81574f.

📒 Files selected for processing (1)
  • trakt/sync.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
trakt/sync.py (4)
trakt/core.py (1)
  • get (144-147)
trakt/utils.py (1)
  • timestamp (47-50)
trakt/movies.py (1)
  • Movie (93-387)
trakt/tv.py (1)
  • TVEpisode (723-970)
🔇 Additional comments (1)
trakt/sync.py (1)

547-553: Confirm: is item id valid without specifying type?

Trakt’s docs typically show the form /sync/history/{type}/{id}. If type is required when passing an id, we should guard against item_id without list_type.

Apply this (if confirmed):

     uri = 'sync/history'
     if list_type:
         uri += '/{}'.format(list_type)

-    if item_id:
+    if item_id:
+        if not list_type:
+            raise ValueError("When specifying an id, list_type must be 'movies' or 'episodes'.")
         uri += '/{}'.format(item_id)

Would you like me to check the latest Trakt spec and adjust accordingly?

Comment on lines +554 to +563
if not isinstance(start_at, str):
start_at = timestamp(start_at)
if start_at:
uri += '?start_at={start_at}'.format(start_at=start_at)

if not isinstance(end_at, str):
end_at = timestamp(end_at)
if end_at:
uri += '?end_at={end_at}'.format(end_at=end_at)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Bug: None handling and malformed query string for start_at/end_at

  • start_at/end_at are timestamped even when None -> crashes.
  • Second query param incorrectly uses ? instead of &.

Apply this diff:

-    if not isinstance(start_at, str):
-        start_at = timestamp(start_at)
-    if start_at:
-        uri += '?start_at={start_at}'.format(start_at=start_at)
-               
-    if not isinstance(end_at, str):
-        end_at = timestamp(end_at)
-    if end_at:
-        uri += '?end_at={end_at}'.format(end_at=end_at)
+    params = []
+    if start_at:
+        if not isinstance(start_at, str):
+            start_at = timestamp(start_at)
+        params.append(f"start_at={start_at}")
+    if end_at:
+        if not isinstance(end_at, str):
+            end_at = timestamp(end_at)
+        params.append(f"end_at={end_at}")
+    if params:
+        uri += "?" + "&".join(params)
📝 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.

Suggested change
if not isinstance(start_at, str):
start_at = timestamp(start_at)
if start_at:
uri += '?start_at={start_at}'.format(start_at=start_at)
if not isinstance(end_at, str):
end_at = timestamp(end_at)
if end_at:
uri += '?end_at={end_at}'.format(end_at=end_at)
params = []
if start_at:
if not isinstance(start_at, str):
start_at = timestamp(start_at)
params.append(f"start_at={start_at}")
if end_at:
if not isinstance(end_at, str):
end_at = timestamp(end_at)
params.append(f"end_at={end_at}")
if params:
uri += "?" + "&".join(params)
🤖 Prompt for AI Agents
In trakt/sync.py around lines 554-563, the code timestamps start_at/end_at even
when they are None (causing crashes) and appends the second query param with '?'
instead of '&', producing a malformed query string; fix by only calling
timestamp(...) if the value is not None, build the query string safely by
collecting params into a list (e.g., params = [] then if start_at is not None:
params.append(f"start_at={timestamp(start_at) if not isinstance(start_at, str)
else start_at}") and similarly for end_at) and then append them to uri as '?' +
'&'.join(params) only if params is non-empty (avoiding multiple '?' and skipping
None values).

Comment on lines +572 to +576
elif 'episode' in d:
from trakt.tv import TVEpisode

results.append(TVEpisode(**d.pop('episode')))

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Bug: TVEpisode constructed without required show context

TVEpisode requires show context; constructing with only episode dict will raise or produce an invalid object. Follow the existing pattern used elsewhere in this module.

Apply this diff:

-        elif 'episode' in d:
-            from trakt.tv import TVEpisode
-
-            results.append(TVEpisode(**d.pop('episode')))
+        elif 'episode' in d:
+            from trakt.tv import TVEpisode
+            show = d.pop('show')
+            ep = d.pop('episode')
+            results.append(
+                TVEpisode(
+                    show.get('title', None),
+                    show_id=show['ids'].get('trakt'),
+                    **ep
+                )
+            )
📝 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.

Suggested change
elif 'episode' in d:
from trakt.tv import TVEpisode
results.append(TVEpisode(**d.pop('episode')))
elif 'episode' in d:
from trakt.tv import TVEpisode
show = d.pop('show')
ep = d.pop('episode')
results.append(
TVEpisode(
show.get('title', None),
show_id=show['ids'].get('trakt'),
**ep
)
)
🤖 Prompt for AI Agents
In trakt/sync.py around lines 572-576, the code constructs TVEpisode with only
the episode dict which lacks required show context; instead, pop the episode
dict and the associated show dict (as done elsewhere), construct a TVShow object
from the show dict, then construct the TVEpisode passing the episode fields plus
show=that TVShow instance; also add/import TVShow at the top if not already
imported so the episode has proper show context.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant