Add hook for running mypy from poetry.

This commit is contained in:
Dain Nilsson 2023-11-30 14:20:23 +01:00
parent b40451ab75
commit 243d65fb4d
No known key found for this signature in database
GPG Key ID: F04367096FBA95E8
8 changed files with 71 additions and 23 deletions

View File

@ -10,6 +10,14 @@ repos:
require_serial: true
# Python
- repo: local
hooks:
- id: mypy
name: mypy
files: helper/
language: script
entry: run-mypy.sh
require_serial: true
- repo: https://github.com/PyCQA/flake8
rev: 6.1.0
hooks:

View File

@ -15,9 +15,11 @@
# limitations under the License.
from helper import run_rpc_pipes, run_rpc_socket
from typing import cast
import socket
import sys
import io
if __name__ == "__main__":
@ -32,8 +34,8 @@ if __name__ == "__main__":
run_rpc_socket(sock)
else:
sys.stdin.reconfigure(encoding="utf-8")
sys.stdout.reconfigure(encoding="utf-8")
sys.stderr.reconfigure(encoding="utf-8")
cast(io.TextIOWrapper, sys.stdin).reconfigure(encoding="utf-8")
cast(io.TextIOWrapper, sys.stdout).reconfigure(encoding="utf-8")
cast(io.TextIOWrapper, sys.stderr).reconfigure(encoding="utf-8")
run_rpc_pipes(sys.stdout, sys.stdin)

View File

@ -25,6 +25,7 @@ from fido2.ctap2 import Ctap2, ClientPin
from fido2.ctap2.credman import CredentialManagement
from fido2.ctap2.bio import BioEnrollment, FPBioEnrollment, CaptureError
from fido2.pcsc import CtapPcscDevice
from fido2.hid import CtapHidDevice
from yubikit.core.fido import FidoConnection
from ykman.hid import list_ctap_devices as list_ctap
from ykman.pcsc import list_devices as list_ccid
@ -94,8 +95,10 @@ class Ctap2Node(RpcNode):
data.update(uv_retries=uv_retries)
return data
def _prepare_reset_nfc(self, event, signal):
reader_name = self.ctap.device._name
@staticmethod
def _prepare_reset_nfc(device, event, signal):
# TODO: Don't use private member _name.
reader_name = device._name
devices = list_ccid(reader_name)
if not devices or devices[0].reader.name != reader_name:
raise ValueError("Unable to isolate NFC reader")
@ -119,8 +122,9 @@ class Ctap2Node(RpcNode):
raise TimeoutException()
def _prepare_reset_usb(self, event, signal):
dev_path = self.ctap.device.descriptor.path
@staticmethod
def _prepare_reset_usb(device, event, signal):
dev_path = device.descriptor.path
logger.debug(f"Reset over USB: {dev_path}")
signal("reset", dict(state="remove"))
@ -148,10 +152,13 @@ class Ctap2Node(RpcNode):
@action
def reset(self, params, event, signal):
target = _ctap_id(self.ctap)
if isinstance(self.ctap.device, CtapPcscDevice):
connection = self._prepare_reset_nfc(event, signal)
device = self.ctap.device
if isinstance(device, CtapPcscDevice):
connection = self._prepare_reset_nfc(device, event, signal)
elif isinstance(device, CtapHidDevice):
connection = self._prepare_reset_usb(device, event, signal)
else:
connection = self._prepare_reset_usb(event, signal)
raise TypeError("Unsupported connection type")
logger.debug("Performing reset...")
self.ctap = Ctap2(connection)
@ -166,7 +173,7 @@ class Ctap2Node(RpcNode):
@action(condition=lambda self: self._info.options["clientPin"])
def unlock(self, params, event, signal):
pin = params.pop("pin")
permissions = 0
permissions = ClientPin.PERMISSION(0)
if CredentialManagement.is_supported(self._info):
permissions |= ClientPin.PERMISSION.CREDENTIAL_MGMT
if BioEnrollment.is_supported(self._info):

View File

