Compare commits

..

13 Commits

Author SHA1 Message Date
Tyler Goodlet 4791c878f7 Uhh ok, apparently this osenv var is just idiotic?
See https://www.pikers.dev/pikers/piker/issues/50#issuecomment-1041 for
deatz.
2025-12-19 19:29:48 -05:00
Tyler Goodlet 24f5cbd4d6 binance: handle new `TRADIFI_PERPETUAL`.. 2025-12-19 19:29:48 -05:00
Tyler Goodlet 658f96e726 Update `default.nix` (from @nt) for py313 2025-12-19 19:29:48 -05:00
Tyler Goodlet 05d5f8e2c8 nix: make Qt6 work on wayland
Taking many tips from our `default.nix` (thanks @nt!) this seems to be
the minimal overlay required for a flake to get up and running with
`piker chart` B)

Notes,
- for now, we're pinning to a major `cpython` version (3.13)
- ensure we (can) build with `nixpkgs.qt6.qtwayland`
- add the minimal Qt ld-lib-path linkings including those for plugin
  use (required for wayland mode).
- for now, hardcode "wayland" platform-mode and the linux standard
  "xdg-shell" integration.
- leave some TODOs to better parameterize around py versions.
2025-12-19 19:29:48 -05:00
Tyler Goodlet 0e39bd7bb2 Touch `conf.toml` by default when dne? 2025-12-19 19:29:48 -05:00
Tyler Goodlet 6551d323a1 Bump `flake.lock`, seemly nicely minimized B) 2025-12-19 19:29:48 -05:00
Tyler Goodlet 3ab19f27ea Redo `flake.nix` using `pyproject.nix` recos
Particularly using their recommended "impure template",
- https://pyproject-nix.github.io/pyproject.nix/templates.html#impure
- code: https://github.com/pyproject-nix/pyproject.nix/blob/master/templates/impure/flake.nix

Note the `shellHook` now contains various `uv`-specific osenv settings
and cmds to get a dev-env setup the way i would do it by default, that
includes all dev and extra (group) deps. For now i've hard coded the
"virt-env subdir" used by `uv` to match the cpython version. We can
obviously parameterize this much better in the future.

For those who want to spawn a diff shell then bash see the commented
line, for ex. i personally use `nix develop -c uv run xonsh`.
2025-12-19 19:29:48 -05:00
Tyler Goodlet 17e975897f Don't pin `pendulum` version so we can use wheel
Bump version in lock file to match.
2025-12-19 19:29:48 -05:00
Tyler Goodlet ca6e922f35 binance: add `Pair.opoAllowed` field
Handle new API field per 2025-12-02 update.

