This commit is contained in:
gti 2025-02-11 23:24:49 +08:00
parent c2ed707a43
commit 6b93db3442
11 changed files with 252 additions and 197 deletions

3
.gitignore vendored
View File

@ -2,4 +2,5 @@
.venv
bak
__pycache__
@DS
@DS
*.whl

View File

@ -16,10 +16,16 @@ dependencies = [
"tqdm>=4.67.1",
"vtk>=9.4.0",
"jupyter>=1.1.1",
"av",
]
[tool.uv]
no-binary-package = ["av"]
override-dependencies = [
"av>=14.0.0",
]
[tool.uv.sources]
av = [
{ path = "./av-14.1.0-cp312-cp312-win_amd64.whl", marker = "sys_platform == 'win32'" },
{ path = "./av-14.1.0-cp312-cp312-linux_amd64.whl", marker = "sys_platform == 'linux'" },
]

View File

@ -1,4 +1,5 @@
import logging
import platform
import sys
from enum import Enum, auto
from pathlib import Path
@ -14,7 +15,7 @@ from nodes.Node import Node
from utils.Msg import KillMsg, Msg, ImageArgMsg, SelectSeqMsg, SeqIdMinMax, MoveAxisMsg, SeqListMsg, SetBaseMsg, \
SeqMetaMsg, SetPlayMode, DeviceConnectedMsg, DeviceEnabledMsg, DeviceOnlineMsg, SetDeviceEnabledMsg, \
SetDeviceConnectedMsg, DeviceConfigListMsg, SetDeviceConfigMsg, SetRecordMsg, RobotRtsiMsg, RecordFrameMsg
from utils.RfFile import RfSequenceMeta
from utils.RfMeta import RfSequenceMeta
class LinkStatus(Enum):
@ -74,6 +75,7 @@ class Adv(QMainWindow, Ui_MainWindow):
self.record_size_cnt = 0
self.record_frame_cnt = 0
self.update_device_buttons()
def update_b_play_live_enabled(self):
self.b_play_live.setEnabled(all([self.b1, self.b2]))
@ -336,6 +338,8 @@ class MainUI(Node):
def loop(self):
app = QApplication(sys.argv)
if platform.system() == 'Windows':
app.setStyle('windowsvista')
MainWindow = Adv(self)
# MainWindow.move(int(px), int(py))
# MainWindow.resize(int(sx), int(sy))

View File

@ -5,6 +5,7 @@ import zmq
from nodes.Node import Node
from utils.Msg import KillMsg, RobotRtsiMsg, Msg
from utils.network import check_port
from utils.rtsi import rtsi
from utils.rtsi.serialize import DataObject
@ -18,6 +19,10 @@ class Robot(Node):
super(Robot, self).__init__()
self.rtsi_thread_stop = False
if not check_port('11.6.1.53', 30004):
logger.warning('Robot is not running on port 11.6.1.53')
self.rtsi_thread_stop = True
return
self.rt = rtsi('11.6.1.53') # 创建rtsi类
self.rt.connect() # socket链接远程rtsi
self.rt.version_check() # rtsi版本协议检查
@ -40,6 +45,8 @@ class Robot(Node):
self.rt.disconnect()
def loop(self):
if self.rtsi_thread_stop:
return
t = threading.Thread(target=self.rtsi_thread)
t.start()
rtsi_pull_socket = self.context.socket(zmq.PULL)

View File

