-
Notifications
You must be signed in to change notification settings - Fork 9
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
Feat/Context Managers for Document and Security Document #35
Feat/Context Managers for Document and Security Document #35
Conversation
Add async context manager to Security Document;
(one each for Document & Security Document)
Thank you for your PR. Now that you brought it up, the missing context managers look like a major oversight on my side. However, I'm having two concerns regarding your implementation. For The other thing I'm not convinced of is silently discarding a |
Codecov Report
@@ Coverage Diff @@
## master #35 +/- ##
==========================================
+ Coverage 96.67% 96.70% +0.03%
==========================================
Files 11 11
Lines 841 851 +10
==========================================
+ Hits 813 823 +10
Misses 28 28
Continue to review full report at Codecov.
|
Thank you for your kind review! May I suggest keeping the Database member functions as they are for more flexibility / finer control? Can we think of Document / Security Document context managers as sort of an advanced feature? Due to the assumptions these context managers currently make, it's a tradeoff between convenience and finer control. This is the sort of compromise that (I'm not suggesting to follow As for --- a/aiocouch/document.py
+++ b/aiocouch/document.py
@@ -97,7 +97,11 @@ class Document(RemoteDocument):
traceback: Optional[TracebackType],
) -> None:
if exc_type is None:
- with suppress(ConflictError):
+ try:
+ await self.save()
+ except ConflictError:
+ info = await self.info()
+ self.rev = info["rev"]
await self.save() |
@bmario Can you please spare some time to review the changes I've made? |
I'm sorry, but I am at a loss here. I don't know why the Actions keep failing with Mypy itself is not reporting any error:
Am I missing something? Perhaps a token in my forked repo? |
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.
I still haven't figured out the interface yet. But having the context managers as part of the Document
class seems fine for now.
aiocouch/document.py
Outdated
) -> None: | ||
if exc_type is None: | ||
try: | ||
await self.save() |
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.
I think the exception should just bubble up the stack. The problem is that this solution to conflict resolution is just a guess for the correct conflict solution and it doesn't work either, as the second call to save
might raise again.
tests/test_document.py
Outdated
@@ -30,6 +30,26 @@ async def test_constructor_with_wrong_type_for_data( | |||
Document(database, "foo", data=cast(Any, doc)) | |||
|
|||
|
|||
async def test_context_manager(database: Database) -> None: |
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.
Please split the test into two functions
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.
I'll split this test into two functions with the following approach:
In the first function, I'll create and save a new document to the server using context manager. Then, I'll use the database methods to retrieve the newly created document and verify whether the data was actually written to the server.
The second function will be inverse of this. I'll create and save a new document using the database methods. After that, I'll use the context manager to retrieve the newly created document and verify the data.
aiocouch/document.py
Outdated
await self.fetch(discard_changes=True) | ||
return self | ||
|
||
async def __aexit__( |
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.
I think the implementation for this should be the same as in the parent class Document
rendering this method redundant.
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.
Yes, you're right. The __aexit__
method here is redundant indeed. I'll remove it. Thanks.
Don't mind that. I think this is a GitHub Actions configuration issue on my part. |
- use suppress to ignore NotFoundError - let ConflictError bubble up on Document __aexit__ - use typing.cast for Security Document __aenter__ - remove redundant Security __aexit__ - split context manager test into two functions - add test case for using context manager with data parameter
Thank you so much for taking the time to review the code! I've made changes as per your review. |
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.
The implementation itself looks good to me. I'd like to see the fixtures getting used in the one test case though.
Also, can you add a paragraph to the documentation about context managers? That would be appreciated.
tests/test_document.py
Outdated
assert saved_doc["king"] == "elvis" | ||
|
||
|
||
async def test_context_manager_by_retrieving_existing_doc(database: Database) -> None: |
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.
Thanks for splitting the test. Though, I think this test should use one of the predefined documents of the filled_database
fixture: https://github.com/metricq/aiocouch/blob/master/tests/conftest.py#L91
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.
Updated the test to use the filled_database
fixture.
- Use filled_database fixture for testing retrieving existing doc - Add missing `async` to Session document - Explain reasoning behind using async context managers - Give examples of Document & Security Document context managers
I'm using the
I've added a section about context managers to the documentation. The section also contains appropriate, self-contained examples. Please take a look, and do let me know if there are some changes I ought to make. I've also edited the |
Looks good to me now. Thank you. |
Adds asynchronous context managers to both Document and Security Document.
These context managers automatically:
with
block.I've also added the appropriate tests.
An example:
Inspired from (now deprecated) python-cloudant. Their examples for reference: Document Context Manager & Security Document Context Manager
PS: Thank you for this amazing library.