@@ -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
@@ -251,6 +252,19 @@ def __exit__(self, exc_type, exc_val, exc_tb) -> None:
251
252
if time .monotonic () - stamp > 1000 :
252
253
raise RuntimeError ("Failed to close socket" )
253
254
255
+ # This works around problems with using a method as a decorator.
256
+ def _check_socket_closed (func ): # pylint: disable=no-self-argument
257
+ """Decorator to check whether the socket object has been closed."""
258
+
259
+ def wrapper (self , * args , ** kwargs ):
260
+ if self ._socket_closed : # pylint: disable=protected-access
261
+ raise RuntimeError ("The socket has been closed." )
262
+ print (* args )
263
+ print (** kwargs )
264
+ return func (self , * args , ** kwargs ) # pylint: disable=not-callable
265
+
266
+ return wrapper
267
+
254
268
@property
255
269
def _status (self ) -> int :
256
270
"""
@@ -288,6 +302,7 @@ def _connected(self) -> bool:
288
302
self .close ()
289
303
return result
290
304
305
+ @_check_socket_closed
291
306
def getpeername (self ) -> Tuple [str , int ]:
292
307
"""
293
308
Return the remote address to which the socket is connected.
@@ -298,6 +313,7 @@ def getpeername(self) -> Tuple[str, int]:
298
313
self ._socknum
299
314
)
300
315
316
+ @_check_socket_closed
301
317
def bind (self , address : Tuple [Optional [str ], int ]) -> None :
302
318
"""
303
319
Bind the socket to address. The socket must not already be bound.
@@ -343,6 +359,7 @@ def _bind(self, address: Tuple[Optional[str], int]) -> None:
343
359
)
344
360
self ._buffer = b""
345
361
362
+ @_check_socket_closed
346
363
def listen (self , backlog : int = 0 ) -> None :
347
364
"""
348
365
Enable a server to accept connections.
@@ -354,6 +371,7 @@ def listen(self, backlog: int = 0) -> None:
354
371
_the_interface .socket_listen (self ._socknum , self ._listen_port )
355
372
self ._buffer = b""
356
373
374
+ @_check_socket_closed
357
375
def accept (
358
376
self ,
359
377
) -> Tuple [socket , Tuple [str , int ]]:
@@ -388,6 +406,7 @@ def accept(
388
406
raise RuntimeError ("Failed to open new listening socket" )
389
407
return client_sock , addr
390
408
409
+ @_check_socket_closed
391
410
def connect (self , address : Tuple [str , int ]) -> None :
392
411
"""
393
412
Connect to a remote socket at address.
@@ -407,6 +426,7 @@ def connect(self, address: Tuple[str, int]) -> None:
407
426
raise RuntimeError ("Failed to connect to host " , address [0 ])
408
427
self ._buffer = b""
409
428
429
+ @_check_socket_closed
410
430
def send (self , data : Union [bytes , bytearray ]) -> int :
411
431
"""
412
432
Send data to the socket. The socket must be connected to a remote socket.
@@ -422,6 +442,7 @@ def send(self, data: Union[bytes, bytearray]) -> int:
422
442
gc .collect ()
423
443
return bytes_sent
424
444
445
+ @_check_socket_closed
425
446
def sendto (self , data : bytearray , * flags_and_or_address : any ) -> int :
426
447
"""
427
448
Send data to the socket. The socket should not be connected to a remote socket, since the
@@ -445,6 +466,7 @@ def sendto(self, data: bytearray, *flags_and_or_address: any) -> int:
445
466
self .connect (address )
446
467
return self .send (data )
447
468
469
+ @_check_socket_closed
448
470
def recv (
449
471
# pylint: disable=too-many-branches
450
472
self ,
@@ -500,6 +522,7 @@ def _embed_recv(
500
522
gc .collect ()
501
523
return ret
502
524
525
+ @_check_socket_closed
503
526
def recvfrom (self , bufsize : int , flags : int = 0 ) -> Tuple [bytes , Tuple [str , int ]]:
504
527
"""
505
528
Receive data from the socket. The return value is a pair (bytes, address) where bytes is
@@ -520,6 +543,7 @@ def recvfrom(self, bufsize: int, flags: int = 0) -> Tuple[bytes, Tuple[str, int]
520
543
),
521
544
)
522
545
546
+ @_check_socket_closed
523
547
def recv_into (self , buffer : bytearray , nbytes : int = 0 , flags : int = 0 ) -> int :
524
548
"""
525
549
Receive up to nbytes bytes from the socket, storing the data into a buffer
@@ -538,6 +562,7 @@ def recv_into(self, buffer: bytearray, nbytes: int = 0, flags: int = 0) -> int:
538
562
buffer [:nbytes ] = bytes_received
539
563
return nbytes
540
564
565
+ @_check_socket_closed
541
566
def recvfrom_into (
542
567
self , buffer : bytearray , nbytes : int = 0 , flags : int = 0
543
568
) -> Tuple [int , Tuple [str , int ]]:
@@ -596,11 +621,13 @@ def _disconnect(self) -> None:
596
621
raise RuntimeError ("Socket must be a TCP socket." )
597
622
_the_interface .socket_disconnect (self ._socknum )
598
623
624
+ @_check_socket_closed
599
625
def close (self ) -> None :
600
626
"""
601
627
Mark the socket closed. Once that happens, all future operations on the socket object
602
628
will fail. The remote end will receive no more data.
603
629
"""
630
+ self ._socket_closed = True
604
631
_the_interface .socket_close (self ._socknum )
605
632
606
633
def _available (self ) -> int :
@@ -611,6 +638,7 @@ def _available(self) -> int:
611
638
"""
612
639
return _the_interface .socket_available (self ._socknum , self ._sock_type )
613
640
641
+ @_check_socket_closed
614
642
def settimeout (self , value : Optional [float ]) -> None :
615
643
"""
616
644
Set a timeout on blocking socket operations. The value argument can be a
@@ -627,6 +655,7 @@ def settimeout(self, value: Optional[float]) -> None:
627
655
else :
628
656
raise ValueError ("Timeout must be None, 0.0 or a positive numeric value." )
629
657
658
+ @_check_socket_closed
630
659
def gettimeout (self ) -> Optional [float ]:
631
660
"""
632
661
Return the timeout in seconds (float) associated with socket operations, or None if no
@@ -636,6 +665,7 @@ def gettimeout(self) -> Optional[float]:
636
665
"""
637
666
return self ._timeout
638
667
668
+ @_check_socket_closed
639
669
def setblocking (self , flag : bool ) -> None :
640
670
"""
641
671
Set blocking or non-blocking mode of the socket: if flag is false, the socket is set
@@ -658,6 +688,7 @@ def setblocking(self, flag: bool) -> None:
658
688
else :
659
689
raise TypeError ("Flag must be a boolean." )
660
690
691
+ @_check_socket_closed
661
692
def getblocking (self ) -> bool :
662
693
"""
663
694
Return True if socket is in blocking mode, False if in non-blocking.
@@ -668,16 +699,19 @@ def getblocking(self) -> bool:
668
699
"""
669
700
return self .gettimeout () == 0
670
701
702
+ @_check_socket_closed
671
703
@property
672
704
def family (self ) -> int :
673
705
"""Socket family (always 0x03 in this implementation)."""
674
706
return 3
675
707
708
+ @_check_socket_closed
676
709
@property
677
710
def type (self ):
678
711
"""Socket type."""
679
712
return self ._sock_type
680
713
714
+ @_check_socket_closed
681
715
@property
682
716
def proto (self ):
683
717
"""Socket protocol (always 0x00 in this implementation)."""
0 commit comments