Skip to content

Commit

Permalink
It's time for python 3.10
Browse files Browse the repository at this point in the history
it provides so much typing enhancements and other nice things like
structural pattern matching.
  • Loading branch information
infirit committed Dec 18, 2024
1 parent 7a6741b commit 88e01e8
Show file tree
Hide file tree
Showing 89 changed files with 479 additions and 475 deletions.
6 changes: 0 additions & 6 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ jobs:
fail-fast: false
matrix:
python:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
Expand All @@ -46,8 +44,6 @@ jobs:
fail-fast: false
matrix:
python:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
Expand All @@ -71,8 +67,6 @@ jobs:
fail-fast: false
matrix:
python:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
Expand Down
39 changes: 20 additions & 19 deletions blueman/Functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
#
from time import sleep
from pathlib import Path
from typing import Optional, Dict, Tuple, List, Callable, Iterable, Union, Any
from typing import Any
from collections.abc import Callable, Iterable
import re
import os
import sys
Expand Down Expand Up @@ -87,9 +88,9 @@ def check_bluetooth_status(message: str, exitfunc: Callable[[], Any]) -> None:

def launch(
cmd: str,
paths: Optional[Iterable[str]] = None,
paths: Iterable[str] | None = None,
system: bool = False,
icon_name: Optional[str] = None,
icon_name: str | None = None,
name: str = "blueman",
sn: bool = True,
) -> bool:
Expand Down Expand Up @@ -120,7 +121,7 @@ def launch(
cmd = os.path.expanduser(cmd)

if paths:
files: Optional[List[Gio.File]] = [Gio.File.new_for_commandline_arg(p) for p in paths]
files: list[Gio.File] | None = [Gio.File.new_for_commandline_arg(p) for p in paths]
else:
files = None

Expand All @@ -141,7 +142,7 @@ def setup_icon_path() -> None:
ic.prepend_search_path(ICON_PATH)


def adapter_path_to_name(path: Optional[str]) -> Optional[str]:
def adapter_path_to_name(path: str | None) -> str | None:
if path is None or path == '':
return None

Expand All @@ -152,15 +153,15 @@ def adapter_path_to_name(path: Optional[str]) -> Optional[str]:


# format error
def e_(msg: Union[str, Exception]) -> Tuple[str, Optional[str]]:
def e_(msg: str | Exception) -> tuple[str, str | None]:
if isinstance(msg, Exception):
return str(msg), traceback.format_exc()
else:
s = msg.strip().split(": ")[-1]
return s, None


def format_bytes(size: float) -> Tuple[float, str]:
def format_bytes(size: float) -> tuple[float, str]:
size = float(size)
if size < 1024:
ret = size
Expand All @@ -180,9 +181,9 @@ def format_bytes(size: float) -> Tuple[float, str]:

def create_menuitem(
text: str,
icon_name: Optional[str] = None,
pixbuf: Optional[GdkPixbuf.Pixbuf] = None,
surface: Optional[cairo.Surface] = None,
icon_name: str | None = None,
pixbuf: GdkPixbuf.Pixbuf | None = None,
surface: cairo.Surface | None = None,
) -> Gtk.ImageMenuItem:
image = Gtk.Image(pixel_size=16)
if icon_name:
Expand All @@ -203,7 +204,7 @@ def create_menuitem(
return item


def have(t: str) -> Optional[str]:
def have(t: str) -> str | None:
paths = os.environ['PATH'] + ':/sbin:/usr/sbin'
for path in paths.split(os.pathsep):
exec_path = os.path.join(path, t)
Expand All @@ -214,7 +215,7 @@ def have(t: str) -> Optional[str]:
return None


def set_proc_title(name: Optional[str] = None) -> int:
def set_proc_title(name: str | None = None) -> int:
"""Set the process title"""

if not name:
Expand All @@ -239,8 +240,8 @@ def set_proc_title(name: Optional[str] = None) -> int:
def create_logger(
log_level: int,
name: str,
log_format: Optional[str] = None,
date_fmt: Optional[str] = None,
log_format: str | None = None,
date_fmt: str | None = None,
syslog: bool = False,
) -> logging.Logger:
if log_format is None:
Expand All @@ -262,7 +263,7 @@ def create_logger(


def create_parser(
parser: Optional[argparse.ArgumentParser] = None,
parser: argparse.ArgumentParser | None = None,
syslog: bool = True,
loglevel: bool = True,
) -> argparse.ArgumentParser:
Expand Down Expand Up @@ -290,7 +291,7 @@ def open_rfcomm(file: str, mode: int) -> int:
raise


def _netmask_for_ifacename(name: str, sock: socket.socket) -> Optional[str]:
def _netmask_for_ifacename(name: str, sock: socket.socket) -> str | None:
siocgifnetmask = 0x891b
bytebuf = struct.pack('256s', name.encode('utf-8'))
try:
Expand All @@ -302,7 +303,7 @@ def _netmask_for_ifacename(name: str, sock: socket.socket) -> Optional[str]:
return socket.inet_ntoa(ret[20:24])


def get_local_interfaces() -> Dict[str, Tuple[str, Optional[str]]]:
def get_local_interfaces() -> dict[str, tuple[str, str | None]]:
""" Returns a dictionary of name:ip, mask key value pairs. """
siocgifconf = 0x8912
names = array.array('B', 4096 * b'\0')
Expand Down Expand Up @@ -333,12 +334,12 @@ def get_local_interfaces() -> Dict[str, Tuple[str, Optional[str]]]:
return ip_dict


def bmexit(msg: Optional[Union[str, int]] = None) -> None:
def bmexit(msg: str | int | None = None) -> None:
raise SystemExit(msg)


def log_system_info() -> None:
def parse_os_release(path: Path) -> Dict[str, str]:
def parse_os_release(path: Path) -> dict[str, str]:
release_dict = {}
try:
with path.open() as f:
Expand Down
3 changes: 1 addition & 2 deletions blueman/Sdp.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from gettext import gettext as _
from typing import Optional
from uuid import UUID

# https://www.bluetooth.com/specifications/assigned-numbers/service-discovery
Expand Down Expand Up @@ -361,7 +360,7 @@ def __init__(self, uuid: str):
super().__init__(uuid)

@property
def short_uuid(self) -> Optional[int]:
def short_uuid(self) -> int | None:
if self.reserved:
return self.int >> 96 & 0xFFFF
else:
Expand Down
10 changes: 5 additions & 5 deletions blueman/Service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from abc import ABC, abstractmethod
from typing import Optional, Callable, List, Set, Collection
from collections.abc import Callable, Collection

from blueman.Sdp import ServiceUUID
from blueman.bluez.Device import Device
Expand Down Expand Up @@ -48,11 +48,11 @@ def uuid(self) -> str:
return self.__uuid

@property
def short_uuid(self) -> Optional[int]:
def short_uuid(self) -> int | None:
return ServiceUUID(self.__uuid).short_uuid

@property
def description(self) -> Optional[str]:
def description(self) -> str | None:
return self.__description__

@property
Expand All @@ -75,9 +75,9 @@ def connectable(self) -> bool:

@property
@abstractmethod
def connected_instances(self) -> List[Instance]:
def connected_instances(self) -> list[Instance]:
...

@property
def common_actions(self) -> Set[Action]:
def common_actions(self) -> set[Action]:
return set()
4 changes: 2 additions & 2 deletions blueman/bluemantyping.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Dict, Tuple, Union, TYPE_CHECKING, NewType
from typing import Union, TYPE_CHECKING, NewType
from gi.repository import GObject

if TYPE_CHECKING:
Expand All @@ -10,7 +10,7 @@ class _HasGType(Protocol):
# Actually supported types are int, bool, str, float, and object but no subclasses, see
# https://github.com/GNOME/pygobject/blob/ac576400ecd554879c906791e6638d64bb8bcc2a/gi/pygi-type.c#L498
# (We shield the possibility to provide a str to avoid errors)
GSignals = Dict[str, Tuple[GObject.SignalFlags, None, Tuple[Union[None, type, GObject.GType, "_HasGType"], ...]]]
GSignals = dict[str, tuple[GObject.SignalFlags, None, tuple[Union[None, type, GObject.GType, "_HasGType"], ...]]]

ObjectPath = NewType("ObjectPath", str)
BtAddress = NewType("BtAddress", str)
4 changes: 2 additions & 2 deletions blueman/bluez/Adapter.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Optional, Callable
from collections.abc import Callable
from blueman.bluemantyping import ObjectPath

from gi.repository import GLib
Expand All @@ -15,7 +15,7 @@ class Adapter(Base):
def __init__(self, obj_path: ObjectPath):
super().__init__(obj_path=obj_path)

def start_discovery(self, error_handler: Optional[Callable[[BluezDBusException], None]] = None) -> None:
def start_discovery(self, error_handler: Callable[[BluezDBusException], None] | None = None) -> None:
self._call('StartDiscovery', error_handler=error_handler)

def stop_discovery(self) -> None:
Expand Down
27 changes: 14 additions & 13 deletions blueman/bluez/Base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import List, Callable, Optional, Any, Union, Dict
from typing import Any
from collections.abc import Callable
from blueman.bluemantyping import GSignals, ObjectPath

from gi.repository import Gio, GLib, GObject
Expand All @@ -10,7 +11,7 @@
class BaseMeta(GObjectMeta):
def __call__(cls, *args: object, **kwargs: str) -> "Base":
if not hasattr(cls, "__instances__"):
cls.__instances__: Dict[str, "Base"] = {}
cls.__instances__: dict[str, "Base"] = {}

path = kwargs.get('obj_path')
if path is None:
Expand All @@ -33,7 +34,7 @@ class Base(GObject.Object, metaclass=BaseMeta):
__gsignals__: GSignals = {
'property-changed': (GObject.SignalFlags.NO_HOOKS, None, (str, object, str))
}
__instances__: Dict[str, "Base"]
__instances__: dict[str, "Base"]

_interface_name: str

Expand All @@ -60,7 +61,7 @@ def __init__(self, *, obj_path: ObjectPath):
self.__variant_map = {str: 's', int: 'u', bool: 'b'}

def _properties_changed(self, _proxy: Gio.DBusProxy, changed_properties: GLib.Variant,
invalidated_properties: List[str]) -> None:
invalidated_properties: list[str]) -> None:
changed = changed_properties.unpack()
object_path = self.get_object_path()
logging.debug(f"{object_path} {changed} {invalidated_properties} {self}")
Expand All @@ -71,15 +72,15 @@ def _properties_changed(self, _proxy: Gio.DBusProxy, changed_properties: GLib.Va
def _call(
self,
method: str,
param: Optional[GLib.Variant] = None,
reply_handler: Optional[Callable[..., None]] = None,
error_handler: Optional[Callable[[BluezDBusException], None]] = None,
param: GLib.Variant | None = None,
reply_handler: Callable[..., None] | None = None,
error_handler: Callable[[BluezDBusException], None] | None = None,
) -> None:
def callback(
proxy: Gio.DBusProxy,
result: Gio.AsyncResult,
reply: Optional[Callable[..., None]],
error: Optional[Callable[[BluezDBusException], None]],
reply: Callable[..., None] | None,
error: Callable[[BluezDBusException], None] | None,
) -> None:
try:
value = proxy.call_finish(result).unpack()
Expand Down Expand Up @@ -112,7 +113,7 @@ def get(self, name: str) -> Any:
else:
raise parse_dbus_error(e)

def set(self, name: str, value: Union[str, int, bool]) -> None:
def set(self, name: str, value: str | int | bool) -> None:
v = GLib.Variant(self.__variant_map[type(value)], value)
param = GLib.Variant('(ssv)', (self._interface_name, name, v))
self.__proxy.call('org.freedesktop.DBus.Properties.Set',
Expand All @@ -124,15 +125,15 @@ def set(self, name: str, value: Union[str, int, bool]) -> None:
def get_object_path(self) -> ObjectPath:
return ObjectPath(self.__proxy.get_object_path())

def get_properties(self) -> Dict[str, Any]:
def get_properties(self) -> dict[str, Any]:
param = GLib.Variant('(s)', (self._interface_name,))
res = self.__proxy.call_sync('org.freedesktop.DBus.Properties.GetAll',
param,
Gio.DBusCallFlags.NONE,
GLib.MAXINT,
None)

props: Dict[str, Any] = res.unpack()[0]
props: dict[str, Any] = res.unpack()[0]
for k, v in self.__fallback.items():
if k in props:
continue
Expand All @@ -148,7 +149,7 @@ def destroy(self) -> None:
def __getitem__(self, key: str) -> Any:
return self.get(key)

def __setitem__(self, key: str, value: Union[str, int, bool]) -> None:
def __setitem__(self, key: str, value: str | int | bool) -> None:
self.set(key, value)

def __contains__(self, key: str) -> bool:
Expand Down
14 changes: 7 additions & 7 deletions blueman/bluez/Device.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Optional, Callable
from collections.abc import Callable
from blueman.bluemantyping import ObjectPath

from blueman.bluez.Base import Base
Expand All @@ -14,22 +14,22 @@ def __init__(self, obj_path: ObjectPath):

def pair(
self,
reply_handler: Optional[Callable[[], None]] = None,
error_handler: Optional[Callable[[BluezDBusException], None]] = None,
reply_handler: Callable[[], None] | None = None,
error_handler: Callable[[BluezDBusException], None] | None = None,
) -> None:
self._call('Pair', reply_handler=reply_handler, error_handler=error_handler)

def connect( # type: ignore
self,
reply_handler: Optional[Callable[[], None]] = None,
error_handler: Optional[Callable[[BluezDBusException], None]] = None,
reply_handler: Callable[[], None] | None = None,
error_handler: Callable[[BluezDBusException], None] | None = None,
) -> None:
self._call('Connect', reply_handler=reply_handler, error_handler=error_handler)

def disconnect( # type: ignore
self,
reply_handler: Optional[Callable[[], None]] = None,
error_handler: Optional[Callable[[BluezDBusException], None]] = None,
reply_handler: Callable[[], None] | None = None,
error_handler: Callable[[BluezDBusException], None] | None = None,
) -> None:
self._call('Disconnect', reply_handler=reply_handler, error_handler=error_handler)

Expand Down
Loading

0 comments on commit 88e01e8

Please sign in to comment.