diff --git a/config/conf.toml b/config/conf.toml index a14f6bdd..1f2a64bc 100644 --- a/config/conf.toml +++ b/config/conf.toml @@ -1,7 +1,9 @@ [network] -tsdb.backend = 'marketstore' -tsdb.host = 'localhost' -tsdb.grpc_port = 5995 +pikerd = [ + '/ipv4/127.0.0.1/tcp/6116', # std localhost daemon-actor tree + # '/uds/6116', # TODO std uds socket file +] + [ui] # set custom font + size which will scale entire UI diff --git a/notes_to_self.rst b/notes_to_self/ideas.rst similarity index 100% rename from notes_to_self.rst rename to notes_to_self/ideas.rst diff --git a/piker/cli/__init__.py b/piker/cli/__init__.py index dde7f83c..bf26d5ab 100644 --- a/piker/cli/__init__.py +++ b/piker/cli/__init__.py @@ -189,28 +189,9 @@ def pikerd( # AsyncExitStack() as stack, ): - # TODO: spawn all other sub-actor daemons according to - # multiaddress endpoint spec defined by user config assert service_mngr - - # if tsdb: - # dname, conf = await stack.enter_async_context( - # service.marketstore.start_ahab_daemon( - # service_mngr, - # loglevel=loglevel, - # ) - # ) - # log.info(f'TSDB `{dname}` up with conf:\n{conf}') - - # if es: - # dname, conf = await stack.enter_async_context( - # service.elastic.start_ahab_daemon( - # service_mngr, - # loglevel=loglevel, - # ) - # ) - # log.info(f'DB `{dname}` up with conf:\n{conf}') - + # ?TODO? spawn all other sub-actor daemons according to + # multiaddress endpoint spec defined by user config await trio.sleep_forever() trio.run(main) diff --git a/piker/config.py b/piker/config.py index 97eb4881..e6d3e60a 100644 --- a/piker/config.py +++ b/piker/config.py @@ -41,10 +41,13 @@ from .log import get_logger log = get_logger('broker-config') -# XXX NOTE: taken from ``click`` since apparently they have some -# super weirdness with sigint and sudo..no clue -# we're probably going to slowly just modify it to our own version over -# time.. +# XXX NOTE: taken from `click` +# |_https://github.com/pallets/click/blob/main/src/click/utils.py#L449 +# +# (since apparently they have some super weirdness with SIGINT and +# sudo.. no clue we're probably going to slowly just modify it to our +# own version over time..) +# def get_app_dir( app_name: str, roaming: bool = True, @@ -261,7 +264,7 @@ def load( MutableMapping, ] = tomllib.loads, - touch_if_dne: bool = False, + touch_if_dne: bool = True, **tomlkws, @@ -270,7 +273,7 @@ def load( Load config file by name. If desired config is not in the top level piker-user config path then - pass the ``path: Path`` explicitly. + pass the `path: Path` explicitly. ''' # create the $HOME/.config/piker dir if dne @@ -285,7 +288,8 @@ def load( if ( not path.is_file() - and touch_if_dne + and + touch_if_dne ): # only do a template if no path provided, # just touch an empty file with same name. diff --git a/piker/data/_sampling.py b/piker/data/_sampling.py index e5b87a2a..cc32af91 100644 --- a/piker/data/_sampling.py +++ b/piker/data/_sampling.py @@ -740,7 +740,7 @@ async def sample_and_broadcast( log.warning( f'Feed OVERRUN {sub_key}' - '@{bus.brokername} -> \n' + f'@{bus.brokername} -> \n' f'feed @ {chan.uid}\n' f'throttle = {throttle} Hz' ) diff --git a/piker/data/_symcache.py b/piker/data/_symcache.py index bcaa5844..1f1cb9ec 100644 --- a/piker/data/_symcache.py +++ b/piker/data/_symcache.py @@ -91,6 +91,18 @@ class SymbologyCache(Struct): # provided by the backend pkg. mktmaps: dict[str, MktPair] = field(default_factory=dict) + def pformat(self) -> str: + return ( + f'<{type(self).__name__}(\n' + f' .mod: {self.mod!r}\n' + f' .assets: {len(self.assets)!r}\n' + f' .pairs: {len(self.pairs)!r}\n' + f' .mktmaps: {len(self.mktmaps)!r}\n' + f')>' + ) + + __repr__ = pformat + def write_config(self) -> None: # put the backend's pair-struct type ref at the top diff --git a/piker/data/feed.py b/piker/data/feed.py index 7264c8e6..df4106e0 100644 --- a/piker/data/feed.py +++ b/piker/data/feed.py @@ -352,7 +352,9 @@ async def allocate_persistent_feed( # yield back control to starting nursery once we receive either # some history or a real-time quote. - log.info(f'loading OHLCV history: {fqme}') + log.info( + f'loading OHLCV history: {fqme!r}\n' + ) await some_data_ready.wait() flume = Flume( @@ -786,7 +788,6 @@ async def install_brokerd_search( @acm async def maybe_open_feed( - fqmes: list[str], loglevel: str | None = None, @@ -840,13 +841,12 @@ async def maybe_open_feed( @acm async def open_feed( - fqmes: list[str], - loglevel: str | None = None, + loglevel: str|None = None, allow_overruns: bool = True, start_stream: bool = True, - tick_throttle: float | None = None, # Hz + tick_throttle: float|None = None, # Hz allow_remote_ctl_ui: bool = False, diff --git a/piker/data/flows.py b/piker/data/flows.py index 677b2f69..573180b9 100644 --- a/piker/data/flows.py +++ b/piker/data/flows.py @@ -36,10 +36,10 @@ from ._sharedmem import ( ShmArray, _Token, ) +from piker.accounting import MktPair if TYPE_CHECKING: - from ..accounting import MktPair - from .feed import Feed + from piker.data.feed import Feed class Flume(Struct): @@ -82,7 +82,7 @@ class Flume(Struct): # TODO: do we need this really if we can pull the `Portal` from # ``tractor``'s internals? - feed: Feed | None = None + feed: Feed|None = None @property def rt_shm(self) -> ShmArray: diff --git a/piker/data/validate.py b/piker/data/validate.py index cefa0f1f..c5317ede 100644 --- a/piker/data/validate.py +++ b/piker/data/validate.py @@ -113,9 +113,9 @@ def validate_backend( ) if ep is None: log.warning( - f'Provider backend {mod.name} is missing ' - f'{daemon_name} support :(\n' - f'The following endpoint is missing: {name}' + f'Provider backend {mod.name!r} is missing ' + f'{daemon_name!r} support?\n' + f'|_module endpoint-func missing: {name!r}\n' ) inits: list[ diff --git a/piker/ui/_style.py b/piker/ui/_style.py index 302d9d30..196d6fd8 100644 --- a/piker/ui/_style.py +++ b/piker/ui/_style.py @@ -269,6 +269,8 @@ def hcolor(name: str) -> str: # default ohlc-bars/curve gray 'bracket': '#666666', # like the logo + 'pikers': '#616161', # a trader shade of.. + 'beast': '#161616', # in the dark alone. # bluish 'charcoal': '#36454F', diff --git a/snippets/qt_screen_info.py b/snippets/qt_screen_info.py index 238367c0..9862a9b8 100644 --- a/snippets/qt_screen_info.py +++ b/snippets/qt_screen_info.py @@ -1,4 +1,22 @@ -""" +# piker: trading gear for hackers +# Copyright (C) Tyler Goodlet (in stewardship for pikers) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +''' +A per-display, DPI (scaling) info dumper. + Resource list for mucking with DPIs on multiple screens: - https://stackoverflow.com/questions/42141354/convert-pixel-size-to-point-size-for-fonts-on-multiple-platforms @@ -12,89 +30,86 @@ Resource list for mucking with DPIs on multiple screens: - https://stackoverflow.com/questions/16561879/what-is-the-difference-between-logicaldpix-and-physicaldpix-in-qt - https://doc.qt.io/qt-5/qguiapplication.html#screenAt -""" +''' from pyqtgraph import QtGui -from PyQt5.QtCore import ( - Qt, QCoreApplication +from PyQt6 import ( + QtCore, + QtWidgets, +) +from PyQt6.QtCore import ( + Qt, + QCoreApplication, + QSize, + QRect, ) # 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'): - QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True) + QCoreApplication.setAttribute( + Qt.AA_EnableHighDpiScaling, + True, + ) if hasattr(Qt, 'AA_UseHighDpiPixmaps'): - QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True) + QCoreApplication.setAttribute( + Qt.AA_UseHighDpiPixmaps, + True, + ) - -app = QtGui.QApplication([]) -window = QtGui.QMainWindow() -main_widget = QtGui.QWidget() +app = QtWidgets.QApplication([]) +window = QtWidgets.QMainWindow() +main_widget = QtWidgets.QWidget() window.setCentralWidget(main_widget) window.show() -pxr = main_widget.devicePixelRatioF() +pxr: float = main_widget.devicePixelRatioF() -# screen_num = app.desktop().screenNumber() -# screen = app.screens()[screen_num] - -screen = app.screenAt(main_widget.geometry().center()) - -name = screen.name() -size = screen.size() -geo = screen.availableGeometry() -phydpi = screen.physicalDotsPerInch() -logdpi = screen.logicalDotsPerInch() - -print( - # f'screen number: {screen_num}\n', - f'screen name: {name}\n' - f'screen size: {size}\n' - f'screen geometry: {geo}\n\n' - f'devicePixelRationF(): {pxr}\n' - f'physical dpi: {phydpi}\n' - f'logical dpi: {logdpi}\n' +# explicitly get main widget and primary displays +current_screen: QtGui.QScreen = app.screenAt( + main_widget.geometry().center() ) +primary_screen: QtGui.QScreen = app.primaryScreen() -print('-'*50) +screen: QtGui.QScreen +for screen in app.screens(): + name: str = screen.name() + model: str = screen.model().rstrip() + size: QSize = screen.size() + geo: QRect = screen.availableGeometry() + phydpi: float = screen.physicalDotsPerInch() + logdpi: float = screen.logicalDotsPerInch() + is_primary: bool = screen is primary_screen + is_current: bool = screen is current_screen -screen = app.primaryScreen() + print( + f'------ screen name: {name} ------\n' + 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' + ) -name = screen.name() -size = screen.size() -geo = screen.availableGeometry() -phydpi = screen.physicalDotsPerInch() -logdpi = screen.logicalDotsPerInch() - -print( - # f'screen number: {screen_num}\n', - f'screen name: {name}\n' - f'screen size: {size}\n' - f'screen geometry: {geo}\n\n' - f'devicePixelRationF(): {pxr}\n' - f'physical dpi: {phydpi}\n' - f'logical dpi: {logdpi}\n' -) - - -# app-wide font +# app-wide font info font = QtGui.QFont("Hack") # use pixel size to be cross-resolution compatible? font.setPixelSize(6) - fm = QtGui.QFontMetrics(font) -fontdpi = fm.fontDpi() -font_h = fm.height() - -string = '10000' -str_br = fm.boundingRect(string) -str_w = str_br.width() +fontdpi: float = fm.fontDpi() +font_h: int = fm.height() +string: str = '10000' +str_br: QtCore.QRect = fm.boundingRect(string) +str_w: int = str_br.width() print( - # f'screen number: {screen_num}\n', + f'------ global font settings ------\n' f'font dpi: {fontdpi}\n' f'font height: {font_h}\n' f'string bounding rect: {str_br}\n' diff --git a/tags b/tags new file mode 100644 index 00000000..5b077243 --- /dev/null +++ b/tags @@ -0,0 +1 @@ +TAG_feed_status_update ./piker/data/feed.py /TAG_feed_status_update/