Repository: encode/httpx (branch: add-ssl-context-argument)
Commit date: 2024-01-16T05:40:47Z

Workflow file: .github/workflows/test-suite.yml (Test Suite)
---
name: Test Suite

on:
  push:
    branches: ["master"]
  pull_request:
    branches: ["master"]

jobs:
  tests:
    name: "Python ${{ matrix.python-version }}"
    runs-on: "ubuntu-latest"
    services:
      pypi_wayback:
        image: ghcr.io/waleko/pypi-wayback
        ports:
          - 8629:8080

    strategy:
      matrix:
        python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]

    steps:
      - uses: "actions/checkout@v4"
      - uses: "actions/setup-python@v5"
        with:
          python-version: "${{ matrix.python-version }}"
          allow-prereleases: true
      - name: "Install dependencies"
        run: "scripts/install"
      - name: "Run linting checks"
        run: "scripts/check"
      - name: "Build package & docs"
        run: "scripts/build"
      - name: "Run tests"
        run: "scripts/test"
      - name: "Enforce coverage"
        run: "scripts/coverage"

env:
  PIP_INDEX_URL: http://localhost:8629/2024-01-16
  UV_INDEX_URL: http://localhost:8629/2024-01-16


Failed build logs:
step_name: Python 3.8/8_Enforce coverage.txt
log: ##[group]Run scripts/coverage
[36;1mscripts/coverage[0m
shell: /usr/bin/bash -e {0}
env:
  pythonLocation: /opt/hostedtoolcache/Python/3.8.18/x64
  PKG_CONFIG_PATH: /opt/hostedtoolcache/Python/3.8.18/x64/lib/pkgconfig
  Python_ROOT_DIR: /opt/hostedtoolcache/Python/3.8.18/x64
  Python2_ROOT_DIR: /opt/hostedtoolcache/Python/3.8.18/x64
  Python3_ROOT_DIR: /opt/hostedtoolcache/Python/3.8.18/x64
  LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.8.18/x64/lib
##[endgroup]
+ coverage report --show-missing --skip-covered --fail-under=100
Name               Stmts   Miss  Cover   Missing
------------------------------------------------
httpx/_config.py     133      1    99%   139
------------------------------------------------
TOTAL               7570      1    99%

58 files skipped due to complete coverage.
Coverage failure: total of 99 is less than fail-under=100
##[error]Process completed with exit code 2.

step_name: Python 3.9/8_Enforce coverage.txt
log: ##[group]Run scripts/coverage
[36;1mscripts/coverage[0m
shell: /usr/bin/bash -e {0}
env:
  pythonLocation: /opt/hostedtoolcache/Python/3.9.18/x64
  PKG_CONFIG_PATH: /opt/hostedtoolcache/Python/3.9.18/x64/lib/pkgconfig
  Python_ROOT_DIR: /opt/hostedtoolcache/Python/3.9.18/x64
  Python2_ROOT_DIR: /opt/hostedtoolcache/Python/3.9.18/x64
  Python3_ROOT_DIR: /opt/hostedtoolcache/Python/3.9.18/x64
  LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.9.18/x64/lib
##[endgroup]
+ coverage report --show-missing --skip-covered --fail-under=100
Name               Stmts   Miss  Cover   Missing
------------------------------------------------
httpx/_config.py     133      1    99%   139
------------------------------------------------
TOTAL               7570      1    99%

58 files skipped due to complete coverage.
Coverage failure: total of 99 is less than fail-under=100
##[error]Process completed with exit code 2.

step_name: Python 3.10/8_Enforce coverage.txt
log: ##[group]Run scripts/coverage
[36;1mscripts/coverage[0m
shell: /usr/bin/bash -e {0}
env:
  pythonLocation: /opt/hostedtoolcache/Python/3.10.13/x64
  PKG_CONFIG_PATH: /opt/hostedtoolcache/Python/3.10.13/x64/lib/pkgconfig
  Python_ROOT_DIR: /opt/hostedtoolcache/Python/3.10.13/x64
  Python2_ROOT_DIR: /opt/hostedtoolcache/Python/3.10.13/x64
  Python3_ROOT_DIR: /opt/hostedtoolcache/Python/3.10.13/x64
  LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.10.13/x64/lib
##[endgroup]
+ coverage report --show-missing --skip-covered --fail-under=100
Name               Stmts   Miss  Cover   Missing
------------------------------------------------
httpx/_config.py     133      1    99%   139
------------------------------------------------
TOTAL               7577      1    99%

58 files skipped due to complete coverage.
Coverage failure: total of 99 is less than fail-under=100
##[error]Process completed with exit code 2.

step_name: Python 3.11/8_Enforce coverage.txt
log: ##[group]Run scripts/coverage
[36;1mscripts/coverage[0m
shell: /usr/bin/bash -e {0}
env:
  pythonLocation: /opt/hostedtoolcache/Python/3.11.7/x64
  PKG_CONFIG_PATH: /opt/hostedtoolcache/Python/3.11.7/x64/lib/pkgconfig
  Python_ROOT_DIR: /opt/hostedtoolcache/Python/3.11.7/x64
  Python2_ROOT_DIR: /opt/hostedtoolcache/Python/3.11.7/x64
  Python3_ROOT_DIR: /opt/hostedtoolcache/Python/3.11.7/x64
  LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.11.7/x64/lib
##[endgroup]
+ coverage report --show-missing --skip-covered --fail-under=100
Name               Stmts   Miss  Cover   Missing
------------------------------------------------
httpx/_config.py     133      1    99%   139
------------------------------------------------
TOTAL               7577      1    99%

58 files skipped due to complete coverage.
Coverage failure: total of 99 is less than fail-under=100
##[error]Process completed with exit code 2.


Changed files:
docs/advanced/ssl.md
httpx/_config.py
tests/test_config.py

Fix diff:
diff --git a/docs/advanced/ssl.md b/docs/advanced/ssl.md
index 1eec32f..2c3e679 100644
--- a/docs/advanced/ssl.md
+++ b/docs/advanced/ssl.md
@@ -14,7 +14,7 @@ You can configure the verification using `httpx.SSLContext()`.
 ```pycon
 >>> ssl_context = httpx.SSLContext()
 >>> ssl_context
-<SSLContext [verify=True]>
+SSLContext(verify=True)
 >>> httpx.get("https://www.example.com", ssl_context=ssl_context)
 httpx.ConnectError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired (_ssl.c:997)
 ```
@@ -24,7 +24,7 @@ For example, you can use this to disable verification completely and allow insec
 ```pycon
 >>> no_verify = httpx.SSLContext(verify=False)
 >>> no_verify
-<SSLContext [verify=False]>
+SSLContext(verify=False)
 >>> httpx.get("https://expired.badssl.com/", ssl_context=no_verify)
 <Response [200 OK]>
 ```
diff --git a/httpx/_config.py b/httpx/_config.py
index 303388d..8cfeea7 100644
--- a/httpx/_config.py
+++ b/httpx/_config.py
@@ -136,7 +136,9 @@ class SSLContext(ssl.SSLContext):
                 )
 
     def __repr__(self) -> str:
-        return f"<SSLContext [verify={self.verify}]>"
+        class_name = self.__class__.__name__
+
+        return f"{class_name}(verify={self.verify!r})"
 
     def __new__(
         cls,
diff --git a/tests/test_config.py b/tests/test_config.py
index 530b150..b39efa8 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -74,6 +74,16 @@ def test_SSLContext_with_get_request(server, cert_pem_file):
     assert response.status_code == 200
 
 
+def test_SSLContext_repr():
+    ssl_context = httpx.SSLContext()
+
+    assert repr(ssl_context) == "SSLContext(verify=True)"
+
+    ssl_context = httpx.SSLContext(verify=certifi.where())
+
+    assert repr(ssl_context) == "SSLContext(verify='{}')".format(certifi.where())
+
+
 def test_limits_repr():
     limits = httpx.Limits(max_connections=100)
     expected = (