(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
2025-12-19 19:29:48 -05:00
Tyler Goodlet e63cffaf53 Add `.xsh` script mentioned in gitea #50
Note since it's actually `xonsh` code run with either,
- most pedantically: `xonsh ./snippets/calc_ppi.xsh`
- or relying on how shebang: `./snippets/calc_ppi.xsh`
  * an sheboom.
2025-12-19 19:29:15 -05:00
Tyler Goodlet 49bedb4912 Reorder imports in `qt_screen_info.py` ??
For wtv reason on nixos importing `pyqtgraph` first is causing `numpy`
to fail import?? No idea, but likely something to do with recent
`flake.nix`'s ld-lib-linking with `<nixpkgs>` marlarky?
2025-12-18 18:24:19 -05:00
Tyler Goodlet 35744f666f Add some Qt DPI extras to `qt_screen_info.py`
- set `QT_USE_PHYSICAL_DPI='1'` env var for Qt6 high-DPI
  * we likely want to do this in `piker.ui` as well!
- move `pxr` calc from widget to per-screen in loop.
- add `unscaled_size` calc using `pxr * size`.
- switch from `.availableGeometry()` to `.geometry()` for full
  bounds.
- shorten output labels, add `!r` repr formatting
- add Qt6 DPI rounding policy TODO with doc links

(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
2025-12-18 18:19:50 -05:00
Tyler Goodlet 6f9b7320e5 Re-fmt and `.info()` the `.configure_to_dpi()` DPI calcs for now 2025-12-18 18:19:50 -05:00
4 changed files with 113 additions and 20 deletions

View File

@ -104,6 +104,9 @@ class Pair(Struct, frozen=True, kw_only=True):
# https://developers.binance.com/docs/binance-spot-api-docs#future-changes
pegInstructionsAllowed: bool = False
# https://developers.binance.com/docs/binance-spot-api-docs#2025-12-02
opoAllowed: bool = False
filters: dict[
str,
str | int | float,

View File

@ -184,22 +184,25 @@ class DpiAwareFont:
self._font_inches = inches
font_size = math.floor(inches * pdpi)
log.debug(
f"screen:{screen.name()}\n"
f"pDPI: {pdpi}, lDPI: {ldpi}, scale: {scale}\n"
f"\nOur best guess font size is {font_size}\n"
ftype: str = f'{type(self)!r}'
log.info(
f'screen: {screen.name()}\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
self._set_qfont_px_size(font_size)
def boundingRect(self, value: str) -> QtCore.QRectF:
screen = self.screen
if screen is None:
if (screen := self.screen) is None:
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(
0,
0,

View File

@ -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'
)

View File

@ -31,6 +31,7 @@ Resource list for mucking with DPIs on multiple screens:
- https://doc.qt.io/qt-5/qguiapplication.html#screenAt
'''
import os
from PyQt6 import (
QtCore,
@ -44,6 +45,12 @@ from PyQt6.QtCore import (
)
from pyqtgraph import QtGui
# https://doc.qt.io/qt-6/highdpi.html#environment-variable-reference
os.environ['QT_USE_PHYSICAL_DPI'] = '0'
# TODO? i don't get how this is useful, when i set it it seems
# the physical-dpi get's computed incorrectly??
# Proper high DPI scaling is available in Qt >= 5.6.0. This attibute
# must be set before creating the application
if hasattr(Qt, 'AA_EnableHighDpiScaling'):
@ -58,13 +65,22 @@ if hasattr(Qt, 'AA_UseHighDpiPixmaps'):
True,
)
# NOTE, inherits `QGuiApplication`
# https://doc.qt.io/qt-6/qapplication.html
# https://doc.qt.io/qt-6/qguiapplication.html
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()
main_widget = QtWidgets.QWidget()
window.setCentralWidget(main_widget)
window.show()
pxr: float = main_widget.devicePixelRatioF()
_main_pxr: float = main_widget.devicePixelRatioF()
# explicitly get main widget and primary displays
current_screen: QtGui.QScreen = app.screenAt(
@ -77,7 +93,13 @@ for screen in app.screens():
name: str = screen.name()
model: str = screen.model().rstrip()
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()
logdpi: float = screen.logicalDotsPerInch()
is_primary: bool = screen is primary_screen
@ -88,11 +110,12 @@ for screen in app.screens():
f'|_primary: {is_primary}\n'
f' _current: {is_current}\n'
f' _model: {model}\n'
f' _screen size: {size}\n'
f' _screen geometry: {geo}\n'
f' _devicePixelRationF(): {pxr}\n'
f' _physical dpi: {phydpi}\n'
f' _logical dpi: {logdpi}\n'
f' _size: {size}\n'
f' _geometry: {geo}\n'
f' _devicePixelRatio(): {pxr}\n'
f' _unscaled-size: {unscaled_size!r}\n'
f' _physical-dpi: {phydpi}\n'
f' _logical-dpi: {logdpi}\n'
)
# app-wide font info
@ -110,8 +133,8 @@ str_w: int = str_br.width()
print(
f'------ global font settings ------\n'
f'font dpi: {fontdpi}\n'
f'font height: {font_h}\n'
f'string bounding rect: {str_br}\n'
f'string width : {str_w}\n'
f'font dpi: {fontdpi!r}\n'
f'font height: {font_h!r}\n'
f'string bounding rect: {str_br!r}\n'
f'string width : {str_w!r}\n'
)