nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: encode/httpx
Pull request #1045 (2020-07-02 17:14:16)

Add exceptions missing from top-level package
While working on #1044 I found out that some exceptions we define were not exposed at the `httpx` package level.

This PR fixes that, and adds a meta-test to ensure this won't happen again…

Refs #949 

(Note: in this PR I'm _tentatively_ adding `StreamError` to public API because right now we have it, but as per https://github.com/encode/httpx/issues/949#issuecomment-627945846 we can later decide to just drop it.)


Patch:
diff --git a/httpx/__init__.py b/httpx/__init__.py
index 35d5975..7a2b8a9 100644
--- a/httpx/__init__.py
+++ b/httpx/__init__.py
@@ -4,6 +4,8 @@ from ._auth import Auth, BasicAuth, DigestAuth
 from ._client import AsyncClient, Client
 from ._config import PoolLimits, Proxy, Timeout
 from ._exceptions import (
+    CloseError,
+    ConnectError,
     ConnectTimeout,
     CookieConflict,
     DecodingError,
@@ -14,13 +16,17 @@ from ._exceptions import (
     PoolTimeout,
     ProtocolError,
     ProxyError,
+    ReadError,
     ReadTimeout,
+    RedirectError,
     RequestBodyUnavailable,
     RequestNotRead,
     ResponseClosed,
     ResponseNotRead,
     StreamConsumed,
+    StreamError,
     TooManyRedirects,
+    WriteError,
     WriteTimeout,
 )
 from ._models import URL, Cookies, Headers, QueryParams, Request, Response
@@ -54,6 +60,8 @@ __all__ = [
     "PoolLimits",
     "Proxy",
     "Timeout",
+    "CloseError",
+    "ConnectError",
     "ConnectTimeout",
     "CookieConflict",
     "DecodingError",
@@ -63,14 +71,18 @@ __all__ = [
     "NotRedirectResponse",
     "PoolTimeout",
     "ProtocolError",
+    "ReadError",
     "ReadTimeout",
+    "RedirectError",
     "RequestBodyUnavailable",
     "ResponseClosed",
     "ResponseNotRead",
     "RequestNotRead",
     "StreamConsumed",
+    "StreamError",
     "ProxyError",
     "TooManyRedirects",
+    "WriteError",
     "WriteTimeout",
     "URL",
     "URLLib3Transport",


Test patch:
diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py
new file mode 100644
index 0000000..1ce71e8
--- /dev/null
+++ b/tests/test_exceptions.py
@@ -0,0 +1,21 @@
+import pytest
+
+import httpx
+
+
+def test_httpx_exceptions_exposed() -> None:
+    """
+    All exception classes defined in `httpx._exceptions`
+    are exposed as public API.
+    """
+
+    not_exposed = [
+        value
+        for name, value in vars(httpx._exceptions).items()
+        if isinstance(value, type)
+        and issubclass(value, Exception)
+        and not hasattr(httpx, name)
+    ]
+
+    if not_exposed:
+        pytest.fail(f"Unexposed HTTPX exceptions: {not_exposed}")
Repository: encode/httpx
Pull request #1055 (2020-07-07 08:16:55)

Add missing `Response.next()`
**Motivation**
`Response.next()` is documented in the [developer docs](https://www.python-httpx.org/api/#response) but did not actually exist yet.


Patch:
diff --git a/httpx/_models.py b/httpx/_models.py
index 8221e72..0437de1 100644
--- a/httpx/_models.py
+++ b/httpx/_models.py
@@ -943,6 +943,15 @@ class Response:
             yield part
         self.close()
 
+    def next(self) -> "Response":
+        """
+        Get the next response from a redirect response.
+        """
+        if not self.is_redirect:
+            raise NotRedirectResponse()
+        assert self.call_next is not None
+        return self.call_next()
+
     def close(self) -> None:
         """
         Close the response and release the connection.


Test patch:
diff --git a/tests/client/test_redirects.py b/tests/client/test_redirects.py
index dea1df2..ae800fa 100644
--- a/tests/client/test_redirects.py
+++ b/tests/client/test_redirects.py
@@ -310,7 +310,7 @@ def test_sync_too_many_redirects_calling_next():
     response = client.get(url, allow_redirects=False)
     with pytest.raises(TooManyRedirects):
         while response.is_redirect:
-            response = response.call_next()
+            response = response.next()
 
 
 @pytest.mark.usefixtures("async_environment")
Repository: encode/httpx
Pull request #1060 (2020-07-16 09:39:24)

Support QueryParams(None)
Ensures marginally more consistent behaviour, eg...

```python
# This will behave as expected.
client.params = None
```


Patch:
diff --git a/httpx/_client.py b/httpx/_client.py
index 35d0bd0..80a2bb0 100644
--- a/httpx/_client.py
+++ b/httpx/_client.py
@@ -73,9 +73,6 @@ class BaseClient:
         else:
             self.base_url = URL(base_url)
 
-        if params is None:
-            params = {}
-
         self.auth = auth
         self._params = QueryParams(params)
         self._headers = Headers(headers)
diff --git a/httpx/_models.py b/httpx/_models.py
index bf5f6d1..1ab162c 100644
--- a/httpx/_models.py
+++ b/httpx/_models.py
@@ -287,7 +287,7 @@ class QueryParams(typing.Mapping[str, str]):
         value = args[0] if args else kwargs
 
         items: typing.Sequence[typing.Tuple[str, PrimitiveData]]
-        if isinstance(value, str):
+        if value is None or isinstance(value, str):
             items = parse_qsl(value)
         elif isinstance(value, QueryParams):
             items = value.multi_items()
diff --git a/httpx/_types.py b/httpx/_types.py
index d2fc098..bfce565 100644
--- a/httpx/_types.py
+++ b/httpx/_types.py
@@ -34,6 +34,7 @@ QueryParamTypes = Union[
     Mapping[str, Union[PrimitiveData, Sequence[PrimitiveData]]],
     List[Tuple[str, PrimitiveData]],
     str,
+    None,
 ]
 
 HeaderTypes = Union[


Test patch:
diff --git a/tests/models/test_queryparams.py b/tests/models/test_queryparams.py
index 0b0101c..99f193f 100644
--- a/tests/models/test_queryparams.py
+++ b/tests/models/test_queryparams.py
@@ -44,6 +44,9 @@ def test_queryparams(source):
 
 
 def test_queryparam_types():
+    q = QueryParams(None)
+    assert str(q) == ""
+
     q = QueryParams({"a": True})
     assert str(q) == "a=true"
Repository: encode/httpx
Pull request #1074 (2020-07-21 09:22:36)

Skip HSTS preloading on single-label domains
As discussed in #1025, this is a simple fix to prevent HSTS on single-label domains like Docker hostnames, while a decision is made about if HSTS should be part of httpx or not.

I've added a separated unit test for this, that'll be easy to drop if it's not needed.

Cheers 👋


Patch:
diff --git a/httpx/_client.py b/httpx/_client.py
index dae1503..1ee9352 100644
--- a/httpx/_client.py
+++ b/httpx/_client.py
@@ -204,7 +204,11 @@ class BaseClient:
         to create the URL used for the outgoing request.
         """
         url = self.base_url.join(relative_url=url)
-        if url.scheme == "http" and hstspreload.in_hsts_preload(url.host):
+        if (
+            url.scheme == "http"
+            and hstspreload.in_hsts_preload(url.host)
+            and len(url.host.split(".")) > 1
+        ):
             port = None if url.port == 80 else url.port
             url = url.copy_with(scheme="https", port=port)
         return url


Test patch:
diff --git a/tests/client/test_client.py b/tests/client/test_client.py
index 40a5904..75384f2 100644
--- a/tests/client/test_client.py
+++ b/tests/client/test_client.py
@@ -162,3 +162,18 @@ def test_merge_url():
     request = client.build_request("GET", "http://www.paypal.com")
     assert request.url.scheme == "https"
     assert request.url.is_ssl
+
+
+@pytest.mark.parametrize(
+    "url,scheme,is_ssl",
+    [
+        ("http://www.paypal.com", "https", True),
+        ("http://app", "http", False),
+        ("http://192.168.1.42", "http", False),
+    ],
+)
+def test_merge_url_hsts(url: str, scheme: str, is_ssl: bool):
+    client = httpx.Client()
+    request = client.build_request("GET", url)
+    assert request.url.scheme == scheme
+    assert request.url.is_ssl == is_ssl