1# This is a pytest hook that skips tests that tries to access the network.
2# These tests will immediately fail, then get marked as "Expected fail" (xfail).
3
4from _pytest.runner import pytest_runtest_makereport as orig_pytest_runtest_makereport
5
6# We use BaseException to minimize the chance it gets caught and 'pass'ed
7class NixNetworkAccessDeniedError(BaseException):
8 pass
9
10def pytest_runtest_makereport(item, call):
11 """
12 Modifies test results after-the-fact. The function name is magic, see:
13 https://docs.pytest.org/en/7.1.x/reference/reference.html?highlight=pytest_runtest_makereport#std-hook-pytest_runtest_makereport
14 """
15
16 def iterate_exc_chain(exc: Exception):
17 """
18 Recurses through exception chain, yielding all exceptions
19 """
20 yield exc
21 if getattr(exc, "__context__", None) is not None:
22 yield from iterate_exc_chain(exc.__context__)
23 if getattr(exc, "__cause__", None) is not None:
24 yield from iterate_exc_chain(exc.__cause__)
25
26 tr = orig_pytest_runtest_makereport(item, call)
27 if call.excinfo is not None:
28 for exc in iterate_exc_chain(call.excinfo.value):
29 if isinstance(exc, NixNetworkAccessDeniedError):
30 tr.outcome, tr.wasxfail = 'skipped', "reason: Requires network access."
31 if isinstance(exc, socket.gaierror):
32 tr.outcome, tr.wasxfail = 'skipped', "reason: Requires network access."
33 if isinstance(exc, httpx.ConnectError):
34 tr.outcome, tr.wasxfail = 'skipped', "reason: Requires network access."
35 if isinstance(exc, FileNotFoundError): # gradio specific
36 tr.outcome, tr.wasxfail = 'skipped', "reason: Pypi dist bad."
37 return tr
38
39# replace network access with exception
40
41def deny_network_access(*a, **kw):
42 raise NixNetworkAccessDeniedError
43
44import httpx
45import requests
46import socket
47import urllib
48import urllib3
49import websockets
50
51httpx.AsyncClient.get = deny_network_access
52httpx.AsyncClient.head = deny_network_access
53httpx.Request = deny_network_access
54requests.get = deny_network_access
55requests.head = deny_network_access
56requests.post = deny_network_access
57socket.socket.connect = deny_network_access
58urllib.request.Request = deny_network_access
59urllib.request.urlopen = deny_network_access
60urllib3.connection.HTTPSConnection._new_conn = deny_network_access
61websockets.connect = deny_network_access