-
Notifications
You must be signed in to change notification settings - Fork 687
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
Add type annotations to journalist_app.api #5464
Add type annotations to journalist_app.api #5464
Conversation
auth_token = request.headers.get('Authorization').split(" ")[1] | ||
user = Journalist.validate_api_token_and_get_user(auth_token) | ||
return user | ||
def _authenticate_user_from_auth_header(request: flask.Request) -> Journalist: |
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.
There was code to parse the Authorization header in both get_user_object() and token_required(), so i combined them into just one function (because get_user_object() was causing a lot typing errors).
I would suggest passing the resulting/authenticated user as an argument to functions decorated with @token_require
so that the views that need to know who the current user is don't need to parse the Auth header again (as done in all_source_replies() for example).
I can make the change if that's useful.
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.
It would generally be better to make functional changes in separate PRs, particularly when they're optimizations and involve authentication, instead of mixing the refactoring with the type hinting.
I preferred the old name, get_user_object
: it was accurate, if less precise, and a lot shorter.
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.
At least for 3 people, including my local laptop: the branch is throwing this following error:
✦ ❯ make typelint
███ Running mypy type checking...
securedrop/journalist_app/api.py:200: error: Incompatible return value type (got "werkzeug.wrappers.Response", expected "flask.wrappers.Response")
securedrop/journalist_app/api.py:209: error: Incompatible return value type (got "werkzeug.wrappers.Response", expected "flask.wrappers.Response")
Found 2 errors in 1 file (checked 104 source files)
make: *** [Makefile:124: typelint] Error 1
@emkll please have a look at this, I am okay to approve, but want to know why a few of us saw that error. |
Didn't have this error locally but I can fix it anyway, later today or tomorrow. |
Yes, I can see this in my laptop, but not in the other places. I can not even see this in the CI. You don't have to change anything right now. But, we should figure out why are we seeing this in some machines. |
Strange, I too am seeing the same error @kushaldas is describing. Those errors occur when running
We should definitely resolve this discrepancy prior to merging. @nabla-c0d3 if you want to take a stab at resolving the issue, that would be greatly appreciated. Otherwise we would be happy to investigate on your behalf, just let us know. Thank you for your continued contributions to the project! |
I haven't been able to reproduce this error. I do get the same mypy error message if I replace:
with
which then returns the error:
However this branch does have the correct |
I would suggest merging this PR (so I can continue adding type annotations elsewhere), and then investigating as part of #5516. |
a2b899c
to
5ae517b
Compare
Sorry for the delay @nabla-c0d3 . The source of the confusion on my end is likely related to the merge commit that included this change as part of conflict resolution in a041434 I've taken the liberty of squashing/rebasing this branch on latest |
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 the changes and for your patience @nabla-c0d3 the changes looks good to me, with linting passing locally and CI still passing.
To aid the review of future PR's, it would be helpful if you could:
- Squash/rebase on latest
develop
instead of merging into your branch (though we would be happy to rebase on your behalf, let us know if you'd prefer to do it yourself) - Either limit or separate code refactoring from type annotations as much as possible
Thanks again for your contributions! We'll take a look at #5491 next.
result = model.query.filter(column == object_id).one_or_none() | ||
else: | ||
result = model.query.get(object_id) | ||
def get_or_404(model: db.Model, object_id: str, column: str) -> db.Model: |
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.
Looks like we always specify column as parameter here, so lgtm
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.
Agreed.
auth_token = request.headers.get('Authorization').split(" ")[1] | ||
user = Journalist.validate_api_token_and_get_user(auth_token) | ||
return user | ||
def _authenticate_user_from_auth_header(request: flask.Request) -> Journalist: |
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.
It would generally be better to make functional changes in separate PRs, particularly when they're optimizations and involve authentication, instead of mixing the refactoring with the type hinting.
I preferred the old name, get_user_object
: it was accurate, if less precise, and a lot shorter.
result = model.query.filter(column == object_id).one_or_none() | ||
else: | ||
result = model.query.get(object_id) | ||
def get_or_404(model: db.Model, object_id: str, column: str) -> db.Model: |
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.
Agreed.
if request.method == 'GET': | ||
source = get_or_404(Source, source_uuid, column=Source.uuid) | ||
return jsonify(source.to_json()), 200 | ||
elif request.method == 'DELETE': | ||
source = get_or_404(Source, source_uuid, column=Source.uuid) | ||
utils.delete_collection(source.filesystem_id) | ||
return jsonify({'message': 'Source and submissions deleted'}), 200 | ||
else: | ||
abort(404) |
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.
This is a good addition, as Flask's implicit support for HEAD
means we're setting up a 500 error when we fall out of the if
without handling it, but I think a 405 (method not allowed) status would be more accurate here and the other places you've caught this.
Status
Ready for review.
Description of Changes
To help with #4399 , this PR adds type annotations to journalist_app/api.py