From c3a26787ec67bb1386bc58106c7796b87785366b Mon Sep 17 00:00:00 2001 From: tekktrik <89490472+tekktrik@users.noreply.github.com> Date: Sun, 23 Jan 2022 12:26:55 -0500 Subject: [PATCH 1/8] Begin type annotations --- adafruit_bus_device/i2c_device.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/adafruit_bus_device/i2c_device.py b/adafruit_bus_device/i2c_device.py index 770f4c7..ff2c00e 100644 --- a/adafruit_bus_device/i2c_device.py +++ b/adafruit_bus_device/i2c_device.py @@ -7,6 +7,12 @@ ==================================================== """ +try: + from typing import Optional + from busio import I2C +except ImportError: + pass + __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BusDevice.git" @@ -41,7 +47,7 @@ class I2CDevice: device.write(bytes_read) """ - def __init__(self, i2c, device_address, probe=True): + def __init__(self, i2c: I2C, device_address: int, probe: bool = True): self.i2c = i2c self.device_address = device_address @@ -49,7 +55,7 @@ def __init__(self, i2c, device_address, probe=True): if probe: self.__probe_for_device() - def readinto(self, buf, *, start=0, end=None): + def readinto(self, buf: bytearray, *, start: int = 0, end: Optional[int] = None): """ Read into ``buf`` from the device. The number of bytes read will be the length of ``buf``. @@ -66,7 +72,7 @@ def readinto(self, buf, *, start=0, end=None): end = len(buf) self.i2c.readfrom_into(self.device_address, buf, start=start, end=end) - def write(self, buf, *, start=0, end=None): + def write(self, buf: bytearray, *, start: int = 0, end: Optional[int] = None): """ Write the bytes from ``buffer`` to the device, then transmit a stop bit. @@ -86,13 +92,13 @@ def write(self, buf, *, start=0, end=None): # pylint: disable-msg=too-many-arguments def write_then_readinto( self, - out_buffer, - in_buffer, + out_buffer: bytearray, + in_buffer: bytearray, *, - out_start=0, - out_end=None, - in_start=0, - in_end=None + out_start: int = 0, + out_end: Optional[int] = None, + in_start: int = 0, + in_end: Optional[int] = None ): """ Write the bytes from ``out_buffer`` to the device, then immediately @@ -133,12 +139,12 @@ def write_then_readinto( # pylint: enable-msg=too-many-arguments - def __enter__(self): + def __enter__(self) -> 'I2CDevice': while not self.i2c.try_lock(): pass return self - def __exit__(self, exc_type, exc_val, exc_tb): + def __exit__(self, exc_type, exc_val, exc_tb) -> bool: self.i2c.unlock() return False From cd7909a4c795f4e20dd18deeb24d4d41aac6d6c5 Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Thu, 3 Feb 2022 20:36:26 -0500 Subject: [PATCH 2/8] Add remaining type annotations --- adafruit_bus_device/i2c_device.py | 7 ++++--- adafruit_bus_device/spi_device.py | 28 ++++++++++++++++++---------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/adafruit_bus_device/i2c_device.py b/adafruit_bus_device/i2c_device.py index ff2c00e..1584a17 100644 --- a/adafruit_bus_device/i2c_device.py +++ b/adafruit_bus_device/i2c_device.py @@ -8,7 +8,8 @@ """ try: - from typing import Optional + from typing import Optional, Type + from types import TracebackType from busio import I2C except ImportError: pass @@ -144,11 +145,11 @@ def __enter__(self) -> 'I2CDevice': pass return self - def __exit__(self, exc_type, exc_val, exc_tb) -> bool: + def __exit__(self, exc_type: Optional[Type[type]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType]) -> bool: self.i2c.unlock() return False - def __probe_for_device(self): + def __probe_for_device(self) -> None: """ Try to read a byte from an address, if you get an OSError it means the device is not there diff --git a/adafruit_bus_device/spi_device.py b/adafruit_bus_device/spi_device.py index 3e20115..8a56ed4 100644 --- a/adafruit_bus_device/spi_device.py +++ b/adafruit_bus_device/spi_device.py @@ -9,6 +9,14 @@ ==================================================== """ +try: + from typing import Optional, Type + from types import TracebackType + from busio import SPI + from digitalio import DigitalInOut +except ImportError: + pass + __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BusDevice.git" @@ -54,15 +62,15 @@ class SPIDevice: def __init__( self, - spi, - chip_select=None, + spi: SPI, + chip_select: Optional[DigitalInOut] = None, *, - cs_active_value=False, - baudrate=100000, - polarity=0, - phase=0, - extra_clocks=0 - ): + cs_active_value: bool = False, + baudrate: int = 100000, + polarity: int = 0, + phase: int = 0, + extra_clocks: int = 0 + ) -> None: self.spi = spi self.baudrate = baudrate self.polarity = polarity @@ -73,7 +81,7 @@ def __init__( if self.chip_select: self.chip_select.switch_to_output(value=True) - def __enter__(self): + def __enter__(self) -> SPI: while not self.spi.try_lock(): pass self.spi.configure( @@ -83,7 +91,7 @@ def __enter__(self): self.chip_select.value = self.cs_active_value return self.spi - def __exit__(self, exc_type, exc_val, exc_tb): + def __exit__(self, exc_type: Optional[Type[type]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType]) -> bool: if self.chip_select: self.chip_select.value = not self.cs_active_value if self.extra_clocks > 0: From cf3f0f7e0ea91bcfa9703b6b16bfd08cac3b1c65 Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Thu, 3 Feb 2022 20:39:30 -0500 Subject: [PATCH 3/8] Add additional documentation to docstring --- adafruit_bus_device/spi_device.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/adafruit_bus_device/spi_device.py b/adafruit_bus_device/spi_device.py index 8a56ed4..578094e 100644 --- a/adafruit_bus_device/spi_device.py +++ b/adafruit_bus_device/spi_device.py @@ -31,6 +31,9 @@ class SPIDevice: DigitalInOut API. :param bool cs_active_value: Set to true if your device requires CS to be active high. Defaults to false. + :param int baudrate: The SPI baudrate + :param int polarity: The SPI polarity + :param int phase: The SPI phase :param int extra_clocks: The minimum number of clock cycles to cycle the bus after CS is high. (Used for SD cards.) From e7b12c18b641f16502242036c0fcdc52dba3fc46 Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Thu, 3 Feb 2022 20:42:37 -0500 Subject: [PATCH 4/8] Reformatted per pre-commit --- adafruit_bus_device/i2c_device.py | 9 +++++++-- adafruit_bus_device/spi_device.py | 7 ++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/adafruit_bus_device/i2c_device.py b/adafruit_bus_device/i2c_device.py index 1584a17..c446074 100644 --- a/adafruit_bus_device/i2c_device.py +++ b/adafruit_bus_device/i2c_device.py @@ -140,12 +140,17 @@ def write_then_readinto( # pylint: enable-msg=too-many-arguments - def __enter__(self) -> 'I2CDevice': + def __enter__(self) -> "I2CDevice": while not self.i2c.try_lock(): pass return self - def __exit__(self, exc_type: Optional[Type[type]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType]) -> bool: + def __exit__( + self, + exc_type: Optional[Type[type]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> bool: self.i2c.unlock() return False diff --git a/adafruit_bus_device/spi_device.py b/adafruit_bus_device/spi_device.py index 578094e..58c948c 100644 --- a/adafruit_bus_device/spi_device.py +++ b/adafruit_bus_device/spi_device.py @@ -94,7 +94,12 @@ def __enter__(self) -> SPI: self.chip_select.value = self.cs_active_value return self.spi - def __exit__(self, exc_type: Optional[Type[type]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType]) -> bool: + def __exit__( + self, + exc_type: Optional[Type[type]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> bool: if self.chip_select: self.chip_select.value = not self.cs_active_value if self.extra_clocks > 0: From a53610bea963a7be209e2d48df00aef2493c4ade Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Thu, 3 Feb 2022 20:46:29 -0500 Subject: [PATCH 5/8] Add duplicate-code to .pylintrc disables --- .pylintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pylintrc b/.pylintrc index cfd1c41..3908316 100644 --- a/.pylintrc +++ b/.pylintrc @@ -55,7 +55,7 @@ confidence= # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" # disable=import-error,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call -disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error,bad-continuation,unspecified-encoding +disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error,bad-continuation,unspecified-encoding,duplicate-code # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option From 5fc4ce92398034c2b1fc5bb90a6b541217ca9fe1 Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Thu, 3 Feb 2022 20:50:57 -0500 Subject: [PATCH 6/8] Add busio and digitalio to mock imports --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index 176dc21..dc196c2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -23,7 +23,7 @@ # Uncomment the below if you use native CircuitPython modules such as # digitalio, micropython and busio. List the modules you use. Without it, the # autodoc module docs will fail to generate with a warning. -# autodoc_mock_imports = ["adafruit_bus_device", "micropython"] +autodoc_mock_imports = ["busio", "digitalio"] intersphinx_mapping = { "python": ("https://docs.python.org/3.4", None), From bbbbf1589af4dc2ac6f3e8b143000e6236fb9459 Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Fri, 4 Feb 2022 13:00:08 -0500 Subject: [PATCH 7/8] Update type annotations and docstrings --- adafruit_bus_device/i2c_device.py | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/adafruit_bus_device/i2c_device.py b/adafruit_bus_device/i2c_device.py index c446074..9c02b4b 100644 --- a/adafruit_bus_device/i2c_device.py +++ b/adafruit_bus_device/i2c_device.py @@ -11,6 +11,11 @@ from typing import Optional, Type from types import TracebackType from busio import I2C + + try: + from circuitpython_typing import ReadableBuffer, WriteableBuffer + except ImportError: + from _typing import ReadableBuffer, WriteableBuffer except ImportError: pass @@ -48,7 +53,7 @@ class I2CDevice: device.write(bytes_read) """ - def __init__(self, i2c: I2C, device_address: int, probe: bool = True): + def __init__(self, i2c: I2C, device_address: int, probe: bool = True) -> None: self.i2c = i2c self.device_address = device_address @@ -56,7 +61,9 @@ def __init__(self, i2c: I2C, device_address: int, probe: bool = True): if probe: self.__probe_for_device() - def readinto(self, buf: bytearray, *, start: int = 0, end: Optional[int] = None): + def readinto( + self, buf: WriteableBuffer, *, start: int = 0, end: Optional[int] = None + ) -> None: """ Read into ``buf`` from the device. The number of bytes read will be the length of ``buf``. @@ -65,7 +72,7 @@ def readinto(self, buf: bytearray, *, start: int = 0, end: Optional[int] = None) as if ``buf[start:end]``. This will not cause an allocation like ``buf[start:end]`` will so it saves memory. - :param bytearray buffer: buffer to write into + :param ~WriteableBuffer buffer: buffer to write into :param int start: Index to start writing at :param int end: Index to write up to but not include; if None, use ``len(buf)`` """ @@ -73,7 +80,9 @@ def readinto(self, buf: bytearray, *, start: int = 0, end: Optional[int] = None) end = len(buf) self.i2c.readfrom_into(self.device_address, buf, start=start, end=end) - def write(self, buf: bytearray, *, start: int = 0, end: Optional[int] = None): + def write( + self, buf: ReadableBuffer, *, start: int = 0, end: Optional[int] = None + ) -> None: """ Write the bytes from ``buffer`` to the device, then transmit a stop bit. @@ -82,7 +91,7 @@ def write(self, buf: bytearray, *, start: int = 0, end: Optional[int] = None): as if ``buffer[start:end]``. This will not cause an allocation like ``buffer[start:end]`` will so it saves memory. - :param bytearray buffer: buffer containing the bytes to write + :param ~ReadableBuffer buffer: buffer containing the bytes to write :param int start: Index to start writing from :param int end: Index to read up to but not include; if None, use ``len(buf)`` """ @@ -93,14 +102,14 @@ def write(self, buf: bytearray, *, start: int = 0, end: Optional[int] = None): # pylint: disable-msg=too-many-arguments def write_then_readinto( self, - out_buffer: bytearray, - in_buffer: bytearray, + out_buffer: ReadableBuffer, + in_buffer: WriteableBuffer, *, out_start: int = 0, out_end: Optional[int] = None, in_start: int = 0, in_end: Optional[int] = None - ): + ) -> None: """ Write the bytes from ``out_buffer`` to the device, then immediately reads into ``in_buffer`` from the device. The number of bytes read @@ -116,8 +125,8 @@ def write_then_readinto( cause an allocation like ``in_buffer[in_start:in_end]`` will so it saves memory. - :param bytearray out_buffer: buffer containing the bytes to write - :param bytearray in_buffer: buffer containing the bytes to read into + :param ~ReadableBuffer out_buffer: buffer containing the bytes to write + :param ~WriteableBuffer in_buffer: buffer containing the bytes to read into :param int out_start: Index to start writing from :param int out_end: Index to read up to but not include; if None, use ``len(out_buffer)`` :param int in_start: Index to start writing at From 5355337b04b32cd7c488a49cc6b9716c676c056c Mon Sep 17 00:00:00 2001 From: Alec Delaney Date: Fri, 4 Feb 2022 13:06:14 -0500 Subject: [PATCH 8/8] Add typing modules to mock imports --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index dc196c2..083e962 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -23,7 +23,7 @@ # Uncomment the below if you use native CircuitPython modules such as # digitalio, micropython and busio. List the modules you use. Without it, the # autodoc module docs will fail to generate with a warning. -autodoc_mock_imports = ["busio", "digitalio"] +autodoc_mock_imports = ["busio", "digitalio", "circuitpython_typing", "_typing"] intersphinx_mapping = { "python": ("https://docs.python.org/3.4", None),