Skip to content

Commit

Permalink
q-dev: make pylint happy
Browse files Browse the repository at this point in the history
  • Loading branch information
piotrbartman committed Apr 23, 2024
1 parent 350502b commit 02e9f7f
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 9 deletions.
70 changes: 63 additions & 7 deletions qubesadmin/device_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import string
import sys
from enum import Enum
from typing import Optional, Dict, Any, List, Union
from typing import Optional, Dict, Any, List, Union, Tuple

import qubesadmin.exc

Expand Down Expand Up @@ -74,6 +74,16 @@ def qbool(value):


class Device:
"""
Basic class of a *bus* device with *ident* exposed by a *backend domain*.
Attributes:
backend_domain (QubesVM): The domain which exposes devices,
e.g.`sys-usb`.
ident (str): A unique identifier for the device within
the backend domain.
devclass (str, optional): The class of the device (e.g., 'usb', 'pci').
"""
ALLOWED_CHARS_KEY = (
string.digits + string.ascii_letters + string.punctuation + ' ')
ALLOWED_CHARS_PARAM = ALLOWED_CHARS_KEY + string.punctuation + ' '
Expand Down Expand Up @@ -152,7 +162,20 @@ def devclass(self, devclass: str):
self.__bus = devclass

@classmethod
def unpack_properties(cls, untrusted_serialization: bytes):
def unpack_properties(
cls, untrusted_serialization: bytes
) -> Tuple[Dict, Dict]:
"""
Unpacks basic device properties from a serialized encoded string.
Returns:
tuple: A tuple containing two dictionaries, properties and options,
extracted from the serialization.
Raises:
ValueError: If unexpected characters are found in property
names or values.
"""
ut_decoded = untrusted_serialization.decode(
'ascii', errors='strict').strip()

Expand Down Expand Up @@ -197,7 +220,17 @@ def unpack_properties(cls, untrusted_serialization: bytes):
return properties, options

@staticmethod
def check_device_properties(expected_device, properties):
def check_device_properties(
expected_device: 'Device', properties: Dict[str, Any]):
"""
Validates properties against an expected device configuration.
Modifies `properties`.
Raises:
UnexpectedDeviceProperty: If any property does not match
the expected values.
"""
expected = expected_device
exp_vm_name = expected.backend_domain.name
if properties.get('backend_domain', exp_vm_name) != exp_vm_name:
Expand All @@ -221,10 +254,9 @@ def check_device_properties(expected_device, properties):
properties['devclass'] = expected.devclass



class DeviceCategory(Enum):
"""
Category of peripheral device.
Category of a peripheral device.
Arbitrarily selected interfaces that are important to users,
thus deserving special recognition such as a custom icon, etc.
Expand Down Expand Up @@ -255,6 +287,9 @@ class DeviceCategory(Enum):

@staticmethod
def from_str(interface_encoding: str) -> 'DeviceCategory':
"""
Returns `DeviceCategory` from data encoded in string.
"""
result = DeviceCategory.Other
if len(interface_encoding) != len(DeviceCategory.Other.value):
return result
Expand Down Expand Up @@ -554,7 +589,7 @@ def attachment(self) -> Optional[QubesVM]:

def serialize(self) -> bytes:
"""
Serialize object to be transmitted via Qubes API.
Serialize an object to be transmitted via Qubes API.
"""
# 'backend_domain', 'attachment', 'interfaces', 'data', 'parent_device'
# are not string, so they need special treatment
Expand Down Expand Up @@ -604,6 +639,9 @@ def deserialize(
expected_backend_domain: QubesVM,
expected_devclass: Optional[str] = None,
) -> 'DeviceInfo':
"""
Recovers a serialized object, see: :py:meth:`serialize`.
"""
ident, _, rest = serialization.partition(b' ')
ident = ident.decode('ascii', errors='ignore')
device = UnknownDevice(
Expand All @@ -626,6 +664,9 @@ def _deserialize(
untrusted_serialization: bytes,
expected_device: Device
) -> 'DeviceInfo':
"""
Actually deserializes the object.
"""
properties, options = cls.unpack_properties(untrusted_serialization)
properties.update(options)

Expand Down Expand Up @@ -684,13 +725,19 @@ def self_identity(self) -> str:


def serialize_str(value: str):
"""
Serialize python string to ensure consistency.
"""
result = repr(str(value))
if result.startswith('"'):
result = "'" + result[1:-1] + "'"
return result


def deserialize_str(value: str):
"""
Deserialize python string to ensure consistency.
"""
return value.replace("\\\'", "'")


Expand Down Expand Up @@ -722,7 +769,7 @@ def sanitize_str(

class UnknownDevice(DeviceInfo):
# pylint: disable=too-few-public-methods
"""Unknown device - for example exposed by domain not running currently"""
"""Unknown device - for example, exposed by domain not running currently"""

def __init__(self, backend_domain, ident, *, devclass, **kwargs):
super().__init__(backend_domain, ident, devclass=devclass, **kwargs)
Expand Down Expand Up @@ -850,6 +897,9 @@ def options(self, options: Optional[Dict[str, Any]]):
self.__options = options or {}

def serialize(self) -> bytes:
"""
Serialize an object to be transmitted via Qubes API.
"""
properties = b' '.join(
f'{prop}={serialize_str(value)}'.encode('ascii')
for prop, value in (
Expand Down Expand Up @@ -885,6 +935,9 @@ def deserialize(
serialization: bytes,
expected_device: Device,
) -> 'DeviceAssignment':
"""
Recovers a serialized object, see: :py:meth:`serialize`.
"""
try:
result = cls._deserialize(serialization, expected_device)
except Exception as exc:
Expand All @@ -897,6 +950,9 @@ def _deserialize(
untrusted_serialization: bytes,
expected_device: Device,
) -> 'DeviceAssignment':
"""
Actually deserializes the object.
"""
properties, options = cls.unpack_properties(untrusted_serialization)
properties['options'] = options

Expand Down
3 changes: 1 addition & 2 deletions qubesadmin/tools/qvm_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,7 @@ def _load_frontends_info(vm, dev, devclass):
return '{!s} ({})'.format(
vm, ', '.join('{}={}'.format(key, value)
for key, value in assignment.options.items()))
else:
return str(vm)
return str(vm)
except qubesadmin.exc.QubesVMNotFoundError:
return None

Expand Down

0 comments on commit 02e9f7f

Please sign in to comment.