diff --git a/.github/workflows/run_test_build_deploy.yaml b/.github/workflows/run_test_build_deploy.yaml index 5a6282b4..0c6fd58a 100644 --- a/.github/workflows/run_test_build_deploy.yaml +++ b/.github/workflows/run_test_build_deploy.yaml @@ -15,7 +15,7 @@ jobs: strategy: max-parallel: 5 matrix: - python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] + python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] steps: - uses: actions/checkout@v3 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 959c6094..b071469b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,10 +31,10 @@ repos: rev: 'v1.6.1' hooks: - id: mypy - additional_dependencies: [numpy<1.22, pyusb>=1.0] + additional_dependencies: [numpy<1.25, pyusb>=1.0] exclude: "^(build|docs|tests|dev|setup.py)" - repo: https://github.com/asottile/pyupgrade rev: v3.15.0 hooks: - id: pyupgrade - args: [--py37-plus] + args: [--py38-plus] diff --git a/pyproject.toml b/pyproject.toml index d5603826..a35e8355 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,14 +1,14 @@ [build-system] requires = [ - "setuptools>=18.0", - "cython>=0.18", - "wheel>=0.31.0", - "setuptools_scm", - "pkgconfig" # this should be Linux only, but PEP508 is not supported yet in pyproject.toml + "setuptools>=64", + "setuptools_scm>=8", + "cython>=3", + "wheel>=0.38", + "pkgconfig", # this should be Linux only, but PEP508 is not supported yet in pyproject.toml ] [tool.black] -target-version = ['py37'] +target-version = ['py38'] include = '\.pyi?$' exclude = ''' ( @@ -27,7 +27,7 @@ exclude = ''' [tool.isort] profile = "black" -py_version = "37" +py_version = "38" force_single_line = true [tool.cibuildwheel] @@ -45,7 +45,7 @@ test-command = [ before-build = "yum install -y libusb-devel" [tool.mypy] -python_version = "3.7" +python_version = "3.8" no_implicit_optional = true warn_redundant_casts = true warn_unused_ignores = true diff --git a/setup.py b/setup.py index 3552b951..fda33306 100644 --- a/setup.py +++ b/setup.py @@ -212,7 +212,7 @@ def win_spawn(_, cmd, *args, **kwargs): "pytest>=6.2.4; python_version>'3.9'", ], }, - python_requires=">=3.7", + python_requires=">=3.8", cmdclass={"build_ext": sb_build_ext}, ext_modules=extensions, packages=find_packages(where="src"), @@ -228,9 +228,10 @@ def win_spawn(_, cmd, *args, **kwargs): long_description_content_type="text/markdown", classifiers=[ "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ], ) diff --git a/src/seabreeze/backends.py b/src/seabreeze/backends.py index 29357ea8..a0ca6a45 100644 --- a/src/seabreeze/backends.py +++ b/src/seabreeze/backends.py @@ -3,14 +3,10 @@ import warnings from typing import Any from typing import Dict +from typing import Literal from typing import Optional from typing import cast -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal - from seabreeze.types import SeaBreezeBackend __all__ = ["use", "get_backend"] diff --git a/src/seabreeze/pyseabreeze/features/rawusb.py b/src/seabreeze/pyseabreeze/features/rawusb.py index 06447639..0745dd77 100644 --- a/src/seabreeze/pyseabreeze/features/rawusb.py +++ b/src/seabreeze/pyseabreeze/features/rawusb.py @@ -1,11 +1,6 @@ from __future__ import annotations -import sys - -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal +from typing import Literal from seabreeze.pyseabreeze.features._base import SeaBreezeFeature from seabreeze.pyseabreeze.transport import USBTransport diff --git a/src/seabreeze/pyseabreeze/features/spectrometer.py b/src/seabreeze/pyseabreeze/features/spectrometer.py index 9df0a49a..8dfbcab7 100644 --- a/src/seabreeze/pyseabreeze/features/spectrometer.py +++ b/src/seabreeze/pyseabreeze/features/spectrometer.py @@ -148,10 +148,7 @@ def get_wavelengths(self) -> NDArray[np.float_]: def get_intensities(self) -> NDArray[np.float_]: tmp = self._get_spectrum_raw() - ret = numpy.array( - struct.unpack("<" + "H" * self._spectrum_length, tmp[:-1]), - dtype=numpy.double, - ) + ret = tmp[:-1].view(numpy.dtype(" NDArray[np.uint8]: @@ -191,7 +188,7 @@ def get_intensities(self) -> NDArray[np.float_]: idx = [(i // 2) % 64 + (i % 2) * 64 + (i // 128) * 128 for i in range(N_raw)] # high nibble not guaranteed to be pulled low tsorted = tmp[idx] & numpy.array((0xFF, 0x0F) * N_pix, dtype=numpy.uint8) - ret = numpy.array(struct.unpack("<" + "H" * N_pix, tsorted), dtype=numpy.double) + ret = tsorted.view(numpy.dtype(" NDArray[np.uint8]: + self.protocol.transport.default_timeout_ms ) datastring = self.protocol.query(0x00101100, timeout_ms=timeout) - return numpy.frombuffer(datastring, dtype=numpy.uint8) # type: ignore + return numpy.frombuffer(datastring, dtype=numpy.uint8) def get_fast_buffer_spectrum(self) -> Any: raise SeaBreezeNotSupported( @@ -460,10 +457,7 @@ class SeaBreezeSpectrometerFeatureHR4000(SeaBreezeSpectrometerFeatureOOIFPGA4K): def get_intensities(self) -> NDArray[np.float_]: tmp = self._get_spectrum_raw() # The HR4000 needs to xor with 0x2000 - ret = ( - numpy.array(struct.unpack("<" + "H" * self._spectrum_length, tmp[:-1])) - ^ 0x2000 - ) + ret = tmp[:-1].view(numpy.dtype(" NDArray[np.float_]: tmp = self._get_spectrum_raw() # The HR2000PLUS needs to xor with 0x2000 - ret = ( - numpy.array(struct.unpack("<" + "H" * self._spectrum_length, tmp[:-1])) - ^ 0x2000 - ) + ret = tmp[:-1].view(numpy.dtype(" NDArray[np.float_]: def get_intensities(self) -> NDArray[np.float_]: tmp = self._get_spectrum_raw() # The QE65000 needs to xor with 0x8000 - ret = ( - numpy.array(struct.unpack("<" + "H" * self._spectrum_length, tmp[:-1])) - ^ 0x8000 - ) + ret = tmp[:-1].view(numpy.dtype(" NDArray[np.float_]: tmp = self._get_spectrum_raw() # The NIRQUEST512 needs to xor with 0x8000 - ret = ( - numpy.array(struct.unpack("<" + "H" * self._spectrum_length, tmp[:-1])) - ^ 0x8000 - ) + ret = tmp[:-1].view(numpy.dtype(" NDArray[np.float_]: tmp = self._get_spectrum_raw() # The NIRQUEST256 needs to xor with 0x8000 - ret = ( - numpy.array(struct.unpack("<" + "H" * self._spectrum_length, tmp[:-1])) - ^ 0x8000 - ) + ret = tmp[:-1].view(numpy.dtype(" NDArray[np.float_]: tmp = self._get_spectrum_raw() # XXX: No sync byte for the Jaz - ret = numpy.array( - struct.unpack("<" + "H" * self._spectrum_length, tmp[:]), dtype=numpy.double - ) + ret = tmp.view(numpy.dtype(" NDArray[np.uint8]: + self.protocol.transport.default_timeout_ms ) datastring = self.protocol.query(0x00100928, timeout_ms=timeout) - return numpy.frombuffer(datastring, dtype=numpy.uint8) # type: ignore + return numpy.frombuffer(datastring, dtype=numpy.uint8) def get_intensities(self) -> NDArray[np.float_]: tmp = self._get_spectrum_raw() # 32byte metadata block at beginning - ret = numpy.array( - struct.unpack("<" + "I" * self._spectrum_length, tmp[32:]), - dtype=numpy.double, - ) + ret = tmp[32:].view(numpy.dtype(" NDArray[np.uint8]: # the message type is different than the default defined in the protocol, # requires addition of a new message type in protocol to work datastring = self.protocol.query(0x00101000, timeout_ms=timeout) - return numpy.frombuffer(datastring, dtype=numpy.uint8) # type: ignore + return numpy.frombuffer(datastring, dtype=numpy.uint8) class SeaBreezeSpectrometerFeatureADC(SeaBreezeSpectrometerFeatureOOI): @@ -621,10 +598,8 @@ def get_intensities(self) -> NDArray[np.float_]: tmp = self._get_spectrum_raw() # The byte order is different for some models N_raw = self._spectrum_raw_length - 1 - N_pix = self._spectrum_length idx = [(i // 2) % 64 + (i % 2) * 64 + (i // 128) * 128 for i in range(N_raw)] - tsorted = tmp[idx] - ret = numpy.array(struct.unpack("<" + "H" * N_pix, tsorted), dtype=numpy.double) + ret = tmp[idx].view(numpy.dtype(" NDArray[np.uint8]: + self.protocol.transport.default_timeout_ms ) datastring = self.protocol.query(0x000_01C_00, timeout_ms=timeout) - return numpy.frombuffer(datastring, dtype=numpy.uint8) # type: ignore + return numpy.frombuffer(datastring, dtype=numpy.uint8) def get_intensities(self) -> NDArray[np.float_]: tmp = self._get_spectrum_raw() # 32byte metadata block at beginning - ret = numpy.array( - struct.unpack("<" + "H" * self._spectrum_length, tmp[32:]), - dtype=numpy.double, - ) + ret = tmp[32:].view(numpy.dtype(" None: diff --git a/src/seabreeze/types.py b/src/seabreeze/types.py index 625e40e2..6ac11609 100644 --- a/src/seabreeze/types.py +++ b/src/seabreeze/types.py @@ -4,21 +4,13 @@ """ from __future__ import annotations -import sys from typing import TYPE_CHECKING from typing import Any +from typing import Literal +from typing import Protocol +from typing import TypedDict from typing import TypeVar - -if sys.version_info >= (3, 8): - from typing import Literal - from typing import Protocol - from typing import TypedDict - from typing import runtime_checkable -else: - from typing_extensions import Literal - from typing_extensions import Protocol - from typing_extensions import TypedDict - from typing_extensions import runtime_checkable +from typing import runtime_checkable if TYPE_CHECKING: import numpy as np