@ -1,169 +1,12 @@
from enum import Enum, auto
from pathlib import Path
from typing import Annotated, get_type_hints
import cupy as cp
import numpy as np
from attr import dataclass
@dataclass
class RfFolder:
parent: Path
D: str
L: int = 30
C: str = 'PAR'
SHAPE = (1500, 256)
@staticmethod
def from_path(p: Path | str) -> 'RfFolder':
p = Path(p)
D, L, C = p.name.split(',')
L = int(L.replace('L=', ''))
C = C.replace('C=', '')
return RfFolder(p.parent, D, L, C)
@property
def name(self):
return f'{self.D},L={self.L},C={self.C}'
@property
def path(self):
return self.parent / self.name
@property
def all(self):
return [RfFile.from_path(f) for f in self.path.glob('*.bin')]
@dataclass
class RfFile:
folder: RfFolder
X: int = None
Y: int = None
Z: int = None
S: int = None
E: int = None
@staticmethod
def from_path(p: Path | str) -> 'RfFile':
p = Path(p)
folder = RfFolder.from_path(p.parent)
return RfFile(folder, **{(c := pair.split('='))[0]: int(c[1]) for pair in p.stem.split(',')})
@property
def path(self):
arr = []
d = self.__dict__.copy()
# print(d)
d.__delitem__('folder')
for k in d:
if d[k] is not None:
arr.append(f'{k}={d[k]}')
filename = ','.join(arr) + '.bin'
# print(filename)
return self.folder.path / filename
@property
def bin(self):
return self.path.read_bytes()
def test2():
r = RfFile.from_path('/run/media/lambda/b86dccdc-f134-464b-a310-6575ee9ae85c/cap4/TEST1,L=30,C=PAR/S=925,E=4.bin')
print(r)
COMMIT_KEY = 'COMMIT'
class SM:
@classmethod
@property
def p2a(clz):
gh = get_type_hints(clz, include_extras=True)
return {k: gh[k].__metadata__[0] for k in gh}
@classmethod
@property
def p2t(clz):
return get_type_hints(clz)
@classmethod
@property
def a2p(clz):
return {v: k for k, v in clz.p2a.items()}
@property
def name(self):
p2a = self.p2a
p2t = self.p2t
a2p = self.a2p
arr = []
if COMMIT_KEY in a2p:
cp = a2p[COMMIT_KEY]
del p2a[cp]
arr.append(f'{self.__getattribute__(cp)}')
for p in p2a:
t = p2t[p]
v = self.__getattribute__(p)
if issubclass(t, Enum):
vs = v.name
elif issubclass(t, tuple):
vs = f'({' '.join([str(vv) for vv in v])})'
else:
vs = str(v)
if v is not None:
arr.append(f'{p2a[p]}={vs}')
return ",".join(arr)
@property
def filename(self):
return self.name + '.bin'
@classmethod
def from_path(clz, path: Path | str):
path = Path(path)
if not path.exists():
raise FileNotFoundError(path)
if path.is_file():
return clz.from_name(path.stem)
elif path.is_dir():
return clz.from_name(path.name)
else:
raise FileNotFoundError
@classmethod
def from_name(clz, name: str):
p2t = clz.p2t
a2p = clz.a2p
c = clz()
sp = name.split(',')
if COMMIT_KEY in a2p:
c.__setattr__(a2p[COMMIT_KEY], sp.pop(0))
for pv in sp:
a, v = pv.split('=')
p = a2p[a]
t = p2t[p]
if issubclass(t, Enum):
c.__setattr__(p, t[v])
elif issubclass(t, tuple):
c.__setattr__(p, tuple(int(i) for i in v[1:-1].split(' ')))
else:
c.__setattr__(p, t(v))
return c
from utils.RfMeta import RfFrameMeta, RfSequenceMeta
class RfFrame:
@dataclass
class RfFrameMeta(SM):
encoder: Annotated[int, 'E'] = None
sequence_id: Annotated[int, 'S'] = None # test3
robot_x: Annotated[int, 'X'] = None
robot_y: Annotated[int, 'Y'] = None
robot_z: Annotated[int, 'Z'] = None
def __init__(self, data: bytes | Path, meta: RfFrameMeta, seq: 'RfSequence' = None):
self.data = data
self.meta = meta
@ -195,18 +38,6 @@ class RfFrame:
return RfMat(arr.reshape(self.seq.meta.shape), frame_meta=self.meta, seq_meta=self.seq.meta)
@dataclass
class RfSequenceMeta(SM):
class RfSequenceMode(Enum):
PWI = auto()
TFM = auto()
commit: Annotated[str, COMMIT_KEY] = None
shape: Annotated[tuple, 'S'] = None
mode: Annotated[RfSequenceMode, 'M'] = RfSequenceMode.PWI
us: Annotated[int, 'U'] = None
class RfSequence:
def __init__(self, frames: list[RfFrame], meta: RfSequenceMeta):
self.frames = frames
@ -220,7 +51,7 @@ class RfSequence:
meta = RfSequenceMeta.from_path(folder)
rs = RfSequence([], meta)
for f in folder.glob('*.bin'):
rs.frames.append(RfFrame(f, RfFrame.RfFrameMeta.from_path(f), seq=rs))
rs.frames.append(RfFrame(f, RfFrameMeta.from_path(f), seq=rs))
return rs
@property
@ -232,7 +63,7 @@ class RfSequence:
@property
def seq_id_minmax(self):
mmin = 2**32
mmin = 2 ** 32
mmax = 0
for f in self.frames:
mmin = min(mmin, f.meta.sequence_id)

