Add top-level comments APIs
Review Request #12296 — Created May 23, 2022 and submitted
Comment resources are currently child resources of reviews. This limits the type
of queries we can do for comments, for example we can't query for all diff
comments created by a given user.This change adds top-level API endpoints for comments. We register root list
resources for diff comments, file attachment comments and general comments and
support GET requests for the resources with the following query parameters:
-review-request-id=<review-request-id>
,review-id=<review-id>
,
user=<user-username>
,is-reply
for all
-file-diff-id
,line
andinterdiff-revision
for diff comments
-file-attachment-id
andfile-name
for file attachment commentsThis change also improves the docstrings and code readability for base diff
comments, base file attachment comments, and base general review comments.Based on work by Chaoyu Xiang at /r/12037.
- Created GET method unit tests for the new resources and ran them successfully
- Manually tested the
/api/general-comments/
,/api/diff-comments/
and
api/file-attachment-comments
endpoints
Summary | ID | Author |
---|---|---|
a5f42292a09663b7e512c6a9d002282dee719333 | Michelle |
Description | From | Last Updated |
---|---|---|
Along the lines of what I said in the Reviews API and CommentManager changes, we should ensure that all the … |
chipx86 | |
E999 SyntaxError: invalid syntax |
reviewbot | |
E999 SyntaxError: invalid syntax |
reviewbot | |
E999 SyntaxError: invalid syntax |
reviewbot | |
E999 SyntaxError: invalid syntax |
reviewbot | |
E999 SyntaxError: invalid syntax |
reviewbot | |
E999 SyntaxError: invalid syntax |
reviewbot | |
Should we specify what "more advanced queries" we made possible? |
maubin | |
E999 SyntaxError: invalid syntax |
reviewbot | |
E999 SyntaxError: invalid syntax |
reviewbot | |
E999 SyntaxError: invalid syntax |
reviewbot | |
coming -> incoming |
david | |
key argument pairs -> keyword arguments |
david | |
This needs a type, and the description should be reworded. We don't need to say "Django's queryset" |
david | |
Same comments here. |
david | |
And here. |
david | |
This can probably just be q = q.filter(review__review_request=review_request). No need for a Q object here. |
david | |
Not sure how best to organize this, but maybe "All Comments". An argument could also be made to just put … |
chipx86 | |
"ID" |
chipx86 | |
This should have , optional after the type. |
chipx86 | |
This should be *args. |
chipx86 | |
This should be **kwargs. |
chipx86 | |
For multi-line conditionals, you can use parens: if ('review_request_id' in kwargs and kwargs['review_request_id'] is not None): Though in this case, … |
chipx86 | |
We can omit this and leave it up to the parent method. |
chipx86 | |
Same comments as above regarding the * in the names. |
chipx86 | |
This blank line can be removed. |
chipx86 | |
This should probably be in the parameter list. |
chipx86 | |
These can use q &=. |
chipx86 | |
When working with multiple keyword arguments, we often prefer to do one parameter per line to keep it readable and … |
chipx86 | |
Can you order these in alphabetical order? That'll help make it obvious where any new query arguments should go. |
chipx86 | |
Since we need a ' in the string, and don't use " anywhere, we can use " for the strings … |
chipx86 | |
No blank line here. |
chipx86 | |
We probably don't need this anymore, if we're reusing the other mimetype constants. |
chipx86 | |
Private methods should always go after all the public methods in the class. We also try to add docstrings for … |
chipx86 | |
This can be one line. Some older tests didn't do this, but we're moving away from that. |
chipx86 | |
Assigning unused variables to _ is a convention many use, but it's harmful in our codebase because _ is (also … |
chipx86 | |
local variable 'comment2' is assigned to but never used Column: 9 Error code: F841 |
reviewbot | |
local variable 'comment' is assigned to but never used Column: 9 Error code: F841 |
reviewbot | |
local variable 'comment2' is assigned to but never used Column: 9 Error code: F841 |
reviewbot | |
local variable 'comment2' is assigned to but never used Column: 9 Error code: F841 |
reviewbot | |
line too long (81 > 79 characters) Column: 80 Error code: E501 |
reviewbot | |
local variable 'comment' is assigned to but never used Column: 9 Error code: F841 |
reviewbot | |
no newline at end of file Column: 67 Error code: W292 |
reviewbot | |
local variable 'comment2' is assigned to but never used Column: 9 Error code: F841 |
reviewbot | |
local variable 'comment2' is assigned to but never used Column: 9 Error code: F841 |
reviewbot | |
local variable 'comment' is assigned to but never used Column: 9 Error code: F841 |
reviewbot | |
Instead of "API Class", let's say "API resource" |
david | |
I don't think "made on a review" makes sense here because we're not dealing with reviews. |
david | |
Instead of "API Class", let's say "API resource" |
david | |
Nix "made on a review" |
david | |
Instead of "API Class", let's say "API resource" |
david | |
Nix "made on a review" |
david | |
"different comments" -> "diff comments" |
david | |
Should be RootDiffCommentResource |
david | |
Should be RootFileAttachmentCommentResource |
david | |
RootGeneralCommentResource |
david | |
Let's have this explicitly check against None (differentiating from 0, ensuring users can't bypass this with some provided parameter). |
chipx86 | |
Same as above, let's compare explicitly against None. |
chipx86 | |
Same as above, let's explicitly check against None. |
chipx86 | |
If we do __id=, we may force a JOIN to the reviews_review table. We can leave that off and just … |
chipx86 | |
This will also force a JOIN, and we want to avoid that. Except we can't just hard-code a comparison with … |
chipx86 | |
Let's pre-fetch the user (just the user's ID, actually, using .values_list('pk', flat=True)). If we get 0 results, we can explicitly … |
chipx86 | |
This can just be file_attachment=. |
chipx86 | |
Same comments as above regarding the JOINs, Local Site handling, and pre-fetching/checking the user ID. |
chipx86 | |
We can probably just say: These are listed in :py:meth:`get_list`. Same elsewhere. |
chipx86 | |
Same comments as above regarding the JOINs, Local Site handling, and pre-fetching/checking the user ID. |
chipx86 | |
continuation line under-indented for visual indent Column: 34 Error code: E128 |
reviewbot | |
While here, can you update this to include a blank line between class-level docstrings and members? Good opportunity to fix … |
chipx86 | |
Small nit: Rather than frm and to, let's go ahead and just make these something like timestamp_from and timestamp_to. Same … |
chipx86 |
- Commits:
-
Summary ID Author a5b9010d4b02e1e6b67a87d07ff8487788e59ae1 Michelle 5281065b69e86ae7d43aac81583424cbb614ca4b Michelle - Diff:
-
Revision 2 (+2834 -48)
- Commits:
-
Summary ID Author 5281065b69e86ae7d43aac81583424cbb614ca4b Michelle ecad7abf9fe6eed0dc0f5d125898d937b5e4916a Michelle - Diff:
-
Revision 3 (+2834 -48)
- Description:
-
Comment resources are currently child resources of reviews. This limits the type
of queries we can do for comments, for example we can't query for all diff comments created by a given user. This change adds top-level API endpoints for comments. We register root list
resources for diff comments, file attachment comments and general comments and support GET requests for the resources with the following query parameters: - review-request-id=<review-request-id>
,review-id=<review-id>
,user=<user-username>
,is-reply
for all- file-diff-id
,line
andinterdiff-revision
for diff comments- file-attachment-id
andfile-name
for file attachment comments~ This change also improves the docstrings and code readbility for base diff
~ This change also improves the docstrings and code readability for base diff
comments, base file attachment comments, and base general review comments. Based on work by Chaoyu Xiang at /r/12037.
- Commits:
-
Summary ID Author ecad7abf9fe6eed0dc0f5d125898d937b5e4916a Michelle 9117c319a9b428260d58856b883014a76b247cfc Michelle - Diff:
-
Revision 4 (+3382 -48)
Checks run (2 succeeded)
- Change Summary:
-
added dependency on #12309
- Change Summary:
-
fixed up arg types and wording in docstrings, also cleaned up query code
- Commits:
-
Summary ID Author 9117c319a9b428260d58856b883014a76b247cfc Michelle 33a3cae263e543ea456b082140c42e521c6d66c3 Michelle - Diff:
-
Revision 5 (+3406 -58)
Checks run (2 succeeded)
-
Thanks for taking this on! It'll be great to have this in.
Many of the comments here apply to all the comment type variations.
-
Not sure how best to organize this, but maybe "All Comments".
An argument could also be made to just put this in "Reviews".
-
-
-
-
-
For multi-line conditionals, you can use parens:
if ('review_request_id' in kwargs and kwargs['review_request_id'] is not None):
Though in this case, we should have
review_request_id
in the function's argument list. -
-
-
-
-
-
When working with multiple keyword arguments, we often prefer to do one parameter per line to keep it readable and maintainable.
-
Can you order these in alphabetical order? That'll help make it obvious where any new query arguments should go.
-
Since we need a
'
in the string, and don't use"
anywhere, we can use"
for the strings itself and avoid the escape.Same below.
-
-
-
Private methods should always go after all the public methods in the class.
We also try to add docstrings for helper methods in unit tests. We didn't always, so some older test modules lack this.
-
-
Assigning unused variables to
_
is a convention many use, but it's harmful in our codebase because_
is (also by convention) often mapped togettext
.Fun fact: A lot of online Python guides claim
_
is a feature of the language for unused variables, but it's no different than any other variable name. Python doesn't treat it specially.
- Change Summary:
-
- Changed the
Root Comments
category in the webapi resources index toComments
- Fixed up
get_queryset
method and docstrings for all base comment resources - Added
interdiff-revision
request field toRootDiffCommentResource
- Applied query optimizations, alphabetized and small style changes to the root comment resources
- Moved private methods so that they're after public ones in tests, added docstrings to private methods
- Made tests docstrings one line when able to
- Got rid of
_
for unused variables
- Changed the
- Commits:
-
Summary ID Author 33a3cae263e543ea456b082140c42e521c6d66c3 Michelle 007d73bdb4128b3b3c9fab81db7bc459ab2d691c Michelle - Diff:
-
Revision 6 (+3681 -204)
Checks run (1 failed, 1 succeeded)
flake8
- Change Summary:
-
Removed unused variables
- Commits:
-
Summary ID Author 007d73bdb4128b3b3c9fab81db7bc459ab2d691c Michelle 3f94075dc5e48f174bfd999ddfc877e6d0c46baa Michelle - Diff:
-
Revision 7 (+3681 -204)
Checks run (2 succeeded)
- Change Summary:
-
Changed category name for the root comments in the webapi resources index to "All Comments"
- Commits:
-
Summary ID Author 3f94075dc5e48f174bfd999ddfc877e6d0c46baa Michelle ddcf5ea50d437d6c7fff66628728c1e24fe589ff Michelle - Diff:
-
Revision 8 (+3681 -204)
Checks run (2 succeeded)
- Change Summary:
-
rebased with release-5.0.x
- Commits:
-
Summary ID Author ddcf5ea50d437d6c7fff66628728c1e24fe589ff Michelle 95982b53570f2c38e66dc4d3fe4d737e0e860f09 Michelle - Diff:
-
Revision 9 (+3652 -90)
Checks run (2 succeeded)
- Change Summary:
-
- Fixed a typo
- Improved
compare_item
docstrings
- Commits:
-
Summary ID Author 95982b53570f2c38e66dc4d3fe4d737e0e860f09 Michelle 7f33f30b50e4e541d57198833d1c21feed7a1a09 Michelle - Diff:
-
Revision 10 (+3652 -90)
Checks run (2 succeeded)
- Commits:
-
Summary ID Author 7f33f30b50e4e541d57198833d1c21feed7a1a09 Michelle c9e9c7d0be9c7d3d26f0786d4a25fd678a577e36 Michelle - Diff:
-
Revision 11 (+3652 -90)
Checks run (2 succeeded)
-
A few things that'll be important to fix regarding querying here, to avoid data leaks in results.
-
Along the lines of what I said in the Reviews API and CommentManager changes, we should ensure that all the unit tests have data that should not match based on access or filtering.
-
Let's have this explicitly check against
None
(differentiating from 0, ensuring users can't bypass this with some provided parameter). -
-
-
If we do
__id=
, we may force a JOIN to thereviews_review
table. We can leave that off and just doreview=
, which will do the right thing and compare againstreview_id
. -
This will also force a JOIN, and we want to avoid that.
Except we can't just hard-code a comparison with the ID. If using a Local Site, then the PK of the object is actually not the ID. The
local_id
field is. But only if on a Local Site. This gives usLocalSite
-bound sequential IDs.So what we need to do is:
if local_site is None: q &= Q(review__review_request=review_request_id) else: q &= (Q(review__review_request__local_id=review_request_id) & Q(review__review_request__local_site=local_site))
We'll need to ensure that unit tests cover ID vs. Local ID testing, and that no data leaks between the two.
-
Let's pre-fetch the user (just the user's ID, actually, using
.values_list('pk', flat=True)
). If we get 0 results, we can explicitly returnself.model.objects.none()
, since we know nothing will end up matching. -
-
Same comments as above regarding the JOINs, Local Site handling, and pre-fetching/checking the user ID.
-
-
Same comments as above regarding the JOINs, Local Site handling, and pre-fetching/checking the user ID.
- Change Summary:
-
- Better test coverage
- Made some dosctrings better and more consistent
- Removed a couple more JOINs
- Commits:
-
Summary ID Author c9e9c7d0be9c7d3d26f0786d4a25fd678a577e36 Michelle d5b833fd2b7289a171f15f15aafb55607bbec57a Michelle - Depends On:
-
- Diff:
Revision 12 (+5500 -90)
- Change Summary:
-
fix a line indentation
- Commits:
-
Summary ID Author d5b833fd2b7289a171f15f15aafb55607bbec57a Michelle 4c14325694cbce016885fcebe07660152bbc3fcc Michelle - Diff:
-
Revision 13 (+5500 -90)
Checks run (2 succeeded)
-
-
While here, can you update this to include a blank line between class-level docstrings and members? Good opportunity to fix this, since the lines are being modified here.
There are some other spots where this can be done as well. We only have the trailing blank line for module-level and class-level docstrings (weird inconsistency, but it's standard in Python).
-
Small nit: Rather than
frm
andto
, let's go ahead and just make these something liketimestamp_from
andtimestamp_to
.Same if we do this anywhere else.
- Change Summary:
-
- Added a blank line between class-level docstrings and members
- Changed
frm
andto
variable names in timestamp tests to more descriptive ones
- Commits:
-
Summary ID Author 4c14325694cbce016885fcebe07660152bbc3fcc Michelle a5f42292a09663b7e512c6a9d002282dee719333 Michelle - Diff:
-
Revision 14 (+5534 -90)