Skip to content
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

Support building query without values #307

Open
rominf opened this issue May 8, 2019 · 4 comments
Open

Support building query without values #307

rominf opened this issue May 8, 2019 · 4 comments

Comments

@rominf
Copy link
Contributor

rominf commented May 8, 2019

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.

@rominf rominf changed the title Support building query with empty values Support building query without values May 8, 2019
@asvetlov
Copy link
Member

asvetlov commented May 8, 2019

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?

@rominf
Copy link
Contributor Author

rominf commented May 8, 2019

@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.

@asvetlov
Copy link
Member

asvetlov commented May 8, 2019

Agree, a constant is worse than just None

@serhiy-storchaka
Copy link
Contributor

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')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants