Skip to content

Commit 8e2f560

Browse files
committed
fix: Make arguments depend on uhubctl version
Refactor uhubctl wrapper code and introduce version check, which is used for conditional arguments (some require a more recent version). Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
1 parent 821fabe commit 8e2f560

3 files changed

Lines changed: 40 additions & 19 deletions

File tree

tests/helper.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ def cmd(
7070
stdout += self.__stdout("New", port_filter=port_number)
7171

7272
fp.register(cmd, stdout=stdout)
73+
fp.register(["uhubctl", "-v"], stdout="2.4.0-43-ge1e4d450")
7374

7475

7576
@pytest.fixture

uhubctl/usb.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import re
33
from typing import List, Optional
44

5-
from .utils import _uhubctl
5+
from .utils import UHubCtl
66

77

88
def discover_hubs() -> List["Hub"]:
@@ -17,7 +17,7 @@ def discover_hubs() -> List["Hub"]:
1717

1818
pattern = re.compile(r"Current status for hub ([\.\d-]+)")
1919

20-
for line in _uhubctl():
20+
for line in UHubCtl.exec():
2121
regex = pattern.match(line)
2222

2323
if regex:
@@ -96,7 +96,7 @@ def discover_ports(self) -> None:
9696
"""
9797
pattern = re.compile(r" Port (\d+): \d{4} ")
9898

99-
for line in _uhubctl(["-l", self.path]):
99+
for line in UHubCtl.exec(["-l", self.path]):
100100
regex = pattern.match(line)
101101

102102
if regex:
@@ -133,7 +133,7 @@ def status(self) -> bool:
133133
pattern = re.compile(rf" Port {self.port_number}: \d{{4}} (power|off|indicator)")
134134

135135
args = ["-l", self.hub.path, "-p", str(self.port_number)]
136-
for line in _uhubctl(args):
136+
for line in UHubCtl.exec(args):
137137
reg = pattern.match(line)
138138

139139
if reg:
@@ -153,7 +153,7 @@ def status(self, status: bool) -> None:
153153
else:
154154
args.append("off")
155155

156-
_uhubctl(args)
156+
UHubCtl.exec(args)
157157

158158
@staticmethod
159159
def from_path(path: str):

uhubctl/utils.py

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,45 @@
11
"""Utilities around uhubctl binary"""
22
import subprocess
33

4+
from packaging import version
5+
46
UHUBCTL_BINARY = "uhubctl"
57

68

7-
def _uhubctl(args: list = None) -> list:
8-
cmd = UHUBCTL_BINARY.split(" ")
9-
cmd.append("-N")
9+
class UHubCtl:
10+
_version = None
11+
12+
@classmethod
13+
def version(cls) -> str:
14+
if cls._version is None:
15+
cmd = UHUBCTL_BINARY.split(" ")
16+
cmd.append("-v")
17+
18+
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
19+
20+
cls._version = result.stdout.split("-", maxsplit=1)[0]
21+
22+
return cls._version
23+
24+
@classmethod
25+
def exec(cls, args: list = None) -> list:
26+
cmd = UHUBCTL_BINARY.split(" ")
27+
28+
if version.parse(cls.version()) > version.parse("2.3.0"):
29+
cmd.append("-N")
1030

11-
if args is not None:
12-
cmd += args
31+
if args is not None:
32+
cmd += args
1333

14-
try:
15-
result = subprocess.run(cmd, capture_output=True, check=True)
16-
stdout = result.stdout.decode()
34+
try:
35+
result = subprocess.run(cmd, capture_output=True, check=True)
36+
stdout = result.stdout.decode()
1737

18-
return stdout.split("\n")
19-
except subprocess.CalledProcessError as exc:
20-
stderr = exc.stderr.decode()
38+
return stdout.split("\n")
39+
except subprocess.CalledProcessError as exc:
40+
stderr = exc.stderr.decode()
2141

22-
if stderr.startswith("No compatible devices detected"):
23-
return []
42+
if stderr.startswith("No compatible devices detected"):
43+
return []
2444

25-
raise Exception(f"uhubctl failed: {stderr}") from exc
45+
raise Exception(f"uhubctl failed: {stderr}") from exc

0 commit comments

Comments
 (0)