-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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 a base_url
option to ClientSession
#6129
Conversation
Codecov Report
@@ Coverage Diff @@
## master #6129 +/- ##
==========================================
- Coverage 93.29% 93.29% -0.01%
==========================================
Files 102 102
Lines 30238 30351 +113
Branches 2712 2729 +17
==========================================
+ Hits 28212 28315 +103
- Misses 1849 1858 +9
- Partials 177 178 +1
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
tests/test_client_session.py
Outdated
async def test_request_uses_base_url_when_url_is_str() -> None: | ||
request_class = mock.MagicMock() | ||
session = ClientSession("http://example.com", request_class=request_class) | ||
with contextlib.suppress(Exception): |
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.
Why not be more precise here?
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.
What do you mean?
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.
Exception
seems too broad. What sort of error do you expect really?
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.
That was exactly the point. In this test I don't care about the exception, I care only about the call of the request_class
.
Actually quite many things happen inside ClientSession._request
, and I don't want this test to fail because something unrelated to it has been changed.
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 disagree with this perception. There are things that we'd want to fail the test. For example, we make pytest error out on any warnings (namely deprecation warnings). This will silently shadow those while they must bubble up and show up as an error.
tests/test_client_session.py
Outdated
with contextlib.suppress(Exception): | ||
await session.get("/test") | ||
|
||
args, _ = request_class.call_args |
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.
Why not use called_with_args()
?
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 need to check only the url param. The others I don't care.
For called_with_args
you have to specify all of them.
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.
Yeah, you could specify mocks for those IIRC.
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 reason I dislike the current approach is that having a check to "extract an element from a list and compare it with some value" is semantically ambiguous. It doesn't mean anything. While called_with_args()
communicates the intent of the test better.
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.
Same idea as with supress(Exception)
. Here the only thing that matters is the url
param of the request_class
constructor.
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's not the only thing that matters. Shadowing the underlying warnings shouldn't happen because it's important for us to see any deprecations as soon as any runtime deps get updated: https://github.com/aio-libs/aiohttp/pull/6129/files#r738312860.
base_url
option to ClientSession
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 have a couple of suggestions if we agree to follow URL.join()
behavior.
Maybe urljoin
is not the fastest approach but it can be improved by the next yarl
release easily.
endpoints of ``http://httpbin.org`` can be used the following code:: | ||
|
||
async with aiohttp.ClientSession('http://httpbin.org') as session: | ||
async with session.get('/get'): |
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 code is correct, sure.
I think an example (or .. note::
) that demonstrates the result of joining base URL with partial path and a relative path can be helpful also.
httpbin.org supports /status/{codes}
and /image/jpeg
/ /image/png
urls.
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 is an example that uses base_url
feature of the code above.
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.
Something like a doctest could be more visual here.
>>> invocation_block()
result
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.
Actually this is the problem.
If I call URL.join
for http://httpbin.org/status
and 200
I get http://httpbin.org/200
which is probably not expected result :-)
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.
Oooh.
Tests for the standard urllib.parse.urljoin()
:
In [1]: from urllib.parse import urljoin
In [2]: urljoin("http://a.b.c:/path", "to")
Out[2]: 'http://a.b.c:/to'
In [3]: urljoin("http://a.b.c:/path/", "to")
Out[3]: 'http://a.b.c:/path/to'
In [4]: urljoin("http://a.b.c:/path/thing", "to")
Out[4]: 'http://a.b.c:/path/to'
In [5]: urljoin("http://a.b.c:/path/thing/foo", "to")
Out[5]: 'http://a.b.c:/path/thing/to'
Sorry, I should go now.
Tomorrow I'll check the compliance of behavior above with RFC. I suspect it matches :(
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.
Ok, works as expected by RFC.
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.
Checked one more time:
>>> from yarl import URL
>>> URL("http://httpbin.org/status").join(URL("/200"))
URL('http://httpbin.org/200')
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.
@asvetlov
It works as expected by RFC, but I think the feature wasn't about RFC implementation.
May be it would be better if base_url='http://httpbin.org/status'
and url='/200'
build http://httpbin.org/status'/200
.
Not RFC complaint, but I would expect such behavior.
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.
Another option is following the current url / path
behavior:
base_url='http://httpbin.org/status'
and url='/200'
is forbidden
base_url='http://httpbin.org/status'
and url='200'
builds http://httpbin.org/status/200
BTW, should we forbid query/fragment parts in base_url
? They are ignored anyway.
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.
Let's wait for the user feedback on it.
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.
LGTM.
I prefer functional tests over mocks (test server that handles all requests and returns request.url
in response body can be used) but I can live with the current state.
Mocking increases the chance of dropping in internals are changed (I want to drop request_class
argument eventually in 4.x for example).
Co-authored-by: Sviatoslav Sydorenko <[email protected]>
Co-authored-by: Andrew Svetlov <[email protected]>
Co-authored-by: Sviatoslav Sydorenko <[email protected]>
I'm merging as-is. |
Backport to 3.8: 💔 cherry-picking failed — conflicts found❌ Failed to cleanly apply 527b1b9 on top of patchback/backports/3.8/527b1b9b6f60b0becae3e63550c1b76de1b189e7/pr-6129 Backporting merged PR #6129 into master
🤖 @patchback |
💔 Backport was not successfulThe PR was attempted backported to the following branches:
|
Co-authored-by: Andrew Svetlov <[email protected]> Co-authored-by: Sviatoslav Sydorenko <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Backported by 59bbcac |
What do these changes do?
Add
base_url
toClientSession
constructor that makes several requests to the same server look simpler.Are there changes in behavior for the user?
New optional parameter in
ClientSession
constructor. If not set, the behavior is not changed.Related issue number
Fixes #6013
Checklist
CONTRIBUTORS.txt
CHANGES
folder<issue_id>.<type>
for example (588.bugfix)issue_id
change it to the pr id after creating the pr.feature
: Signifying a new feature..bugfix
: Signifying a bug fix..doc
: Signifying a documentation improvement..removal
: Signifying a deprecation or removal of public API..misc
: A ticket has been closed, but it is not of interest to users.