Compare commits

..

4 Commits

Author SHA1 Message Date
Gud Boi bd812bd2dd Merge pull request 'pdbp_bump: to latest version, readme/pyproject tweaks' (#66) from pdbp_bump into main
Reviewed-on: #66
2026-01-15 19:17:30 +00:00
Gud Boi 664be2cd0b Another little `pyproject` rejig
Adding links to `uv` stuff and cleaning up old cruft from before recent
flash landing of various feature/dev branches.
2026-01-14 15:29:26 -05:00
Gud Boi 6f0f926259 Fix `uv sync` flags in readme
Much thx to @momo for pointing out that we were still documenting the
old `--extra` flags (which are for `[optional-dependencies]`, see docs
https://docs.astral.sh/uv/concepts/projects/dependencies/#optional-dependencies)
but we're now using "dev dependency-groups"
(https://docs.astral.sh/uv/concepts/projects/dependencies/#dependency-groups)
which instead use the `--group` flag.
2026-01-14 15:27:13 -05:00
Gud Boi eab9dfcd13 Update `pdbp` to latest release
Since i fixed a UX regression that's critical for our dev tooling.
See the patch @ https://github.com/mdmintz/pdbp/pull/83
2026-01-14 09:49:50 -05:00
7 changed files with 86 additions and 207 deletions

View File

@ -95,12 +95,15 @@ 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 --extra uis uv sync --group uis
AND with all our hacking tools and WIP integrations:: AND with **all** our normal hacking tools::
uv sync --dev --all-extras uv sync --dev
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::

View File

@ -182,27 +182,24 @@ 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 * pdpi) font_size = math.floor(inches * dpi)
ftype: str = f'{type(self)!r}' log.debug(
log.info( f"screen:{screen.name()}\n"
f'screen: {screen.name()}\n' f"pDPI: {pdpi}, lDPI: {ldpi}, scale: {scale}\n"
f'pDPI: {pdpi!r}\n' f"\nOur best guess font size is {font_size}\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: QtCore.QRectF = self._qfm.boundingRect(value) unscaled_br = self._qfm.boundingRect(value)
return QtCore.QRectF( return QtCore.QRectF(
0, 0,
0, 0,

View File

@ -77,54 +77,42 @@ 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]
# TODO: add an `--only daemon` group for running non-ui / pikerd # uis = []
# service tree in distributed mode B) # ?TODO? really we should be able to mv this `uis` group
# 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 = [
# https://docs.astral.sh/uv/concepts/projects/dependencies/#optional-dependencies "pyqtgraph",
# TODO: make sure the levenshtein shit compiles on nix.. "qdarkstyle >=3.0.2, <4.0.0",
# rapidfuzz = {extras = ["speedup"], version = "^0.18.0"} "pyqt6 >=6.7.0, <7.0.0",
"rapidfuzz >=3.2.0, <4.0.0",
"qdarkstyle >=3.0.2, <4.0.0",
"pyqt6 >=6.7.0, <7.0.0",
"pyqtgraph",
# for consideration, # fuzzy search
# - 'visidata' "rapidfuzz >=3.2.0, <4.0.0",
"qdarkstyle >=3.0.2, <4.0.0",
"pyqt6 >=6.7.0, <7.0.0",
"pyqtgraph",
] ]
# TODO: a toolset that makes debugging a `pikerd` service (tree) easy # dev deps enabled by `uv --dev`
# to hack on directly using more or less the local env: # https://docs.astral.sh/uv/concepts/projects/dependencies/#development-dependencies
# - 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",
@ -136,13 +124,34 @@ 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'",
# ; defined('IN_NIX_SHELL')", # ?TODO? since ^ markers won't work, use a deps-flags to toggle for
# now.
] ]
dbs = [ dbs = [
"elasticsearch >=8.9.0, <9.0.0", "elasticsearch >=8.9.0, <9.0.0",
@ -177,15 +186,6 @@ 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" }

View File

@ -1,64 +0,0 @@
#!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'
)

View File

@ -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,11 +43,6 @@ 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
@ -63,22 +58,13 @@ 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()
_main_pxr: float = main_widget.devicePixelRatioF() 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(
@ -91,13 +77,7 @@ 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.geometry() geo: QRect = screen.availableGeometry()
# 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
@ -108,12 +88,11 @@ 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' _size: {size}\n' f' _screen size: {size}\n'
f' _geometry: {geo}\n' f' _screen geometry: {geo}\n'
f' _devicePixelRatio(): {pxr}\n' f' _devicePixelRationF(): {pxr}\n'
f' _unscaled-size: {unscaled_size!r}\n' f' _physical dpi: {phydpi}\n'
f' _physical-dpi: {phydpi}\n' f' _logical dpi: {logdpi}\n'
f' _logical-dpi: {logdpi}\n'
) )
# app-wide font info # app-wide font info
@ -131,8 +110,8 @@ str_w: int = str_br.width()
print( print(
f'------ global font settings ------\n' f'------ global font settings ------\n'
f'font dpi: {fontdpi!r}\n' f'font dpi: {fontdpi}\n'
f'font height: {font_h!r}\n' f'font height: {font_h}\n'
f'string bounding rect: {str_br!r}\n' f'string bounding rect: {str_br}\n'
f'string width : {str_w!r}\n' f'string width : {str_w}\n'
) )

View File

@ -1,36 +0,0 @@
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
View File

@ -955,16 +955,16 @@ wheels = [
[[package]] [[package]]
name = "pdbp" name = "pdbp"
version = "1.8.1" version = "1.8.2"
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/fc/f5/794ef06a84b4aea5619cda8956aefb838c6b4849002079dca3bc8955f6e3/pdbp-1.8.1.tar.gz", hash = "sha256:e2acef6b14567b5599f624aec7378139cba086695c13a4e7e327ccb235c3a00b", size = 25812, upload-time = "2025-11-02T18:15:27.098Z" } 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" }
wheels = [ wheels = [
{ 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" }, { 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" },
] ]
[[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.5.0,<2.0.0" }, { name = "pdbp", specifier = ">=1.8.2,<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.5.0,<2.0.0" }, { name = "pdbp", specifier = ">=1.8.2,<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" },