Altering URLs
chey opened this issue · comments
Is your feature request related to a problem?
No
Describe the solution you'd like
Would like the ability to alter single/multiple parts of a URL in single statement.
Example:
>>> URL("http://localhost:8080").with(host="newhost", port=80)
URL("http://newhost")
or this
>>> URL("http://localhost:8080").with(port=80)
URL("http://localhost")
Describe alternatives you've considered
N/A
Additional context
No response
Code of Conduct
- I agree to follow the aio-libs Code of Conduct
build
doesn't alter URLs:
>>> URL("http://localhost:9090").build(port=8080)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/chey/work/vicinity/venv/lib/python3.10/site-packages/yarl/_url.py", line 216, in build
raise ValueError('Can\'t build URL with "port" but without "host".')
ValueError: Can't build URL with "port" but without "host".
build
doesn't alter URLs:
No, URL.build()
is a class method and builds a new URL from scratch. It has no knowledge of the existing instance.
You can chain up multiple with_*
calls, instead:
>>> URL("http://localhost:8080").with_host("newhost").with_port(80)
URL('http://newhost:80')
Note that with
is a keyword in Python so can't be used for a method name; it'd have to be with_
instead or a different name altogether.
That said I'm +0 on adding a URL.with_()
method that passes on keyword arguments to .with_{key}(value)
calls
def with_(self, **kwargs):
new = self
for key, value in kwargs.items():
new = getattr(new, f"with_{key}")(value)
return new
If this was added, the actual implementation would be a bit more robust, perhaps with cached mapping of known with_*
method names to apply so an exception can be raised early if any of the keywords passed don't fit.
You can add the above locally if you want to:
>>> def with_(self, **kwargs):
... new = self
... for key, value in kwargs.items():
... new = getattr(new, f"with_{key}")(value)
... return new
...
>>> URL.with_ = with_
>>> URL("http://localhost:8080").with_(host="newhost", port=80)
URL('http://newhost:80')
Yes, it's clear with
will not be a good method choice. Maybe alter
would be sufficient. Looking at pathlib
i see names like unparse
and unsplit
which seem confusing at first glance.
Yes, it's clear
with
will not be a good method choice. Maybealter
would be sufficient.
update()
would echo update_query()
. Still not sold it is really needed however, but not dead against it at the same time.
Looking at
pathlib
i see names likeunparse
andunsplit
which seem confusing at first glance.
pathlib
doesn't have such methods, maybe you were looking at urllib.parse
instead?
pathlib
doesn't have such methods, maybe you were looking aturllib.parse
instead?
Yes, that's what I was referring to.
You can add the above locally if you want to:
>>> def with_(self, **kwargs): ... new = self ... for key, value in kwargs.items(): ... new = getattr(new, f"with_{key}")(value) ... return new ... >>> URL.with_ = with_ >>> URL("http://localhost:8080").with_(host="newhost", port=80) URL('http://newhost:80')
I did make a similar function to this in order to test out the idea. I suppose one could do a dir
scan of URL
for with_*
in order to add exceptions. Like you said though, that would need to be cached as it would get expensive to scan URL
each time.