View File

@ -3,6 +3,7 @@ import numpy as np
import cupy as cp
from utils.RfFile import RfFrame, RfSequenceMeta
from utils.RfMeta import RfFrameMeta
def bypass(f):
@ -21,7 +22,7 @@ def bypass(f):
class RfMat:
def __init__(self,
data: cp.ndarray,
frame_meta: RfFrame.RfFrameMeta = None,
frame_meta: RfFrameMeta = None,
seq_meta: RfSequenceMeta = None,
):
self.m = data

104
src/utils/RfMeta.py Normal file
View File

@ -0,0 +1,104 @@
from enum import Enum, auto
from pathlib import Path
from typing import Annotated, get_type_hints
from attr import dataclass
COMMIT_KEY = 'COMMIT'
class RfMeta:
@classmethod
@property
def p2a(clz):
gh = get_type_hints(clz, include_extras=True)
return {k: gh[k].__metadata__[0] for k in gh}
@classmethod
@property
def p2t(clz):
return get_type_hints(clz)
@classmethod
@property
def a2p(clz):
return {v: k for k, v in clz.p2a.items()}
@property
def name(self):
p2a = self.p2a
p2t = self.p2t
a2p = self.a2p
arr = []
if COMMIT_KEY in a2p:
cp = a2p[COMMIT_KEY]
del p2a[cp]
arr.append(f'{self.__getattribute__(cp)}')
for p in p2a:
t = p2t[p]
v = self.__getattribute__(p)
if issubclass(t, Enum):
vs = v.name
elif issubclass(t, tuple):
vs = f'({' '.join([str(vv) for vv in v])})'
else:
vs = str(v)
if v is not None:
arr.append(f'{p2a[p]}={vs}')
return ",".join(arr)
@property
def filename(self):
return self.name + '.bin'
@classmethod
def from_path(clz, path: Path | str):
path = Path(path)
if not path.exists():
raise FileNotFoundError(path)
if path.is_file():
return clz.from_name(path.stem)
elif path.is_dir():
return clz.from_name(path.name)
else:
raise FileNotFoundError
@classmethod
def from_name(clz, name: str):
p2t = clz.p2t
a2p = clz.a2p
c = clz()
sp = name.split(',')
if COMMIT_KEY in a2p:
c.__setattr__(a2p[COMMIT_KEY], sp.pop(0))
for pv in sp:
a, v = pv.split('=')
p = a2p[a]
t = p2t[p]
if issubclass(t, Enum):
c.__setattr__(p, t[v])
elif issubclass(t, tuple):
c.__setattr__(p, tuple(int(i) for i in v[1:-1].split(' ')))
else:
c.__setattr__(p, t(v))
return c
@dataclass
class RfFrameMeta(RfMeta):
encoder: Annotated[int, 'E'] = None
sequence_id: Annotated[int, 'S'] = None # test3
robot_x: Annotated[int, 'X'] = None
robot_y: Annotated[int, 'Y'] = None
robot_z: Annotated[int, 'Z'] = None
@dataclass
class RfSequenceMeta(RfMeta):
class RfSequenceMode(Enum):
PWI = auto()
TFM = auto()
commit: Annotated[str, COMMIT_KEY] = None
shape: Annotated[tuple, 'S'] = None
mode: Annotated[RfSequenceMode, 'M'] = RfSequenceMode.PWI
us: Annotated[int, 'U'] = None

15
src/utils/network.py Normal file
View File

@ -0,0 +1,15 @@
import socket
def check_port(host, port):
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(2) # 设置超时时间为2秒
result = s.connect_ex((host, port))
# 返回True如果连接成功result为0
return result == 0
except socket.gaierror:
print(f"错误:无法解析主机名 '{host}'")
return False
except socket.error as e:
print(f"连接过程中发生错误: {e}")
return False

4
test/qtstyles.py Normal file
View File

@ -0,0 +1,4 @@
import PyQt6.QtWidgets as QtWidgets
if __name__ == '__main__':
print(QtWidgets.QStyleFactory.keys())

52
test/winmain.py Normal file
View File

