Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGES/1458.doc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Documented that objects implementing :class:`~typing.SupportsInt` (such as
:class:`uuid.UUID`) are converted to :class:`int` when used as query parameter
values, and that explicit conversion to :class:`str` is needed if the string
representation is desired -- by :user:`edvatar`.
19 changes: 19 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,25 @@ section generates a new :class:`URL` instance.
Please see :ref:`yarl-bools-support` for the reason why :class:`bool` is not
supported out-of-the-box.

.. warning::

Any object implementing :class:`~typing.SupportsInt` (i.e. having an
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, this protocol has been a part of the data model long before typing was a thing: https://docs.python.org/2.0/ref/numeric-types.html. It's rather a part of the data model that is also additionally represented in typing, not vice versa.

``__int__`` method) will be converted to :class:`int` before being used
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method can actually be linked:

Suggested change
``__int__`` method) will be converted to :class:`int` before being used
:external+python:meth:`~object.__int__` method) will be converted to :class:`int` before being used

as a query parameter value. This includes types such as :class:`uuid.UUID`,
which will be converted to their integer representation rather than their
string representation. To avoid unexpected results, explicitly convert such
values to :class:`str` before passing them as query parameters:

.. code-block:: python

import uuid

my_uuid = uuid.UUID("3199712f-1b78-4420-852b-a73ee09e6a8f")
# Wrong: will use int(my_uuid) -> a large integer
url = URL("http://example.com/").with_query({"id": my_uuid})
# Correct: explicitly convert to string
url = URL("http://example.com/").with_query({"id": str(my_uuid)})

.. doctest::

>>> URL('http://example.com/path?a=b').with_query('c=d')
Expand Down
7 changes: 6 additions & 1 deletion yarl/_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@


def query_var(v: SimpleQuery) -> str:
"""Convert a query variable to a string."""
"""Convert a query variable to a string.

Note: Objects implementing ``SupportsInt`` (e.g. ``uuid.UUID``) will be
converted via ``int()`` first. Callers should convert such values to ``str``
explicitly if the string representation is desired.
"""
cls = type(v)
if cls is int: # Fast path for non-subclassed int
return str(v)
Expand Down
Loading