Skip to content

Commit 2c79732

Browse files
authored
Merge pull request #11 from justmobilize/esp32spi-and-wiznet5k-socketpool
Use new SocketPool for ESP32SPI and WIZNET5K
2 parents 2b5816d + b14ed99 commit 2c79732

7 files changed

+100
-46
lines changed

adafruit_connection_manager.py

+28-12
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ def __init__(self, socket: CircuitPythonSocketType, tls_mode: int) -> None:
5858
self.recv = socket.recv
5959
self.close = socket.close
6060
self.recv_into = socket.recv_into
61+
# For sockets that come from software socketpools (like the esp32api), they track
62+
# the interface and socket pool. We need to make sure the clones do as well
63+
self._interface = getattr(socket, "_interface", None)
64+
self._socket_pool = getattr(socket, "_socket_pool", None)
6165

6266
def connect(self, address: Tuple[str, int]) -> None:
6367
"""Connect wrapper to add non-standard mode parameter"""
@@ -94,7 +98,10 @@ def create_fake_ssl_context(
9498
* `Adafruit AirLift FeatherWing – ESP32 WiFi Co-Processor
9599
<https://www.adafruit.com/product/4264>`_
96100
"""
97-
socket_pool.set_interface(iface)
101+
if hasattr(socket_pool, "set_interface"):
102+
# this is to manually support legacy hardware like the fona
103+
socket_pool.set_interface(iface)
104+
98105
return _FakeSSLContext(iface)
99106

100107

@@ -104,6 +111,13 @@ def create_fake_ssl_context(
104111
_global_ssl_contexts = {}
105112

106113

114+
def _get_radio_hash_key(radio):
115+
try:
116+
return hash(radio)
117+
except TypeError:
118+
return radio.__class__.__name__
119+
120+
107121
def get_radio_socketpool(radio):
108122
"""Helper to get a socket pool for common boards.
109123
@@ -113,8 +127,9 @@ def get_radio_socketpool(radio):
113127
* Using the ESP32 WiFi Co-Processor (like the Adafruit AirLift)
114128
* Using a WIZ5500 (Like the Adafruit Ethernet FeatherWing)
115129
"""
116-
class_name = radio.__class__.__name__
117-
if class_name not in _global_socketpools:
130+
key = _get_radio_hash_key(radio)
131+
if key not in _global_socketpools:
132+
class_name = radio.__class__.__name__
118133
if class_name == "Radio":
119134
import ssl # pylint: disable=import-outside-toplevel
120135

@@ -124,12 +139,15 @@ def get_radio_socketpool(radio):
124139
ssl_context = ssl.create_default_context()
125140

126141
elif class_name == "ESP_SPIcontrol":
127-
import adafruit_esp32spi.adafruit_esp32spi_socket as pool # pylint: disable=import-outside-toplevel
142+
import adafruit_esp32spi.adafruit_esp32spi_socketpool as socketpool # pylint: disable=import-outside-toplevel
128143

144+
pool = socketpool.SocketPool(radio)
129145
ssl_context = create_fake_ssl_context(pool, radio)
130146

131147
elif class_name == "WIZNET5K":
132-
import adafruit_wiznet5k.adafruit_wiznet5k_socket as pool # pylint: disable=import-outside-toplevel
148+
import adafruit_wiznet5k.adafruit_wiznet5k_socketpool as socketpool # pylint: disable=import-outside-toplevel
149+
150+
pool = socketpool.SocketPool(radio)
133151

134152
# Note: At this time, SSL/TLS connections are not supported by older
135153
# versions of the Wiznet5k library or on boards withouut the ssl module
@@ -141,7 +159,6 @@ def get_radio_socketpool(radio):
141159
import ssl # pylint: disable=import-outside-toplevel
142160

143161
ssl_context = ssl.create_default_context()
144-
pool.set_interface(radio)
145162
except ImportError:
146163
# if SSL not on board, default to fake_ssl_context
147164
pass
@@ -152,11 +169,11 @@ def get_radio_socketpool(radio):
152169
else:
153170
raise AttributeError(f"Unsupported radio class: {class_name}")
154171

155-
_global_key_by_socketpool[pool] = class_name
156-
_global_socketpools[class_name] = pool
157-
_global_ssl_contexts[class_name] = ssl_context
172+
_global_key_by_socketpool[pool] = key
173+
_global_socketpools[key] = pool
174+
_global_ssl_contexts[key] = ssl_context
158175

159-
return _global_socketpools[class_name]
176+
return _global_socketpools[key]
160177

161178

162179
def get_radio_ssl_context(radio):
@@ -168,9 +185,8 @@ def get_radio_ssl_context(radio):
168185
* Using the ESP32 WiFi Co-Processor (like the Adafruit AirLift)
169186
* Using a WIZ5500 (Like the Adafruit Ethernet FeatherWing)
170187
"""
171-
class_name = radio.__class__.__name__
172188
get_radio_socketpool(radio)
173-
return _global_ssl_contexts[class_name]
189+
return _global_ssl_contexts[_get_radio_hash_key(radio)]
174190

175191

176192
# main class

tests/conftest.py

+46-20
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,31 @@
1010
import pytest
1111

1212

13-
# pylint: disable=unused-argument
14-
def set_interface(iface):
15-
"""Helper to set the global internet interface"""
13+
class SocketPool:
14+
name = None
15+
16+
def __init__(self, *args, **kwargs):
17+
pass
18+
19+
@property
20+
def __name__(self):
21+
return self.name
22+
23+
24+
class ESP32SPI_SocketPool(SocketPool): # pylint: disable=too-few-public-methods
25+
name = "adafruit_esp32spi_socketpool"
26+
27+
28+
class WIZNET5K_SocketPool(SocketPool): # pylint: disable=too-few-public-methods
29+
name = "adafruit_wiznet5k_socketpool"
30+
SOCK_STREAM = 0x21
31+
32+
33+
class WIZNET5K_With_SSL_SocketPool(
34+
SocketPool
35+
): # pylint: disable=too-few-public-methods
36+
name = "adafruit_wiznet5k_socketpool"
37+
SOCK_STREAM = 0x1
1638

1739

1840
@pytest.fixture
@@ -25,41 +47,45 @@ def circuitpython_socketpool_module():
2547

2648

2749
@pytest.fixture
28-
def adafruit_esp32spi_socket_module():
50+
def adafruit_esp32spi_socketpool_module():
2951
esp32spi_module = type(sys)("adafruit_esp32spi")
30-
esp32spi_socket_module = type(sys)("adafruit_esp32spi_socket")
31-
esp32spi_socket_module.set_interface = set_interface
52+
esp32spi_socket_module = type(sys)("adafruit_esp32spi_socketpool")
53+
esp32spi_socket_module.SocketPool = ESP32SPI_SocketPool
3254
sys.modules["adafruit_esp32spi"] = esp32spi_module
33-
sys.modules["adafruit_esp32spi.adafruit_esp32spi_socket"] = esp32spi_socket_module
55+
sys.modules["adafruit_esp32spi.adafruit_esp32spi_socketpool"] = (
56+
esp32spi_socket_module
57+
)
3458
yield
3559
del sys.modules["adafruit_esp32spi"]
36-
del sys.modules["adafruit_esp32spi.adafruit_esp32spi_socket"]
60+
del sys.modules["adafruit_esp32spi.adafruit_esp32spi_socketpool"]
3761

3862

3963
@pytest.fixture
40-
def adafruit_wiznet5k_socket_module():
64+
def adafruit_wiznet5k_socketpool_module():
4165
wiznet5k_module = type(sys)("adafruit_wiznet5k")
42-
wiznet5k_socket_module = type(sys)("adafruit_wiznet5k_socket")
43-
wiznet5k_socket_module.set_interface = set_interface
44-
wiznet5k_socket_module.SOCK_STREAM = 0x21
66+
wiznet5k_socketpool_module = type(sys)("adafruit_wiznet5k_socketpool")
67+
wiznet5k_socketpool_module.SocketPool = WIZNET5K_SocketPool
4568
sys.modules["adafruit_wiznet5k"] = wiznet5k_module
46-
sys.modules["adafruit_wiznet5k.adafruit_wiznet5k_socket"] = wiznet5k_socket_module
69+
sys.modules["adafruit_wiznet5k.adafruit_wiznet5k_socketpool"] = (
70+
wiznet5k_socketpool_module
71+
)
4772
yield
4873
del sys.modules["adafruit_wiznet5k"]
49-
del sys.modules["adafruit_wiznet5k.adafruit_wiznet5k_socket"]
74+
del sys.modules["adafruit_wiznet5k.adafruit_wiznet5k_socketpool"]
5075

5176

5277
@pytest.fixture
53-
def adafruit_wiznet5k_with_ssl_socket_module():
78+
def adafruit_wiznet5k_with_ssl_socketpool_module():
5479
wiznet5k_module = type(sys)("adafruit_wiznet5k")
55-
wiznet5k_socket_module = type(sys)("adafruit_wiznet5k_socket")
56-
wiznet5k_socket_module.set_interface = set_interface
57-
wiznet5k_socket_module.SOCK_STREAM = 1
80+
wiznet5k_socketpool_module = type(sys)("adafruit_wiznet5k_socketpool")
81+
wiznet5k_socketpool_module.SocketPool = WIZNET5K_With_SSL_SocketPool
5882
sys.modules["adafruit_wiznet5k"] = wiznet5k_module
59-
sys.modules["adafruit_wiznet5k.adafruit_wiznet5k_socket"] = wiznet5k_socket_module
83+
sys.modules["adafruit_wiznet5k.adafruit_wiznet5k_socketpool"] = (
84+
wiznet5k_socketpool_module
85+
)
6086
yield
6187
del sys.modules["adafruit_wiznet5k"]
62-
del sys.modules["adafruit_wiznet5k.adafruit_wiznet5k_socket"]
88+
del sys.modules["adafruit_wiznet5k.adafruit_wiznet5k_socketpool"]
6389

6490

6591
@pytest.fixture(autouse=True)

tests/connection_manager_close_all_test.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def test_connection_manager_close_all_untracked():
8888

8989

9090
def test_connection_manager_close_all_single_release_references_false( # pylint: disable=unused-argument
91-
circuitpython_socketpool_module, adafruit_esp32spi_socket_module
91+
circuitpython_socketpool_module, adafruit_esp32spi_socketpool_module
9292
):
9393
radio_wifi = mocket.MockRadio.Radio()
9494
radio_esp = mocket.MockRadio.ESP_SPIcontrol()
@@ -131,7 +131,7 @@ def test_connection_manager_close_all_single_release_references_false( # pylint
131131

132132

133133
def test_connection_manager_close_all_single_release_references_true( # pylint: disable=unused-argument
134-
circuitpython_socketpool_module, adafruit_esp32spi_socket_module
134+
circuitpython_socketpool_module, adafruit_esp32spi_socketpool_module
135135
):
136136
radio_wifi = mocket.MockRadio.Radio()
137137
radio_esp = mocket.MockRadio.ESP_SPIcontrol()

tests/get_connection_manager_test.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def test_get_connection_manager():
1919

2020

2121
def test_different_connection_manager_different_pool( # pylint: disable=unused-argument
22-
circuitpython_socketpool_module, adafruit_esp32spi_socket_module
22+
circuitpython_socketpool_module, adafruit_esp32spi_socketpool_module
2323
):
2424
radio_wifi = mocket.MockRadio.Radio()
2525
radio_esp = mocket.MockRadio.ESP_SPIcontrol()

tests/get_radio_test.py

+18-6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,18 @@
1313
import adafruit_connection_manager
1414

1515

16+
def test__get_radio_hash_key():
17+
radio = mocket.MockRadio.Radio()
18+
assert adafruit_connection_manager._get_radio_hash_key(radio) == hash(radio)
19+
20+
21+
def test__get_radio_hash_key_not_hashable():
22+
radio = mocket.MockRadio.Radio()
23+
24+
with mock.patch("builtins.hash", side_effect=TypeError()):
25+
assert adafruit_connection_manager._get_radio_hash_key(radio) == "Radio"
26+
27+
1628
def test_get_radio_socketpool_wifi( # pylint: disable=unused-argument
1729
circuitpython_socketpool_module,
1830
):
@@ -23,21 +35,21 @@ def test_get_radio_socketpool_wifi( # pylint: disable=unused-argument
2335

2436

2537
def test_get_radio_socketpool_esp32spi( # pylint: disable=unused-argument
26-
adafruit_esp32spi_socket_module,
38+
adafruit_esp32spi_socketpool_module,
2739
):
2840
radio = mocket.MockRadio.ESP_SPIcontrol()
2941
socket_pool = adafruit_connection_manager.get_radio_socketpool(radio)
30-
assert socket_pool.__name__ == "adafruit_esp32spi_socket"
42+
assert socket_pool.__name__ == "adafruit_esp32spi_socketpool"
3143
assert socket_pool in adafruit_connection_manager._global_socketpools.values()
3244

3345

3446
def test_get_radio_socketpool_wiznet5k( # pylint: disable=unused-argument
35-
adafruit_wiznet5k_socket_module,
47+
adafruit_wiznet5k_socketpool_module,
3648
):
3749
radio = mocket.MockRadio.WIZNET5K()
3850
with mock.patch("sys.implementation", return_value=[9, 0, 0]):
3951
socket_pool = adafruit_connection_manager.get_radio_socketpool(radio)
40-
assert socket_pool.__name__ == "adafruit_wiznet5k_socket"
52+
assert socket_pool.__name__ == "adafruit_wiznet5k_socketpool"
4153
assert socket_pool in adafruit_connection_manager._global_socketpools.values()
4254

4355

@@ -68,7 +80,7 @@ def test_get_radio_ssl_context_wifi( # pylint: disable=unused-argument
6880

6981

7082
def test_get_radio_ssl_context_esp32spi( # pylint: disable=unused-argument
71-
adafruit_esp32spi_socket_module,
83+
adafruit_esp32spi_socketpool_module,
7284
):
7385
radio = mocket.MockRadio.ESP_SPIcontrol()
7486
ssl_context = adafruit_connection_manager.get_radio_ssl_context(radio)
@@ -77,7 +89,7 @@ def test_get_radio_ssl_context_esp32spi( # pylint: disable=unused-argument
7789

7890

7991
def test_get_radio_ssl_context_wiznet5k( # pylint: disable=unused-argument
80-
adafruit_wiznet5k_socket_module,
92+
adafruit_wiznet5k_socketpool_module,
8193
):
8294
radio = mocket.MockRadio.WIZNET5K()
8395
with mock.patch("sys.implementation", return_value=[9, 0, 0]):

tests/get_socket_test.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ def test_get_socket_runtime_error_ties_again_only_once():
218218

219219

220220
def test_fake_ssl_context_connect( # pylint: disable=unused-argument
221-
adafruit_esp32spi_socket_module,
221+
adafruit_esp32spi_socketpool_module,
222222
):
223223
mock_pool = mocket.MocketPool()
224224
mock_socket_1 = mocket.Mocket()
@@ -237,7 +237,7 @@ def test_fake_ssl_context_connect( # pylint: disable=unused-argument
237237

238238

239239
def test_fake_ssl_context_connect_error( # pylint: disable=unused-argument
240-
adafruit_esp32spi_socket_module,
240+
adafruit_esp32spi_socketpool_module,
241241
):
242242
mock_pool = mocket.MocketPool()
243243
mock_socket_1 = mocket.Mocket()

tests/ssl_context_test.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616

1717
def test_connect_esp32spi_https( # pylint: disable=unused-argument
18-
adafruit_esp32spi_socket_module,
18+
adafruit_esp32spi_socketpool_module,
1919
):
2020
mock_pool = mocket.MocketPool()
2121
mock_socket_1 = mocket.Mocket()
@@ -48,7 +48,7 @@ def test_connect_wifi_https( # pylint: disable=unused-argument
4848

4949

5050
def test_connect_wiznet5k_https_not_supported( # pylint: disable=unused-argument
51-
adafruit_wiznet5k_socket_module,
51+
adafruit_wiznet5k_socketpool_module,
5252
):
5353
mock_pool = mocket.MocketPool()
5454
radio = mocket.MockRadio.WIZNET5K()
@@ -66,7 +66,7 @@ def test_connect_wiznet5k_https_not_supported( # pylint: disable=unused-argumen
6666

6767

6868
def test_connect_wiznet5k_https_supported( # pylint: disable=unused-argument
69-
adafruit_wiznet5k_with_ssl_socket_module,
69+
adafruit_wiznet5k_with_ssl_socketpool_module,
7070
):
7171
radio = mocket.MockRadio.WIZNET5K()
7272
with mock.patch("sys.implementation", (None, WIZNET5K_SSL_SUPPORT_VERSION)):

0 commit comments

Comments
 (0)