Compare commits
8 Commits
main
...
dpi-font-a
| Author | SHA1 | Date |
|---|---|---|
|
|
e1a81fa433 | |
|
|
073f496f87 | |
|
|
5b08ee1317 | |
|
|
28d0b4ce36 | |
|
|
d4d4628680 | |
|
|
78e5c799f0 | |
|
|
ee45b46638 | |
|
|
4b6bd55df4 |
|
|
@ -95,15 +95,12 @@ bc why install with `python` when you can faster with `rust` ::
|
||||||
|
|
||||||
include all GUIs (ex. for charting)::
|
include all GUIs (ex. for charting)::
|
||||||
|
|
||||||
uv sync --group uis
|
uv sync --extra uis
|
||||||
|
|
||||||
AND with **all** our normal hacking tools::
|
AND with all our hacking tools and WIP integrations::
|
||||||
|
|
||||||
uv sync --dev
|
uv sync --dev --all-extras
|
||||||
|
|
||||||
AND if you want to try WIP integrations::
|
|
||||||
|
|
||||||
uv sync --all-groups
|
|
||||||
|
|
||||||
Ensure you can run the root-daemon::
|
Ensure you can run the root-daemon::
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -182,24 +182,27 @@ class DpiAwareFont:
|
||||||
# always going to hit that error in range mapping from inches:
|
# always going to hit that error in range mapping from inches:
|
||||||
# float to px size: int.
|
# float to px size: int.
|
||||||
self._font_inches = inches
|
self._font_inches = inches
|
||||||
font_size = math.floor(inches * dpi)
|
font_size = math.floor(inches * pdpi)
|
||||||
|
|
||||||
log.debug(
|
ftype: str = f'{type(self)!r}'
|
||||||
f"screen:{screen.name()}\n"
|
log.info(
|
||||||
f"pDPI: {pdpi}, lDPI: {ldpi}, scale: {scale}\n"
|
f'screen: {screen.name()}\n'
|
||||||
f"\nOur best guess font size is {font_size}\n"
|
f'pDPI: {pdpi!r}\n'
|
||||||
|
f'lDPI: {ldpi!r}\n'
|
||||||
|
f'scale: {scale!r}\n'
|
||||||
|
f'{ftype}._font_inches={self._font_inches!r}\n'
|
||||||
|
f'\n'
|
||||||
|
f"Our best guess for an auto-font-size is,\n"
|
||||||
|
f'font_size: {font_size!r}\n'
|
||||||
)
|
)
|
||||||
# apply the size
|
# apply the size
|
||||||
self._set_qfont_px_size(font_size)
|
self._set_qfont_px_size(font_size)
|
||||||
|
|
||||||
def boundingRect(self, value: str) -> QtCore.QRectF:
|
def boundingRect(self, value: str) -> QtCore.QRectF:
|
||||||
|
if (screen := self.screen) is None:
|
||||||
screen = self.screen
|
|
||||||
if screen is None:
|
|
||||||
raise RuntimeError("You must call .configure_to_dpi() first!")
|
raise RuntimeError("You must call .configure_to_dpi() first!")
|
||||||
|
|
||||||
unscaled_br = self._qfm.boundingRect(value)
|
unscaled_br: QtCore.QRectF = self._qfm.boundingRect(value)
|
||||||
|
|
||||||
return QtCore.QRectF(
|
return QtCore.QRectF(
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
|
|
||||||
104
pyproject.toml
104
pyproject.toml
|
|
@ -77,42 +77,54 @@ dependencies = [
|
||||||
"pyvnc",
|
"pyvnc",
|
||||||
]
|
]
|
||||||
# ------ dependencies ------
|
# ------ dependencies ------
|
||||||
# NOTE, by default we ship only a "headless" deps set bc
|
|
||||||
# the `uis` group is not listed in the optional set.
|
|
||||||
|
|
||||||
# [optional-dependencies]
|
|
||||||
# uis = []
|
# TODO: add an `--only daemon` group for running non-ui / pikerd
|
||||||
# ?TODO? really we should be able to mv this `uis` group
|
# service tree in distributed mode B)
|
||||||
# to be under [optional-dependencies] and then include
|
|
||||||
# it in the dev deps?
|
|
||||||
# https://docs.astral.sh/uv/concepts/projects/dependencies/#optional-dependencies
|
# https://docs.astral.sh/uv/concepts/projects/dependencies/#optional-dependencies
|
||||||
# -> uis should be included in pubbed pkgs.
|
|
||||||
# [ ] uv seems to have no way to do this though?
|
|
||||||
|
|
||||||
# TODO? move to a `uv.toml`?
|
|
||||||
[tool.uv]
|
|
||||||
# https://docs.astral.sh/uv/reference/settings/#python-preference
|
|
||||||
python-preference = 'system'
|
|
||||||
# https://docs.astral.sh/uv/reference/settings/#python-downloads
|
|
||||||
python-downloads = 'manual'
|
|
||||||
# https://docs.astral.sh/uv/concepts/projects/dependencies/#default-groups
|
|
||||||
default-groups = [
|
|
||||||
'uis',
|
|
||||||
]
|
|
||||||
# ------ tool.uv ------
|
|
||||||
|
|
||||||
[dependency-groups]
|
[dependency-groups]
|
||||||
uis = [
|
uis = [
|
||||||
"pyqtgraph",
|
# https://docs.astral.sh/uv/concepts/projects/dependencies/#optional-dependencies
|
||||||
"qdarkstyle >=3.0.2, <4.0.0",
|
# TODO: make sure the levenshtein shit compiles on nix..
|
||||||
"pyqt6 >=6.7.0, <7.0.0",
|
# rapidfuzz = {extras = ["speedup"], version = "^0.18.0"}
|
||||||
|
"rapidfuzz >=3.2.0, <4.0.0",
|
||||||
|
"qdarkstyle >=3.0.2, <4.0.0",
|
||||||
|
"pyqt6 >=6.7.0, <7.0.0",
|
||||||
|
"pyqtgraph",
|
||||||
|
|
||||||
# fuzzy search
|
# for consideration,
|
||||||
"rapidfuzz >=3.2.0, <4.0.0",
|
# - 'visidata'
|
||||||
|
|
||||||
|
"qdarkstyle >=3.0.2, <4.0.0",
|
||||||
|
"pyqt6 >=6.7.0, <7.0.0",
|
||||||
|
"pyqtgraph",
|
||||||
]
|
]
|
||||||
|
|
||||||
# dev deps enabled by `uv --dev`
|
# TODO: a toolset that makes debugging a `pikerd` service (tree) easy
|
||||||
# https://docs.astral.sh/uv/concepts/projects/dependencies/#development-dependencies
|
# to hack on directly using more or less the local env:
|
||||||
|
# - xonsh + xxh
|
||||||
|
# - rsyscall + pdbp
|
||||||
|
# - actor runtime control console like BEAM/OTP
|
||||||
|
#
|
||||||
|
# console ehancements and eventually remote debugging extras/helpers.
|
||||||
|
# use `uv --dev` to enable
|
||||||
|
repl = [
|
||||||
|
# debug
|
||||||
|
"pdbp >=1.5.0, <2.0.0",
|
||||||
|
"greenback >=1.1.1, <2.0.0",
|
||||||
|
"xonsh",
|
||||||
|
"prompt-toolkit ==3.0.40",
|
||||||
|
"pyperclip>=1.9.0",
|
||||||
|
|
||||||
|
]
|
||||||
|
testing = [
|
||||||
|
"pytest",
|
||||||
|
]
|
||||||
|
de = [
|
||||||
|
# DE-specific
|
||||||
|
"i3ipc>=2.2.1",
|
||||||
|
]
|
||||||
dev = [
|
dev = [
|
||||||
# https://docs.astral.sh/uv/concepts/projects/dependencies/#development-dependencies
|
# https://docs.astral.sh/uv/concepts/projects/dependencies/#development-dependencies
|
||||||
"cython >=3.0.0, <4.0.0",
|
"cython >=3.0.0, <4.0.0",
|
||||||
|
|
@ -124,34 +136,13 @@ dev = [
|
||||||
{include-group = 'testing'},
|
{include-group = 'testing'},
|
||||||
{include-group = 'de'},
|
{include-group = 'de'},
|
||||||
]
|
]
|
||||||
repl = [
|
|
||||||
# `tractor`'s debugger
|
|
||||||
"pdbp >=1.8.2, <2.0.0",
|
|
||||||
"greenback >=1.1.1, <2.0.0",
|
|
||||||
|
|
||||||
# @goodboy's preferred console toolz
|
|
||||||
"xonsh",
|
|
||||||
"prompt-toolkit ==3.0.40",
|
|
||||||
"pyperclip>=1.9.0",
|
|
||||||
|
|
||||||
# ?TODO, new stuff to consider..
|
|
||||||
# "visidata" # console numerics
|
|
||||||
# "xxh" # for remote `xonsh`-ing
|
|
||||||
# "rsyscall" # (eventual) optional `tractor` backend
|
|
||||||
# - an actor-runtime-ctl console like BEAM/OTP
|
|
||||||
]
|
|
||||||
testing = [
|
|
||||||
"pytest",
|
|
||||||
]
|
|
||||||
de = [ # (linux) specific DEs
|
|
||||||
"i3ipc>=2.2.1",
|
|
||||||
]
|
|
||||||
lint = [
|
lint = [
|
||||||
# XXX, with flake.nix needs to be from nixpkgs
|
# XXX, with flake.nix needs to be from nixpkgs
|
||||||
"ruff>=0.9.6"
|
"ruff>=0.9.6"
|
||||||
|
#
|
||||||
|
# ^TODO? these markers don't work; use deps-flags for now?
|
||||||
# ; os_name != 'nixos' and platform_system != 'NixOS'",
|
# ; os_name != 'nixos' and platform_system != 'NixOS'",
|
||||||
# ?TODO? since ^ markers won't work, use a deps-flags to toggle for
|
# ; defined('IN_NIX_SHELL')",
|
||||||
# now.
|
|
||||||
]
|
]
|
||||||
dbs = [
|
dbs = [
|
||||||
"elasticsearch >=8.9.0, <9.0.0",
|
"elasticsearch >=8.9.0, <9.0.0",
|
||||||
|
|
@ -186,6 +177,15 @@ include = ["piker"]
|
||||||
# ------ tool.hatch ------
|
# ------ tool.hatch ------
|
||||||
|
|
||||||
|
|
||||||
|
# TODO? move to a `uv.toml`?
|
||||||
|
[tool.uv]
|
||||||
|
python-preference = 'system'
|
||||||
|
python-downloads = 'manual'
|
||||||
|
# https://docs.astral.sh/uv/concepts/projects/dependencies/#default-groups
|
||||||
|
default-groups = ['uis', 'dev']
|
||||||
|
# ------ tool.uv ------
|
||||||
|
|
||||||
|
|
||||||
[tool.uv.sources]
|
[tool.uv.sources]
|
||||||
pyqtgraph = { git = "https://github.com/pikers/pyqtgraph.git" }
|
pyqtgraph = { git = "https://github.com/pikers/pyqtgraph.git" }
|
||||||
tomlkit = { git = "https://github.com/pikers/tomlkit.git", branch ="piker_pin" }
|
tomlkit = { git = "https://github.com/pikers/tomlkit.git", branch ="piker_pin" }
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
#!env xonsh
|
||||||
|
'''
|
||||||
|
Compute the pxs-per-inch (PPI) naively for the local DE.
|
||||||
|
|
||||||
|
NOTE, currently this only supports the `sway`-TWM on wayland.
|
||||||
|
|
||||||
|
!TODO!
|
||||||
|
- [ ] support Xorg (and possibly other OSs as well?
|
||||||
|
- [ ] conver this to pure py code, dropping the `.xsh` specifics
|
||||||
|
instead for `subprocess` API calls?
|
||||||
|
- [ ] possibly unify all this with `./qt_screen_info.py` as part of
|
||||||
|
a "PPI config wizard" or something, but more then likely we'll
|
||||||
|
have lib-ified version inside modden/piker by then?
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
import math
|
||||||
|
import json
|
||||||
|
|
||||||
|
# XXX, xonsh part using "subprocess mode"
|
||||||
|
disp_infos: list[dict] = json.loads($(wlr-randr --json))
|
||||||
|
lappy: dict = disp_infos[0]
|
||||||
|
|
||||||
|
dims: dict[str, int] = lappy['physical_size']
|
||||||
|
w_cm: int = dims['width']
|
||||||
|
h_cm: int = dims['height']
|
||||||
|
|
||||||
|
# cm per inch
|
||||||
|
cpi: float = 25.4
|
||||||
|
|
||||||
|
# compute "diagonal" size (aka hypot)
|
||||||
|
diag_inches: float = math.sqrt((h_cm/cpi)**2 + (w_cm/cpi)**2)
|
||||||
|
|
||||||
|
# compute reso-hypot / inches-hypot
|
||||||
|
hi_res: dict[str, float|bool] = lappy['modes'][0]
|
||||||
|
w_px: int = hi_res['width']
|
||||||
|
h_px: int = hi_res['height']
|
||||||
|
|
||||||
|
diag_pxs: float = math.sqrt(h_px**2 + w_px**2)
|
||||||
|
unscaled_ppi: float = diag_pxs/diag_inches
|
||||||
|
|
||||||
|
# retrieve TWM info on the display (including scaling info)
|
||||||
|
sway_disp_info: dict = json.loads($(swaymsg -r -t get_outputs))[0]
|
||||||
|
scale: float = sway_disp_info['scale']
|
||||||
|
|
||||||
|
print(
|
||||||
|
f'output: {sway_disp_info["name"]!r}\n'
|
||||||
|
f'--- DIMENSIONS ---\n'
|
||||||
|
f'w_cm: {w_cm!r}\n'
|
||||||
|
f'h_cm: {h_cm!r}\n'
|
||||||
|
f'w_px: {w_px!r}\n'
|
||||||
|
f'h_cm: {h_px!r}\n'
|
||||||
|
f'\n'
|
||||||
|
f'--- DIAGONALS ---\n'
|
||||||
|
f'diag_inches: {diag_inches!r}\n'
|
||||||
|
f'diag_pxs: {diag_pxs!r}\n'
|
||||||
|
f'\n'
|
||||||
|
f'--- PPI-related-info ---\n'
|
||||||
|
f'(DE reported) scale: {scale!r}\n'
|
||||||
|
f'unscaled PPI: {unscaled_ppi!r}\n'
|
||||||
|
f'|_ =sqrt(h_px**2 + w_px**2) / sqrt(h_in**2 + w_in**2)\n'
|
||||||
|
f'scaled PPI: {unscaled_ppi/scale!r}\n'
|
||||||
|
f'|_ =unscaled_ppi/scale\n'
|
||||||
|
)
|
||||||
|
|
@ -31,8 +31,8 @@ Resource list for mucking with DPIs on multiple screens:
|
||||||
- https://doc.qt.io/qt-5/qguiapplication.html#screenAt
|
- https://doc.qt.io/qt-5/qguiapplication.html#screenAt
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
import os
|
||||||
|
|
||||||
from pyqtgraph import QtGui
|
|
||||||
from PyQt6 import (
|
from PyQt6 import (
|
||||||
QtCore,
|
QtCore,
|
||||||
QtWidgets,
|
QtWidgets,
|
||||||
|
|
@ -43,6 +43,11 @@ from PyQt6.QtCore import (
|
||||||
QSize,
|
QSize,
|
||||||
QRect,
|
QRect,
|
||||||
)
|
)
|
||||||
|
from pyqtgraph import QtGui
|
||||||
|
|
||||||
|
|
||||||
|
# https://doc.qt.io/qt-6/highdpi.html#environment-variable-reference
|
||||||
|
os.environ['QT_USE_PHYSICAL_DPI'] = '1'
|
||||||
|
|
||||||
# Proper high DPI scaling is available in Qt >= 5.6.0. This attibute
|
# Proper high DPI scaling is available in Qt >= 5.6.0. This attibute
|
||||||
# must be set before creating the application
|
# must be set before creating the application
|
||||||
|
|
@ -58,13 +63,22 @@ if hasattr(Qt, 'AA_UseHighDpiPixmaps'):
|
||||||
True,
|
True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# NOTE, inherits `QGuiApplication`
|
||||||
|
# https://doc.qt.io/qt-6/qapplication.html
|
||||||
|
# https://doc.qt.io/qt-6/qguiapplication.html
|
||||||
app = QtWidgets.QApplication([])
|
app = QtWidgets.QApplication([])
|
||||||
|
#
|
||||||
|
# ^TODO? various global DPI settings?
|
||||||
|
# [ ] DPI rounding policy,
|
||||||
|
# - https://doc.qt.io/qt-6/qt.html#HighDpiScaleFactorRoundingPolicy-enum
|
||||||
|
# - https://doc.qt.io/qt-6/qguiapplication.html#setHighDpiScaleFactorRoundingPolicy
|
||||||
|
|
||||||
window = QtWidgets.QMainWindow()
|
window = QtWidgets.QMainWindow()
|
||||||
main_widget = QtWidgets.QWidget()
|
main_widget = QtWidgets.QWidget()
|
||||||
window.setCentralWidget(main_widget)
|
window.setCentralWidget(main_widget)
|
||||||
window.show()
|
window.show()
|
||||||
|
|
||||||
pxr: float = main_widget.devicePixelRatioF()
|
_main_pxr: float = main_widget.devicePixelRatioF()
|
||||||
|
|
||||||
# explicitly get main widget and primary displays
|
# explicitly get main widget and primary displays
|
||||||
current_screen: QtGui.QScreen = app.screenAt(
|
current_screen: QtGui.QScreen = app.screenAt(
|
||||||
|
|
@ -77,7 +91,13 @@ for screen in app.screens():
|
||||||
name: str = screen.name()
|
name: str = screen.name()
|
||||||
model: str = screen.model().rstrip()
|
model: str = screen.model().rstrip()
|
||||||
size: QSize = screen.size()
|
size: QSize = screen.size()
|
||||||
geo: QRect = screen.availableGeometry()
|
geo: QRect = screen.geometry()
|
||||||
|
|
||||||
|
# device-pixel-ratio
|
||||||
|
# https://doc.qt.io/qt-6/highdpi.html
|
||||||
|
pxr: float = screen.devicePixelRatio()
|
||||||
|
|
||||||
|
unscaled_size: QSize = pxr * size
|
||||||
phydpi: float = screen.physicalDotsPerInch()
|
phydpi: float = screen.physicalDotsPerInch()
|
||||||
logdpi: float = screen.logicalDotsPerInch()
|
logdpi: float = screen.logicalDotsPerInch()
|
||||||
is_primary: bool = screen is primary_screen
|
is_primary: bool = screen is primary_screen
|
||||||
|
|
@ -88,11 +108,12 @@ for screen in app.screens():
|
||||||
f'|_primary: {is_primary}\n'
|
f'|_primary: {is_primary}\n'
|
||||||
f' _current: {is_current}\n'
|
f' _current: {is_current}\n'
|
||||||
f' _model: {model}\n'
|
f' _model: {model}\n'
|
||||||
f' _screen size: {size}\n'
|
f' _size: {size}\n'
|
||||||
f' _screen geometry: {geo}\n'
|
f' _geometry: {geo}\n'
|
||||||
f' _devicePixelRationF(): {pxr}\n'
|
f' _devicePixelRatio(): {pxr}\n'
|
||||||
f' _physical dpi: {phydpi}\n'
|
f' _unscaled-size: {unscaled_size!r}\n'
|
||||||
f' _logical dpi: {logdpi}\n'
|
f' _physical-dpi: {phydpi}\n'
|
||||||
|
f' _logical-dpi: {logdpi}\n'
|
||||||
)
|
)
|
||||||
|
|
||||||
# app-wide font info
|
# app-wide font info
|
||||||
|
|
@ -110,8 +131,8 @@ str_w: int = str_br.width()
|
||||||
|
|
||||||
print(
|
print(
|
||||||
f'------ global font settings ------\n'
|
f'------ global font settings ------\n'
|
||||||
f'font dpi: {fontdpi}\n'
|
f'font dpi: {fontdpi!r}\n'
|
||||||
f'font height: {font_h}\n'
|
f'font height: {font_h!r}\n'
|
||||||
f'string bounding rect: {str_br}\n'
|
f'string bounding rect: {str_br!r}\n'
|
||||||
f'string width : {str_w}\n'
|
f'string width : {str_w!r}\n'
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
import pytest
|
||||||
|
from piker.ui._style import DpiAwareFont
|
||||||
|
|
||||||
|
|
||||||
|
class MockScreen:
|
||||||
|
def __init__(self, pdpi, ldpi, name="MockScreen"):
|
||||||
|
self._pdpi = pdpi
|
||||||
|
self._ldpi = ldpi
|
||||||
|
self._name = name
|
||||||
|
|
||||||
|
def physicalDotsPerInch(self):
|
||||||
|
return self._pdpi
|
||||||
|
|
||||||
|
def logicalDotsPerInch(self):
|
||||||
|
return self._ldpi
|
||||||
|
|
||||||
|
def name(self):
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"pdpi, ldpi, expected_px",
|
||||||
|
[
|
||||||
|
(96, 96, 9), # normal DPI
|
||||||
|
(169, 96, 15), # HiDPI
|
||||||
|
(120, 96, 10), # mid-DPI
|
||||||
|
]
|
||||||
|
)
|
||||||
|
def test_font_px_size(pdpi, ldpi, expected_px):
|
||||||
|
font = DpiAwareFont()
|
||||||
|
font.configure_to_dpi(screen=MockScreen(pdpi, ldpi))
|
||||||
|
|
||||||
|
px = font.px_size
|
||||||
|
print(f"{pdpi}x{ldpi} DPI -> Computed pixel size: {px}")
|
||||||
|
|
||||||
|
assert px == expected_px
|
||||||
10
uv.lock
10
uv.lock
|
|
@ -955,16 +955,16 @@ wheels = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pdbp"
|
name = "pdbp"
|
||||||
version = "1.8.2"
|
version = "1.8.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||||
{ name = "pygments" },
|
{ name = "pygments" },
|
||||||
{ name = "tabcompleter" },
|
{ name = "tabcompleter" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/50/91/2d614b0db12840d646159f65510415ade0db9db595d6dee3eac60dfe9302/pdbp-1.8.2.tar.gz", hash = "sha256:367c25c17555d3ac1f024b9ad494ff50e6e20f6494a84741487f3e6596d88f94", size = 25843, upload-time = "2026-01-14T03:10:28.134Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/fc/f5/794ef06a84b4aea5619cda8956aefb838c6b4849002079dca3bc8955f6e3/pdbp-1.8.1.tar.gz", hash = "sha256:e2acef6b14567b5599f624aec7378139cba086695c13a4e7e327ccb235c3a00b", size = 25812, upload-time = "2025-11-02T18:15:27.098Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/51/fe/53ac0cd932db5dcaf55961bc7cb7afdca8d80d8cc7406ed661f0c7dc111a/pdbp-1.8.2-py3-none-any.whl", hash = "sha256:d4fd05e177636b5ccd0b2e03e378cec57afc06149e5fd975de6f8ddb3d0109a8", size = 21969, upload-time = "2026-01-14T03:10:27.062Z" },
|
{ url = "https://files.pythonhosted.org/packages/75/58/3af430d0de0b95d5adf7e576067e07d750ba76e28d142871982464fb40db/pdbp-1.8.1-py3-none-any.whl", hash = "sha256:643e8c84df7c09542c0c7c3f0f18a6c2fb4fb372f9f054ceca80a9037db986a5", size = 21950, upload-time = "2025-11-02T18:15:25.923Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1115,7 +1115,7 @@ dev = [
|
||||||
{ name = "cython", specifier = ">=3.0.0,<4.0.0" },
|
{ name = "cython", specifier = ">=3.0.0,<4.0.0" },
|
||||||
{ name = "greenback", specifier = ">=1.1.1,<2.0.0" },
|
{ name = "greenback", specifier = ">=1.1.1,<2.0.0" },
|
||||||
{ name = "i3ipc", specifier = ">=2.2.1" },
|
{ name = "i3ipc", specifier = ">=2.2.1" },
|
||||||
{ name = "pdbp", specifier = ">=1.8.2,<2.0.0" },
|
{ name = "pdbp", specifier = ">=1.5.0,<2.0.0" },
|
||||||
{ name = "prompt-toolkit", specifier = "==3.0.40" },
|
{ name = "prompt-toolkit", specifier = "==3.0.40" },
|
||||||
{ name = "pyperclip", specifier = ">=1.9.0" },
|
{ name = "pyperclip", specifier = ">=1.9.0" },
|
||||||
{ name = "pyqt6", specifier = ">=6.7.0,<7.0.0" },
|
{ name = "pyqt6", specifier = ">=6.7.0,<7.0.0" },
|
||||||
|
|
@ -1128,7 +1128,7 @@ dev = [
|
||||||
lint = [{ name = "ruff", specifier = ">=0.9.6" }]
|
lint = [{ name = "ruff", specifier = ">=0.9.6" }]
|
||||||
repl = [
|
repl = [
|
||||||
{ name = "greenback", specifier = ">=1.1.1,<2.0.0" },
|
{ name = "greenback", specifier = ">=1.1.1,<2.0.0" },
|
||||||
{ name = "pdbp", specifier = ">=1.8.2,<2.0.0" },
|
{ name = "pdbp", specifier = ">=1.5.0,<2.0.0" },
|
||||||
{ name = "prompt-toolkit", specifier = "==3.0.40" },
|
{ name = "prompt-toolkit", specifier = "==3.0.40" },
|
||||||
{ name = "pyperclip", specifier = ">=1.9.0" },
|
{ name = "pyperclip", specifier = ">=1.9.0" },
|
||||||
{ name = "xonsh" },
|
{ name = "xonsh" },
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue