-
Notifications
You must be signed in to change notification settings - Fork 4
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
Support external aiohttp session #41
Conversation
…nt and add ETag cache clearing method
📝 WalkthroughWalkthroughThe changes to the Changes
Sequence DiagramsequenceDiagram
participant User
participant iRail
participant ClientSession
alt New Session
User->>iRail: Initialize with no session
iRail->>ClientSession: Create new session
iRail-->>User: iRail instance
else Existing Session
User->>iRail: Initialize with existing session
iRail->>ClientSession: Use provided session
iRail-->>User: iRail instance
end
User->>iRail: clear_etag_cache()
iRail-->>User: Cache cleared
Poem
Finishing Touches
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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
🧹 Nitpick comments (5)
pyrail/irail.py (5)
57-57
: Consider using a more precise type annotation for the session parameter.The type annotation could be more specific by using
aiohttp.ClientSession
instead of justClientSession
to make the expected type clearer.-def __init__(self, lang: str = "en", session: ClientSession | None = None) -> None: +def __init__(self, lang: str = "en", session: aiohttp.ClientSession | None = None) -> None:Also applies to: 62-62
70-71
: Document session ownership behavior.The session ownership tracking is implemented correctly, but it would be helpful to document this behavior in the class docstring to make it clear to users how session lifecycle management works.
Add this to the class docstring:
"""A Python wrapper for the iRail API, handling rate limiting and endpoint requests. Attributes: lang (str): The language for API responses ('nl', 'fr', 'en', 'de'). + session (aiohttp.ClientSession | None): The HTTP session used for API requests. + If not provided, a new session will be created and managed internally. + If provided, the session lifecycle must be managed externally. Endpoints:
76-81
: Enhance session initialization logging.The logging messages could be more descriptive to help with debugging session-related issues.
- logger.debug("Using externally provided session") + logger.debug("Using externally provided session %r", self.session) - logger.debug("Initializing new aiohttp session") + logger.debug("Creating new internal aiohttp session")
89-98
: Improve error handling specificity in session cleanup.The current error handling catches all exceptions, but it would be better to catch specific aiohttp exceptions.
try: await self.session.close() - except Exception as e: + except (aiohttp.ClientError, asyncio.CancelledError) as e: logger.error("Error while closing aiohttp session: %s", e)
124-128
: Add return type annotation and adjust logging level.The method should have a return type annotation, and the logging level should be INFO since cache clearing is a significant operation.
- def clear_etag_cache(self): + def clear_etag_cache(self) -> None: """Clear the ETag cache.""" self.etag_cache.clear() - logger.debug("ETag cache cleared") + logger.info("ETag cache cleared")
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
🧹 Nitpick comments (3)
pyrail/irail.py (3)
60-60
: Consider using newer type annotation syntax.The implementation is correct, but the type annotation could be modernized.
-def __init__(self, lang: str = "en", session: ClientSession | None = None) -> None: +def __init__(self, lang: str = "en", session: None | ClientSession = None) -> None:Note: In Python, it's a convention to put
None
first in Union types withNone
. This makes it clearer that the parameter is optional and matches the pattern used in the standard library.Also applies to: 65-65, 73-74
79-84
: Consider simplifying session closure logic.While the implementation is correct, the session closure logic in
__aexit__
could be more concise.async def __aexit__( self, exc_type: Type[BaseException] | None, exc: BaseException | None, tb: TracebackType | None ) -> None: """Close the aiohttp client session when exiting the async context.""" if self.session: - if self.session.closed: - logger.debug("Session is already closed, skipping closure") - elif not self._owns_session: - logger.debug("Session is externally provided; not closing it") - else: - logger.debug("Closing aiohttp session") - try: - await self.session.close() - except Exception as e: - logger.error("Error while closing aiohttp session: %s", e) + if self._owns_session and not self.session.closed: + logger.debug("Closing aiohttp session") + try: + await self.session.close() + except Exception as e: + logger.error("Error while closing aiohttp session: %s", e) + else: + logger.debug( + "Session is %s, skipping closure", + "already closed" if self.session.closed else "externally provided" + )Also applies to: 92-101
127-131
: Enhance method documentation.While the implementation is correct, the method documentation could be more descriptive.
def clear_etag_cache(self) -> None: - """Clear the ETag cache.""" + """Clear the ETag cache used for conditional requests. + + This method removes all cached ETags, forcing subsequent requests to fetch fresh data + instead of receiving 304 Not Modified responses. + + Example: + async with iRail() as client: + await client.get_stations() # Response cached with ETag + client.clear_etag_cache() # Clear the cache + await client.get_stations() # Fresh data fetched + """ self.etag_cache.clear() logger.info("ETag cache cleared")
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
pyrail/irail.py
(3 hunks)
🔇 Additional comments (2)
pyrail/irail.py (2)
31-33
: LGTM! Well-documented session attribute.The documentation clearly explains the session parameter's optionality and lifecycle management responsibilities.
31-33
: Verify proper session cleanup in documentation.While the implementation correctly handles session lifecycle, consider adding a warning in the documentation about the importance of proper cleanup when using external sessions.
session (ClientSession, optional): The HTTP session used for API requests. If not provided, a new session will be created and managed internally. If provided, the session lifecycle must be managed externally. + Warning: When providing an external session, ensure it's properly closed + to prevent resource leaks. The session should be active when entering + the context and remain open until after exiting the context.Let's verify the session management implementation:
Also applies to: 60-60, 73-74
@coderabbitai Do you propose we update the README as well? |
Tip For best results, initiate chat on the files or code changes. @tjorim Yes, I recommend updating the README to document the new features. Here's a suggested addition to include under the "Usage" section: ### Session Management
You can provide an external aiohttp ClientSession:
```python
from aiohttp import ClientSession
async def main():
# Using an external session
async with ClientSession() as session:
async with iRail(session=session) as api:
stations = await api.get_stations()
print(f"Total stations: {len(stations)}")
# Or let iRail manage its own session
async with iRail() as api:
stations = await api.get_stations() Cache ManagementYou can clear the ETag cache when needed: async with iRail() as api:
# Clear the ETag cache
api.clear_etag_cache()
# Subsequent requests will fetch fresh data
stations = await api.get_stations()
#!/bin/bash Check if README exists and show its contentcat README.md 2>/dev/null || echo "README.md not found"
|
@coderabbitai Thanks for your feedback, I implemented these changes in #42. |
Tip For best results, initiate chat on the files or code changes. @tjorim Thank you for implementing the documentation changes! Looking forward to seeing the improved README in PR #42. (_/) If you found this review helpful, would you consider giving us a shout-out on X? |
Enhance iRail API client to support external aiohttp session management and add ETag cache clearing method
Summary by CodeRabbit
New Features
Improvements