Hacktoberfest 2026:維護者為十月標記出來的 issue,仍然開放、適合新手。 瀏覽 Hacktoberfest issue

Replace unmaintained httpretty with mocket in the test suite

未關閉
#833 0 則留言 0 個 reaction 已指派 1 人 在 GitHub 檢視

@mconflitti-pbc 已經在處理了。

開始於 2026年8月7日。

評估

這個 Issue 還沒有評估資料。

描述

Problem

Adding Python 3.14 support required a shim in conftest.py, because httpretty
fails on 3.14. This ticket proposes removing that shim by replacing httpretty
with a maintained equivalent.

Root cause

CPython 3.14 makes functools.partial objects method descriptors. A
FutureWarning was added in 3.13 (python/cpython#121027) and the behavior
changed in 3.14 (python/cpython#125983):

3.13: class C: m = partial(f, "PRE")  ->  C().m("SOCK") == ("PRE", "SOCK")  + FutureWarning
3.14: class C: m = partial(f, "PRE")  ->  C().m("SOCK") == ("PRE", <C obj>, "SOCK")

httpretty mocks TLS with this class-attribute assignment
(httpretty/core.py:1875):

ssl.SSLContext.wrap_socket = partial(fake_wrap_socket, old_ssl_wrap_socket)

On 3.14 the partial now binds, so the SSLContext arrives as the first
positional argument and httpretty mistakes it for the socket. Every HTTPS test
fails with:

AttributeError: 'SSLContext' object has no attribute 'sendall'

That is 3 tests today (the shinyapps.io paths in tests/test_main.py), but it
affects the whole TLS mock, which covers over 100 https:// registrations.

Upstream will probably not fix this
  • gabrielfalcao/HTTPretty#488 ("Support Python 3.14 partial() changes", opened
    2026-04-10) fixes it with staticmethod(partial(...)), but is unmerged.
  • httpretty 1.1.4 was released 2021-08-16. The last merged PR was 2022-10-11.
    There are 129 open issues, with PRs from 2023 and 2024 still open. The PyPI
    classifiers stop at Python 3.9.
  • Even a released upstream fix may not help us: staticmethod objects only
    became callable in Python 3.10, so #488's two module-level assignments
    (ssl.wrap_socket and requests_urllib3_connection.ssl_wrap_socket) would
    break on our 3.8 and 3.9 floor if anything called them.
Current workaround

conftest.py wraps httpretty.core.fake_wrap_socket and drops the leading
SSLContext. It is 4 lines and verified on 3.8, 3.13 and 3.14, and it stays
correct if #488 lands (the isinstance check simply stops matching).

Its downside: it reads a private function at import time. If httpretty renames
fake_wrap_socket, the failure is not one red test. Collection fails and the
entire suite stops on every Python version and OS.

Proposal: migrate to mocket

mocket 3.14.3 (uploaded
2026-07-13) is actively maintained, declares requires-python = ">=3.8", and
classifies 3.8 through 3.14, so it covers our full support range. Its major
version tracks the newest supported Python.

Verified against rsconnect's real http.client HTTPS path on 3.14 using
mocket.plugins.httpretty: status 200 and the JSON body came back intact with
strict_mode=True.

Note the honest limits:

  • mocket monkeypatches socket and ssl too. This buys a maintainer, not real
    TLS. Only a real local server (for example pytest-httpserver) would give
    real TLS, at the cost of rewriting all registrations and adding certificate
    plumbing.
  • responses and requests-mock are not options. rsconnect uses http.client
    directly (rsconnect/http_support.py), not requests.
Migration scope

6 test files: test_api.py, test_main.py, test_main_content.py,
test_main_environment.py, test_main_integration.py,
test_main_system_caches.py.

Item Count Notes
@httpretty.activate(verbose=True, allow_net_connect=False) 81 becomes @mocketize(strict_mode=True); verbose has no equivalent
httpretty.register_uri(...) 165 body, adding_headers and status confirmed working
latest_requests() / last_request() 17 attributes in mocket, not calls; verify .method, .path, .body parity
has_request 1 no equivalent; needs a manual replacement

Acceptance criteria

  • The fake_wrap_socket shim is deleted from conftest.py.
  • The suite is green on Python 3.8 through 3.14.
  • Test count and skip count are unchanged (768 passed, 12 skipped today).
  • Line coverage does not regress (83.0% today).

Context

Closed #528 is where this repo deliberately adopted httpretty over
mock_connect, so that trade-off is worth re-reading before changing direction.

Separate pre-existing gap, unchanged by any of the above and out of scope here:
the custom-CA branch (ssl.create_default_context(cadata=...)) and the
--insecure branch (ssl._create_unverified_context()) in
rsconnect/http_support.py are not covered by the httpretty tests on any
Python version.

主要語言
Python
星號
37
分支
28
平均合併
1 天 3 小時
30 天內合併 PR
7

環境準備

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

posit-dev/rsconnect-python 的其他 Issue

查看 posit-dev/rsconnect-python 的全部 Issue

相似的 Issue

更多 Python Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。