22
33from enum import Enum , auto
44import sys
5- from typing import List
5+ from typing import List , Optional
66
77import circuitpython_typing
88
1717 SPITransfer ,
1818)
1919from circuitpython_mocks ._mixins import Expecting , Lockable
20- from circuitpython_mocks .board import Pin
20+ from circuitpython_mocks .board import (
21+ Pin ,
22+ SDA ,
23+ SDA1 ,
24+ SCL ,
25+ SCL1 ,
26+ SCK ,
27+ MOSI as PinMOSI ,
28+ MISO as PinMISO ,
29+ TX ,
30+ RX ,
31+ MISO_1 ,
32+ MOSI_1 ,
33+ SCK_1 ,
34+ )
2135
2236
2337class I2C (Expecting , Lockable ):
24- """A mock of `busio.I2C` class."""
38+ """A mock of :external:py:class:`busio.I2C` class."""
39+
40+ _primary_singleton : Optional ["I2C" ] = None
41+ _secondary_singleton : Optional ["I2C" ] = None
42+
43+ def __new__ (cls , scl : Pin , sda : Pin , ** kwargs ) -> "I2C" :
44+ if scl == SCL and sda == SDA :
45+ if cls ._primary_singleton is None :
46+ cls ._primary_singleton = super ().__new__ (cls )
47+ return cls ._primary_singleton
48+ if scl == SCL1 and sda == SDA1 :
49+ if cls ._secondary_singleton is None :
50+ cls ._secondary_singleton = super ().__new__ (cls )
51+ return cls ._secondary_singleton
52+ return super ().__new__ (cls )
2553
2654 def __init__ (
2755 self ,
@@ -31,6 +59,8 @@ def __init__(
3159 frequency : int = 100000 ,
3260 timeout : int = 255 ,
3361 ):
62+ if hasattr (self , "expectations" ):
63+ return
3464 super ().__init__ ()
3565
3666 def scan (self ) -> List [int ]:
@@ -99,6 +129,22 @@ def writeto_then_readfrom(
99129
100130
101131class SPI (Expecting , Lockable ):
132+ """A mock of :external:py:class:`busio.SPI` class."""
133+
134+ _primary_singleton : Optional ["SPI" ] = None
135+ _secondary_singleton : Optional ["SPI" ] = None
136+
137+ def __new__ (cls , clock : Pin , MOSI : Pin , MISO : Pin , ** kwargs ) -> "SPI" :
138+ if clock == SCK and MOSI == PinMOSI and MISO == PinMISO :
139+ if cls ._primary_singleton is None :
140+ cls ._primary_singleton = super ().__new__ (cls )
141+ return cls ._primary_singleton
142+ if clock == SCK_1 and MOSI == MOSI_1 and MISO == MISO_1 :
143+ if cls ._secondary_singleton is None :
144+ cls ._secondary_singleton = super ().__new__ (cls )
145+ return cls ._secondary_singleton
146+ return super ().__new__ (cls )
147+
102148 def __init__ (
103149 self ,
104150 clock : Pin ,
@@ -183,6 +229,15 @@ def write_readinto(
183229class UART (Expecting , Lockable ):
184230 """A class that mocks :external:py:class:`busio.UART`."""
185231
232+ _primary_singleton : Optional ["UART" ] = None
233+
234+ def __new__ (cls , tx : Pin , rx : Pin , ** kwargs ) -> "UART" :
235+ if tx == TX and rx == RX :
236+ if cls ._primary_singleton is None :
237+ cls ._primary_singleton = super ().__new__ (cls )
238+ return cls ._primary_singleton
239+ return super ().__new__ (cls )
240+
186241 class Parity (Enum ):
187242 ODD = auto ()
188243 EVEN = auto ()
@@ -250,3 +305,6 @@ def write(self, buf: circuitpython_typing.ReadableBuffer) -> int | None:
250305 len_buf = len (op .expected )
251306 op .assert_expected (buf , 0 , len_buf )
252307 return len (buf ) or None
308+
309+
310+ _UART = UART (TX , RX )
0 commit comments