diff --git a/CHANGES/1256.misc.rst b/CHANGES/1256.misc.rst new file mode 100644 index 000000000..d931dacfc --- /dev/null +++ b/CHANGES/1256.misc.rst @@ -0,0 +1 @@ +Improved performance of constructing query strings from :class:`~multidict.MultiDict` -- by :user:`bdraco`. diff --git a/yarl/_url.py b/yarl/_url.py index 99fc90812..abc926414 100644 --- a/yarl/_url.py +++ b/yarl/_url.py @@ -1263,16 +1263,20 @@ def _get_str_query_from_sequence_iterable( """ quoter = self._QUERY_PART_QUOTER pairs = [ - f"{quoter(k)}={quoter(self._query_var(v))}" + f"{quoter(k)}={quoter(v if type(v) is str else self._query_var(v))}" for k, val in items - for v in (val if isinstance(val, (list, tuple)) else (val,)) + for v in ( + val + if type(val) is not str and isinstance(val, (list, tuple)) + else (val,) + ) ] return "&".join(pairs) @staticmethod def _query_var(v: QueryVariable) -> str: cls = type(v) - if cls is str or issubclass(cls, str): + if issubclass(cls, str): if TYPE_CHECKING: assert isinstance(v, str) return v @@ -1305,7 +1309,11 @@ def _get_str_query_from_iterable( quoter = self._QUERY_PART_QUOTER # A listcomp is used since listcomps are inlined on CPython 3.12+ and # they are a bit faster than a generator expression. - return "&".join([f"{quoter(k)}={quoter(self._query_var(v))}" for k, v in items]) + pairs = [ + f"{quoter(k)}={quoter(v if type(v) is str else self._query_var(v))}" + for k, v in items + ] + return "&".join(pairs) def _get_str_query(self, *args: Any, **kwargs: Any) -> Union[str, None]: query: Union[str, Mapping[str, QueryVariable], None]