yarl
yarl copied to clipboard
Support building query without values
Sometimes query consists not only of pairs of keys and values but also can contain standalone keys. In my opinion, it's bad, but I encountered this a few times in different APIs. For example, I need to build a URL like: https://api.crowdin.com/api/project/{project_identifier}/pre-translate?key={project_key}&json (see https://support.crowdin.com/api/pre-translate/ for details).
I propose to make an interface look like this:
url = URL('https://api.crowdin.com/api/project/{project-identifier}/pre-translate')
url = url.with_query(key=project_key, json=None)
This is safe because now passing None
as keyword argument value raises TypeError
. If user wants to get an URL with json=
(note that the last symbol is the equals sign), he passes json=''
as he does now.
Right now I'm inclining to agree with your proposal but want to check it again for controversy.
I don't like usage of None
as not for None
value but the absence of value at all.
On the other hand, I don't see a better solution.
Would you prepare a PR for review?
@asvetlov it could be a special constant:
# in yarl:
QUERY_KEY_WITHOUT_VALUE = object()
# in code:
from yarl import QUERY_KEY_WITHOUT_VALUE
url = URL('https://api.crowdin.com/api/project/{project-identifier}/pre-translate')
url = url.with_query(key=project_key, json=QUERY_KEY_WITHOUT_VALUE)
It's more obvious, but IMHO more ugly.
I can prepare a PR tomorrow.
Agree, a constant is worse than just None
urllib.parse.parse_qsl()
does not distinguish empty value from absent value:
>>> parse_qsl('a=b&c=', keep_blank_values=True)
[('a', 'b'), ('c', '')]
>>> parse_qsl('a=b&c', keep_blank_values=True)
[('a', 'b'), ('c', '')]
As well as it does not distinguish the &
separator from the ;
separator.
>>> parse_qsl('a=b&c=d')
[('a', 'b'), ('c', 'd')]
>>> parse_qsl('a=b;c=d')
[('a', 'b'), ('c', 'd')]
If you want to create a query with non-standard representation (parameters without =
, with the ;
separator instead of &
, or %-encoded characters which do not need to be encoded in norm, or using encoding different from UTF-8), you need to change directly the query_string
or even the raw_query_string
attributes, but not the query
dict.
url = url.with_query(key=project_key)
url = url.with_query(url.query_string + '&json')