@ -13,7 +13,7 @@
# limitations under the License.
from .base import RpcNode, action
from yubikit.core import require_version, NotSupportedError, TRANSPORT
from yubikit.core import require_version, NotSupportedError, TRANSPORT, Connection
from yubikit.core.smartcard import SmartCardConnection
from yubikit.core.otp import OtpConnection
from yubikit.core.fido import FidoConnection
@ -21,6 +21,7 @@ from yubikit.management import ManagementSession, DeviceConfig, Mode, CAPABILITY
from ykman.device import list_all_devices
from dataclasses import asdict
from time import sleep
from typing import Type
import logging
logger = logging.getLogger(__name__)
@ -29,7 +30,7 @@ logger = logging.getLogger(__name__)
class ManagementNode(RpcNode):
def __init__(self, connection):
super().__init__()
self._connection_type = type(connection)
self._connection_type: Type[Connection] = type(connection)
self.session = ManagementSession(connection)
def get_data(self):
@ -54,11 +55,13 @@ class ManagementNode(RpcNode):
if self._connection_type.usb_interface in ifaces:
connection_types = [self._connection_type]
else:
connection_types = [
t
for t in [SmartCardConnection, OtpConnection, FidoConnection]
if t.usb_interface in ifaces
types: list[Type[Connection]] = [
SmartCardConnection,
OtpConnection,
# mypy doesn't support ABC.register()
FidoConnection, # type: ignore
]
connection_types = [t for t in types if t.usb_interface in ifaces]
self.session.close()
logger.debug("Waiting for device to re-appear...")

View File

@ -166,6 +166,7 @@ class PivNode(RpcNode):
key = None
if self._pivman_data.has_derived_key:
assert self._pivman_data.salt # nosec
key = derive_management_key(pin, self._pivman_data.salt)
elif self._pivman_data.has_stored_key:
pivman_prot = get_pivman_protected_data(self.session)
@ -452,13 +453,14 @@ class SlotNode(RpcNode):
signal("touch")
if generate_type == GENERATE_TYPE.CSR:
result = generate_csr(self.session, self.slot, public_key, subject)
csr = generate_csr(self.session, self.slot, public_key, subject)
result = csr.public_bytes(encoding=Encoding.PEM).decode()
elif generate_type == GENERATE_TYPE.CERTIFICATE:
now = datetime.datetime.utcnow()
then = now + datetime.timedelta(days=365)
valid_from = params.pop("valid_from", now.strftime(_date_format))
valid_to = params.pop("valid_to", then.strftime(_date_format))
result = generate_self_signed_certificate(
cert = generate_self_signed_certificate(
self.session,
self.slot,
public_key,
@ -466,7 +468,8 @@ class SlotNode(RpcNode):
datetime.datetime.strptime(valid_from, _date_format),
datetime.datetime.strptime(valid_to, _date_format),
)
self.session.put_certificate(self.slot, result)
result = cert.public_bytes(encoding=Encoding.PEM).decode()
self.session.put_certificate(self.slot, cert)
self.session.put_object(OBJECT_ID.CHUID, generate_chuid())
else:
raise ValueError("Unsupported GENERATE_TYPE")
@ -477,5 +480,5 @@ class SlotNode(RpcNode):
public_key=public_key.public_bytes(
encoding=Encoding.PEM, format=PublicFormat.SubjectPublicKeyInfo
).decode(),
result=result.public_bytes(encoding=Encoding.PEM).decode(),
result=result,
)

13
helper/poetry.lock generated
View File

@ -659,6 +659,17 @@ files = [
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
]
[[package]]
name = "types-pillow"
version = "10.1.0.2"
description = "Typing stubs for Pillow"
optional = false
python-versions = ">=3.7"
files = [
{file = "types-Pillow-10.1.0.2.tar.gz", hash = "sha256:525c1c5ee67b0ac1721c40d2bc618226ef2123c347e527e14e05b920721a13b9"},
{file = "types_Pillow-10.1.0.2-py3-none-any.whl", hash = "sha256:131078ffa547bf9a201d39ffcdc65633e108148085f4f1b07d4647fcfec6e923"},
]
[[package]]
name = "typing-extensions"
version = "4.8.0"
@ -737,4 +748,4 @@ subdirectory = "wrappers/python"
[metadata]
lock-version = "2.0"
python-versions = "^3.8"
content-hash = "10b4e5ccc4857ea83ad330dc0be559048745b25dc385d70a9393425a226a4ca7"
content-hash = "536b00ea0443a4fb0b7e1293758b14021f9ee68699acf7e621d094339417624c"

View File

@ -22,6 +22,7 @@ Pillow = "^10.0.0"
pyinstaller = {version = "^6.0", python = "<3.13"}
pytest = "^7.4.0"
mypy = "^1.7.1"
types-Pillow = "^10.0.0.0"
[build-system]
requires = ["poetry-core>=1.0.0"]
@ -35,5 +36,5 @@ files = "."
check_untyped_defs = true
[[tool.mypy.overrides]]
module = "smartcard.*"
module = ["smartcard.*", "zxingcpp"]
ignore_missing_imports = true

13
run-mypy.sh Executable file
View File

@ -0,0 +1,13 @@
#!/bin/sh
# Runs mypy from poetry in the helper directory.
set -e
cd helper
if [ "$(poetry env list)" = "" ]; then
echo "Initializing poetry env..."
poetry install
fi
poetry run mypy