@ -0,0 +1,52 @@
import os
import platform
if platform.system() == 'Windows':
os.add_dll_directory(r'C:\Users\lambda\source\scarlet\ffmpeg-n7.0.1-221-g0ab20b5788-win64-gpl-shared-7.0\bin')
import logging
import multiprocessing
from BusClient import BusClient
from nodes.WebRTC import WebRTC
from nodes.Beamformer import Beamformer
from nodes.Loader import Loader
from nodes.Broker import Broker
from nodes.Device import Device
from nodes.ImageCV import ImageCV
from nodes.MainUI import MainUI
from nodes.Robot import Robot
from utils.Msg import KillMsg
def main():
logging.basicConfig(level=logging.INFO)
multiprocessing.set_start_method('spawn')
multiprocessing.Pool()
pps = []
ps = [
Broker(),
WebRTC(),
MainUI(),
Device(level=logging.DEBUG),
ImageCV(),
Beamformer(),
Loader(),
Robot(),
]
for p in ps:
pps.append(multiprocessing.Process(target=p))
for p in pps:
p.start()
c = BusClient(KillMsg)
while True:
x: KillMsg = c.recv()
if x.name == '':
break
for p in pps:
p.kill()
if __name__ == '__main__':
main()

72
uv.lock
View File

@ -3,11 +3,17 @@ requires-python = ">=3.12"
resolution-markers = [
"sys_platform == 'darwin'",
"platform_machine == 'aarch64' and sys_platform == 'linux'",
"(platform_machine != 'aarch64' and sys_platform == 'linux') or (sys_platform != 'darwin' and sys_platform != 'linux')",
"sys_platform == 'win32'",
"platform_machine != 'aarch64' and sys_platform == 'linux'",
"sys_platform != 'darwin' and sys_platform != 'linux' and sys_platform != 'win32'",
]
[manifest]
overrides = [{ name = "av", specifier = ">=14.0.0" }]
overrides = [
{ name = "av", marker = "sys_platform != 'linux' and sys_platform != 'win32'", specifier = ">=14.0.0" },
{ name = "av", marker = "sys_platform == 'linux'", path = "av-14.1.0-cp312-cp312-linux_amd64.whl" },
{ name = "av", marker = "sys_platform == 'win32'", path = "av-14.1.0-cp312-cp312-win_amd64.whl" },
]
[[package]]
name = "aiohappyeyeballs"
@ -96,7 +102,9 @@ version = "1.9.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "aioice" },
{ name = "av" },
{ name = "av", version = "14.1.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform != 'linux' and sys_platform != 'win32'" },
{ name = "av", version = "14.1.0", source = { path = "av-14.1.0-cp312-cp312-linux_amd64.whl" }, marker = "sys_platform == 'linux'" },
{ name = "av", version = "14.1.0", source = { path = "av-14.1.0-cp312-cp312-win_amd64.whl" }, marker = "sys_platform == 'win32'" },
{ name = "cffi" },
{ name = "cryptography" },
{ name = "google-crc32c" },
@ -225,22 +233,38 @@ wheels = [
[[package]]
name = "av"
version = "14.0.1"
version = "14.1.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/04/6a/8461055082eee773b549b87519eb8519c2194af1157f6971e3a0722b308e/av-14.0.1.tar.gz", hash = "sha256:2b0a17301af469ddaea46b5c1c982df1b7b5de8bc6c94cdc98cad4a67178c82a", size = 3918806 }
resolution-markers = [
"sys_platform == 'darwin'",
"sys_platform != 'darwin' and sys_platform != 'linux' and sys_platform != 'win32'",
]
sdist = { url = "https://files.pythonhosted.org/packages/c1/8c/8551a53c713424aff5ae1600f17f7407e64761d4eca8854013ee15f2c090/av-14.1.0.tar.gz", hash = "sha256:81a0185af0237016049c2b1560d51d5895ef56763ea7ebab939baa7b6b87e6f7", size = 4049387 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7d/01/b198c3af186003b6429ad4dd9f654f99761a8efa59ab838884c6ac842117/av-14.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e022c6ec1ef4bf324f83ecbe4aa6b0afa89e86537d8c5e15f065e4da1a5de6a8", size = 19530078 },
{ url = "https://files.pythonhosted.org/packages/00/48/2f0ec27a521f4963683d76f3b7870c7667dfb8be4ab9512dad92566a8cbc/av-14.0.1-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:97daa268795449709f0034b19bb7ca4e99018825f9c7640fde30f2cb51f63f00", size = 24343809 },
{ url = "https://files.pythonhosted.org/packages/ca/6f/1bf89ac1f82c79f797d8331a7b191a16c6a8336fc59dbbc3d0b66d543e0a/av-14.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14faba003c6bf6d6b9b9521f77a2059cfd206ae95b48f610b14de8d5ba2ccd4e", size = 32252684 },
{ url = "https://files.pythonhosted.org/packages/ba/71/8eedb586a32f7d1f8d23d9e0a7bc879d4dae6f82c2b7977c69171ea2e5b6/av-14.0.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c1e0319a09525916a51f3c0ab4c07dfe9e82b3c1d8cf7aa3bb495d5dd28e767", size = 31617399 },
{ url = "https://files.pythonhosted.org/packages/16/19/7a833ba5b3c190f204dabc138bbc3f06730084400d79723cbe8d5792364e/av-14.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d37bf19987c8cad8c5701c174bf4e89df7e2de97be2176bd81a2b0f86516f1c3", size = 34166747 },
{ url = "https://files.pythonhosted.org/packages/a9/09/825273ebdadae19b654ca54cfe4096af5c2e06dc53c31150510e8343d6f0/av-14.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:a0893c45c426c0ae6681c689c8f669b7ca76cba4594f8ce50b240850e1145a62", size = 25847349 },
{ url = "https://files.pythonhosted.org/packages/25/32/3ce1b51d6638a1141614f24ed4f4e483613ae9b4a6e53f23f4a5b25907e2/av-14.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:71d7cae036bc362b3c255f99669e2e3412dc9b9e3e390ff426b9ea167f1f1c37", size = 19489839 },
{ url = "https://files.pythonhosted.org/packages/ef/e4/152c072da36a91b3158816a304eed73d2ab1bc6accd690ccce5bcb2dbc3a/av-14.0.1-cp313-cp313-macosx_11_0_x86_64.whl", hash = "sha256:e54079e560cc8d91b9be224a8ced4c8c6b97efdb8932f27c56efcbc2181c8129", size = 24303231 },
{ url = "https://files.pythonhosted.org/packages/6d/f1/968a4182df7dae4badb581106c8655591d42d88bc8efcc54bd5f27c7f3a6/av-14.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d98ab1b5ef8b13fa5875757d6e16fbe0a0c48e98e4c2c1da8478a0dda0ed500b", size = 31899455 },
{ url = "https://files.pythonhosted.org/packages/62/fe/61a85fc2c8286c11a0f607cc044b0c1cd858ddfc71004d5a9857d071f357/av-14.0.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:15924960530541ae6a2b3ce5de2e9bcb5c20379ac57850cfac3ee179b4411f64", size = 31286047 },
{ url = "https://files.pythonhosted.org/packages/e3/86/5eb261662b8766007239f35c33e37589f51b6346fb29cd5281df49f01c84/av-14.0.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:502ecd3cc0973cd2f868ec245bb3f838bb9d4da91bcc608f72a7cdd2cd44f0d1", size = 33822372 },
{ url = "https://files.pythonhosted.org/packages/c7/8d/3b55a58241a74a5b7458085203c98487018b6b507fefa100c21d815b6ec4/av-14.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:7d4adddc7eb6119233b6fca6ad610904312c650eb1743ab52e28d1e5f0b5a466", size = 25818678 },
{ url = "https://files.pythonhosted.org/packages/d0/3f/9fb6a691f52a38917330d7025690445db1aff3eff5887852a44a0728511d/av-14.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d2ca492e369b5628c8a1fc6889c1ac1f66ec8e4b99d2cc2633e7eaf4d2c82e66", size = 22093254 },
{ url = "https://files.pythonhosted.org/packages/af/08/b1de0d440e73b3dfd117cedd2dcbb81eabe601da4ea84aa12d66bc9b3716/av-14.1.0-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:8bf8db92bd986e3278b93bd7ca187bf753bb56d63a0015160fe1d3bba69f30e7", size = 27487693 },
{ url = "https://files.pythonhosted.org/packages/f9/1e/8643dee1647e7714dc2e34ab8717203037080f3a37a9f82c5a8efc180a24/av-14.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:012fb4d08576432b155a8da8d2012a40fb7d7efa63bf117d669ea06ec75cb9a7", size = 22052107 },
{ url = "https://files.pythonhosted.org/packages/2b/3f/2ff3a1f580df369157029029992cce59f826042e02448613083f9f530137/av-14.1.0-cp313-cp313-macosx_11_0_x86_64.whl", hash = "sha256:6ac867ab34b9cfbf3ccdd3f497aaddcbb04cb34f17cf710c8db60cae8d7f1ad7", size = 27445950 },
]
[[package]]
name = "av"
version = "14.1.0"
source = { path = "av-14.1.0-cp312-cp312-linux_amd64.whl" }
resolution-markers = [
"platform_machine == 'aarch64' and sys_platform == 'linux'",
"platform_machine != 'aarch64' and sys_platform == 'linux'",
]
[[package]]
name = "av"
version = "14.1.0"
source = { path = "av-14.1.0-cp312-cp312-win_amd64.whl" }
resolution-markers = [
"sys_platform == 'win32'",
]
wheels = [
{ filename = "av-14.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:455065d7e423393a4ebcde38873d263288f6dd14ed2d00313422938e2cef6718" },
]
[[package]]
@ -578,6 +602,9 @@ source = { virtual = "." }
dependencies = [
{ name = "aiohttp-cors" },
{ name = "aiortc" },
{ name = "av", version = "14.1.0", source = { registry = "https://pypi.org/simple" }, marker = "sys_platform != 'linux' and sys_platform != 'win32'" },
{ name = "av", version = "14.1.0", source = { path = "av-14.1.0-cp312-cp312-linux_amd64.whl" }, marker = "sys_platform == 'linux'" },
{ name = "av", version = "14.1.0", source = { path = "av-14.1.0-cp312-cp312-win_amd64.whl" }, marker = "sys_platform == 'win32'" },
{ name = "cupy-cuda12x" },
{ name = "jupyter" },
{ name = "opencv-python" },
@ -593,6 +620,9 @@ dependencies = [
requires-dist = [
{ name = "aiohttp-cors", specifier = ">=0.7.0" },
{ name = "aiortc", specifier = ">=1.9.0" },
{ name = "av", marker = "sys_platform != 'linux' and sys_platform != 'win32'" },
{ name = "av", marker = "sys_platform == 'linux'", path = "av-14.1.0-cp312-cp312-linux_amd64.whl" },
{ name = "av", marker = "sys_platform == 'win32'", path = "av-14.1.0-cp312-cp312-win_amd64.whl" },
{ name = "cupy-cuda12x", specifier = ">=13.3.0" },
{ name = "jupyter", specifier = ">=1.1.1" },
{ name = "opencv-python", specifier = ">=4.10.0.84" },
@ -1011,7 +1041,7 @@ dependencies = [
{ name = "overrides" },
{ name = "packaging" },
{ name = "prometheus-client" },
{ name = "pywinpty", marker = "(os_name == 'nt' and platform_machine != 'aarch64' and sys_platform == 'linux') or (os_name == 'nt' and sys_platform != 'darwin' and sys_platform != 'linux')" },
{ name = "pywinpty", marker = "os_name == 'nt' and sys_platform != 'darwin' and sys_platform != 'linux'" },
{ name = "pyzmq" },
{ name = "send2trash" },
{ name = "terminado" },
@ -1029,7 +1059,7 @@ name = "jupyter-server-terminals"
version = "0.5.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pywinpty", marker = "(os_name == 'nt' and platform_machine != 'aarch64' and sys_platform == 'linux') or (os_name == 'nt' and sys_platform != 'darwin' and sys_platform != 'linux')" },
{ name = "pywinpty", marker = "os_name == 'nt' and sys_platform != 'darwin' and sys_platform != 'linux'" },
{ name = "terminado" },
]
sdist = { url = "https://files.pythonhosted.org/packages/fc/d5/562469734f476159e99a55426d697cbf8e7eb5efe89fb0e0b4f83a3d3459/jupyter_server_terminals-0.5.3.tar.gz", hash = "sha256:5ae0295167220e9ace0edcfdb212afd2b01ee8d179fe6f23c899590e9b8a5269", size = 31430 }
@ -1460,7 +1490,7 @@ name = "pexpect"
version = "4.9.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "ptyprocess" },
{ name = "ptyprocess", marker = "sys_platform != 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450 }
wheels = [
@ -4662,7 +4692,7 @@ version = "0.18.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "ptyprocess", marker = "os_name != 'nt'" },
{ name = "pywinpty", marker = "(os_name == 'nt' and platform_machine != 'aarch64' and sys_platform == 'linux') or (os_name == 'nt' and sys_platform != 'darwin' and sys_platform != 'linux')" },
{ name = "pywinpty", marker = "os_name == 'nt' and sys_platform != 'darwin' and sys_platform != 'linux'" },
{ name = "tornado" },
]
sdist = { url = "https://files.pythonhosted.org/packages/8a/11/965c6fd8e5cc254f1fe142d547387da17a8ebfd75a3455f637c663fb38a0/terminado-0.18.1.tar.gz", hash = "sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e", size = 32701 }