@@ -226,6 +226,7 @@ def __init__(
226
226
"""
227
227
if family != AF_INET :
228
228
raise RuntimeError ("Only AF_INET family supported by W5K modules." )
229
+ self ._socket_closed = False
229
230
self ._sock_type = type
230
231
self ._buffer = b""
231
232
self ._timeout = _default_socket_timeout
@@ -255,6 +256,17 @@ def __exit__(self, exc_type, exc_val, exc_tb) -> None:
255
256
if time .monotonic () - stamp > 1000 :
256
257
raise RuntimeError ("Failed to close socket" )
257
258
259
+ # This works around problems with using a class method as a decorator.
260
+ def _check_socket_closed (func ): # pylint: disable=no-self-argument
261
+ """Decorator to check whether the socket object has been closed."""
262
+
263
+ def wrapper (self , * args , ** kwargs ):
264
+ if self ._socket_closed : # pylint: disable=protected-access
265
+ raise RuntimeError ("The socket has been closed." )
266
+ return func (self , * args , ** kwargs ) # pylint: disable=not-callable
267
+
268
+ return wrapper
269
+
258
270
@property
259
271
def _status (self ) -> int :
260
272
"""
@@ -292,6 +304,7 @@ def _connected(self) -> bool:
292
304
self .close ()
293
305
return result
294
306
307
+ @_check_socket_closed
295
308
def getpeername (self ) -> Tuple [str , int ]:
296
309
"""
297
310
Return the remote address to which the socket is connected.
@@ -302,6 +315,7 @@ def getpeername(self) -> Tuple[str, int]:
302
315
self ._socknum
303
316
)
304
317
318
+ @_check_socket_closed
305
319
def bind (self , address : Tuple [Optional [str ], int ]) -> None :
306
320
"""
307
321
Bind the socket to address. The socket must not already be bound.
@@ -347,6 +361,7 @@ def _bind(self, address: Tuple[Optional[str], int]) -> None:
347
361
)
348
362
self ._buffer = b""
349
363
364
+ @_check_socket_closed
350
365
def listen (self , backlog : int = 0 ) -> None :
351
366
"""
352
367
Enable a server to accept connections.
@@ -358,6 +373,7 @@ def listen(self, backlog: int = 0) -> None:
358
373
_the_interface .socket_listen (self ._socknum , self ._listen_port )
359
374
self ._buffer = b""
360
375
376
+ @_check_socket_closed
361
377
def accept (
362
378
self ,
363
379
) -> Tuple [socket , Tuple [str , int ]]:
@@ -392,6 +408,7 @@ def accept(
392
408
raise RuntimeError ("Failed to open new listening socket" )
393
409
return client_sock , addr
394
410
411
+ @_check_socket_closed
395
412
def connect (self , address : Tuple [str , int ]) -> None :
396
413
"""
397
414
Connect to a remote socket at address.
@@ -411,6 +428,7 @@ def connect(self, address: Tuple[str, int]) -> None:
411
428
raise RuntimeError ("Failed to connect to host " , address [0 ])
412
429
self ._buffer = b""
413
430
431
+ @_check_socket_closed
414
432
def send (self , data : Union [bytes , bytearray ]) -> int :
415
433
"""
416
434
Send data to the socket. The socket must be connected to a remote socket.
@@ -426,6 +444,7 @@ def send(self, data: Union[bytes, bytearray]) -> int:
426
444
gc .collect ()
427
445
return bytes_sent
428
446
447
+ @_check_socket_closed
429
448
def sendto (self , data : bytearray , * flags_and_or_address : any ) -> int :
430
449
"""
431
450
Send data to the socket. The socket should not be connected to a remote socket, since the
@@ -449,6 +468,7 @@ def sendto(self, data: bytearray, *flags_and_or_address: any) -> int:
449
468
self .connect (address )
450
469
return self .send (data )
451
470
471
+ @_check_socket_closed
452
472
def recv (
453
473
# pylint: disable=too-many-branches
454
474
self ,
@@ -504,6 +524,7 @@ def _embed_recv(
504
524
gc .collect ()
505
525
return ret
506
526
527
+ @_check_socket_closed
507
528
def recvfrom (self , bufsize : int , flags : int = 0 ) -> Tuple [bytes , Tuple [str , int ]]:
508
529
"""
509
530
Receive data from the socket. The return value is a pair (bytes, address) where bytes is
@@ -524,6 +545,7 @@ def recvfrom(self, bufsize: int, flags: int = 0) -> Tuple[bytes, Tuple[str, int]
524
545
),
525
546
)
526
547
548
+ @_check_socket_closed
527
549
def recv_into (self , buffer : bytearray , nbytes : int = 0 , flags : int = 0 ) -> int :
528
550
"""
529
551
Receive up to nbytes bytes from the socket, storing the data into a buffer
@@ -542,6 +564,7 @@ def recv_into(self, buffer: bytearray, nbytes: int = 0, flags: int = 0) -> int:
542
564
buffer [:nbytes ] = bytes_received
543
565
return nbytes
544
566
567
+ @_check_socket_closed
545
568
def recvfrom_into (
546
569
self , buffer : bytearray , nbytes : int = 0 , flags : int = 0
547
570
) -> Tuple [int , Tuple [str , int ]]:
@@ -600,13 +623,15 @@ def _disconnect(self) -> None:
600
623
raise RuntimeError ("Socket must be a TCP socket." )
601
624
_the_interface .socket_disconnect (self ._socknum )
602
625
626
+ @_check_socket_closed
603
627
def close (self ) -> None :
604
628
"""
605
629
Mark the socket closed. Once that happens, all future operations on the socket object
606
630
will fail. The remote end will receive no more data.
607
631
"""
608
632
_the_interface .release_socket (self ._socknum )
609
633
_the_interface .socket_close (self ._socknum )
634
+ self ._socket_closed = True
610
635
611
636
def _available (self ) -> int :
612
637
"""
@@ -616,6 +641,7 @@ def _available(self) -> int:
616
641
"""
617
642
return _the_interface .socket_available (self ._socknum , self ._sock_type )
618
643
644
+ @_check_socket_closed
619
645
def settimeout (self , value : Optional [float ]) -> None :
620
646
"""
621
647
Set a timeout on blocking socket operations. The value argument can be a
@@ -632,6 +658,7 @@ def settimeout(self, value: Optional[float]) -> None:
632
658
else :
633
659
raise ValueError ("Timeout must be None, 0.0 or a positive numeric value." )
634
660
661
+ @_check_socket_closed
635
662
def gettimeout (self ) -> Optional [float ]:
636
663
"""
637
664
Return the timeout in seconds (float) associated with socket operations, or None if no
@@ -641,6 +668,7 @@ def gettimeout(self) -> Optional[float]:
641
668
"""
642
669
return self ._timeout
643
670
671
+ @_check_socket_closed
644
672
def setblocking (self , flag : bool ) -> None :
645
673
"""
646
674
Set blocking or non-blocking mode of the socket: if flag is false, the socket is set
@@ -663,6 +691,7 @@ def setblocking(self, flag: bool) -> None:
663
691
else :
664
692
raise TypeError ("Flag must be a boolean." )
665
693
694
+ @_check_socket_closed
666
695
def getblocking (self ) -> bool :
667
696
"""
668
697
Return True if socket is in blocking mode, False if in non-blocking.
@@ -674,16 +703,19 @@ def getblocking(self) -> bool:
674
703
return self .gettimeout () == 0
675
704
676
705
@property
706
+ @_check_socket_closed
677
707
def family (self ) -> int :
678
708
"""Socket family (always 0x03 in this implementation)."""
679
709
return 3
680
710
681
711
@property
712
+ @_check_socket_closed
682
713
def type (self ):
683
714
"""Socket type."""
684
715
return self ._sock_type
685
716
686
717
@property
718
+ @_check_socket_closed
687
719
def proto (self ):
688
720
"""Socket protocol (always 0x00 in this implementation)."""
689
721
return 0
0 commit comments