From 44403bea2bb44d2898bf1a12cfb77acd03a0fe50 Mon Sep 17 00:00:00 2001 From: Hector van der Aa Date: Tue, 7 Jul 2026 23:00:49 +0100 Subject: [PATCH 1/3] Improve gauge grid layout --- README.md | 6 +- docs/API_REFERENCE.md | 5 +- docs/EXAMPLES.md | 1 + examples/layout_grid.py | 64 ++++++++++++ src/dpg_gauges/widget.py | 150 ++++++++++++++++++++++++++-- tests/test_step3_widget_renderer.py | 44 ++++++++ 6 files changed, 260 insertions(+), 10 deletions(-) create mode 100644 examples/layout_grid.py diff --git a/README.md b/README.md index 5b23b57..1b546e1 100644 --- a/README.md +++ b/README.md @@ -37,12 +37,16 @@ dpg.destroy_context() ```python with dpg.window(label="Engine"): with dpgg.gauge_panel(label="Powertrain", width=-1, height=260): - with dpgg.gauge_grid(columns=3): + with dpgg.gauge_grid(columns=3, min_column_width=180): dpgg.analog_gauge(tag="rpm", label="RPM", max_value=8000, redline_start=6500) dpgg.bar_gauge(tag="boost", label="Boost", max_value=30, unit="psi") dpgg.status_light(tag="ecu", label="ECU", state=True) ``` +`gauge_grid` is a wrapping, table-backed layout. `columns` is a maximum; if the parent is too +narrow for `columns * min_column_width`, the grid uses fewer columns and continues on the next row +instead of creating a horizontal scrollbar. Gauges with `width=0` or `width=-1` fill their grid cell. + Gauges also accept Dear PyGui's usual `parent` argument for adding a gauge to an existing container after that container has already been created: diff --git a/docs/API_REFERENCE.md b/docs/API_REFERENCE.md index b4181a6..7a4ab89 100644 --- a/docs/API_REFERENCE.md +++ b/docs/API_REFERENCE.md @@ -24,7 +24,10 @@ Creation functions are context managers and accept common options such as `tag`, ## Layout Helpers - `gauge_panel(**config)`: child-window panel for grouped gauges. -- `gauge_grid(**config)`: lightweight horizontal gauge group. +- `gauge_grid(columns=1, min_column_width=180, fit_gauges=True, **config)`: table-backed + wrapping gauge grid. `columns` is the maximum number of columns. If the parent is narrower than + `columns * min_column_width`, the grid uses fewer columns and wraps gauges onto later rows to + avoid horizontal scrolling. Gauges without an explicit positive width fill their grid cell. ## Runtime API diff --git a/docs/EXAMPLES.md b/docs/EXAMPLES.md index d959d5b..e3ea42d 100644 --- a/docs/EXAMPLES.md +++ b/docs/EXAMPLES.md @@ -15,6 +15,7 @@ Run examples with `uv run python examples/.py`. - `thresholds_markers.py` - `animations.py` - `dashboard.py` +- `layout_grid.py` - `sizing.py` - `live_high_rate.py` - `live_worst_case.py` diff --git a/examples/layout_grid.py b/examples/layout_grid.py new file mode 100644 index 0000000..43cfaba --- /dev/null +++ b/examples/layout_grid.py @@ -0,0 +1,64 @@ +# pyright: reportGeneralTypeIssues=false + +import dearpygui.dearpygui as dpg + +import dpg_gauges as dpgg + + +def main() -> None: + dpg.create_context() + try: + with dpg.window(label="Grid layout", width=820, height=620): + dpg.add_text("Three-column grid: fixed column cap, automatic rows") + with dpgg.gauge_panel(label="Wide panel", width=-1, height=270), dpgg.gauge_grid( + columns=3, min_column_width=190 + ): + dpgg.analog_gauge( + tag="grid_rpm", label="RPM", value=4200, max_value=8000, height=190 + ) + dpgg.digital_gauge( + tag="grid_speed", label="Speed", value=88, unit="km/h", height=90 + ) + dpgg.bar_gauge( + tag="grid_boost", label="Boost", value=12.5, max_value=30, unit="psi" + ) + dpgg.status_light(tag="grid_ecu", label="ECU", state=True, height=70) + dpgg.battery_gauge(tag="grid_battery", label="Battery", value=74, height=160) + + dpg.add_spacer(height=8) + dpg.add_text("Narrow panel: columns=3 auto-reduces to avoid horizontal scrolling") + with dpgg.gauge_panel(label="Narrow panel", width=390, height=250), dpgg.gauge_grid( + columns=3, min_column_width=180 + ): + for index, value in enumerate((18, 42, 67, 91, 55), start=1): + dpgg.digital_gauge( + tag=f"narrow_{index}", + label=f"Metric {index}", + value=value, + unit="%", + height=72, + ) + + dpg.add_spacer(height=8) + dpg.add_text("Panels can also occupy grid cells") + with dpgg.gauge_grid(columns=2, min_column_width=240): + with dpgg.gauge_panel(label="Left cell", height=120): + dpgg.segmented_gauge(tag="left_segments", label="Load", value=70, height=80) + with dpgg.gauge_panel(label="Right cell", height=120): + dpgg.multi_value_gauge( + tag="right_values", + label="Sensors", + values={"oil": 82, "fuel": 64, "air": 31}, + height=92, + ) + + dpg.create_viewport(title="dpg-gauges grid layout", width=860, height=660) + dpg.setup_dearpygui() + dpg.show_viewport() + dpg.start_dearpygui() + finally: + dpg.destroy_context() + + +if __name__ == "__main__": + main() diff --git a/src/dpg_gauges/widget.py b/src/dpg_gauges/widget.py index 456544e..51ee1fc 100644 --- a/src/dpg_gauges/widget.py +++ b/src/dpg_gauges/widget.py @@ -3,7 +3,7 @@ from __future__ import annotations from collections.abc import Mapping, Sequence -from dataclasses import dataclass +from dataclasses import dataclass, replace from types import TracebackType from typing import Any, Generic, Literal, TypeVar, cast @@ -42,6 +42,8 @@ ConfigT = TypeVar("ConfigT", bound=GaugeConfig) _dpg_context_active = False _original_create_context = dpg.create_context _original_destroy_context = dpg.destroy_context +_active_grids: list[GridLayoutContext] = [] +_layout_suspend_depth = 0 def _install_context_tracking() -> None: @@ -73,10 +75,14 @@ _install_context_tracking() @dataclass class GaugeContext(Generic[ConfigT]): state: GaugeState + _suspended_layout: bool = False def __enter__(self) -> ConfigT: + global _layout_suspend_depth if _dpg_context_active and dpg.does_item_exist(self.state.container_tag): dpg.push_container_stack(self.state.container_tag) + _layout_suspend_depth += 1 + self._suspended_layout = True return cast(ConfigT, self.state.config) def __exit__( @@ -85,17 +91,27 @@ class GaugeContext(Generic[ConfigT]): exc: BaseException | None, traceback: TracebackType | None, ) -> None: + global _layout_suspend_depth if _dpg_context_active and dpg.does_item_exist(self.state.container_tag): dpg.pop_container_stack() + if self._suspended_layout: + _layout_suspend_depth = max(_layout_suspend_depth - 1, 0) + self._suspended_layout = False @dataclass class LayoutContext: tag: Tag | None + suspend_layout: bool = True + _suspended_layout: bool = False def __enter__(self) -> Tag | None: + global _layout_suspend_depth if self.tag is not None and _dpg_context_active and dpg.does_item_exist(self.tag): dpg.push_container_stack(self.tag) + if self.suspend_layout: + _layout_suspend_depth += 1 + self._suspended_layout = True return self.tag def __exit__( @@ -104,14 +120,69 @@ class LayoutContext: exc: BaseException | None, traceback: TracebackType | None, ) -> None: + global _layout_suspend_depth if self.tag is not None and _dpg_context_active and dpg.does_item_exist(self.tag): dpg.pop_container_stack() + if self._suspended_layout: + _layout_suspend_depth = max(_layout_suspend_depth - 1, 0) + self._suspended_layout = False + + +@dataclass +class GridLayoutContext: + tag: Tag | None + columns: int + min_column_width: int + fit_gauges: bool + row_height: int = 0 + available_width: int = 0 + _next_index: int = 0 + _current_row: Tag | None = None + _suspend_depth: int = 0 + + def __enter__(self) -> Tag | None: + self._suspend_depth = _layout_suspend_depth + if self.tag is not None and _dpg_context_active and dpg.does_item_exist(self.tag): + _active_grids.append(self) + return self.tag + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc: BaseException | None, + traceback: TracebackType | None, + ) -> None: + if _active_grids and _active_grids[-1] is self: + _active_grids.pop() + elif self in _active_grids: + _active_grids.remove(self) + + def next_cell(self) -> tuple[Tag | None, int | None]: + if self.tag is None or not _dpg_context_active or not dpg.does_item_exist(self.tag): + return None, None + if self._next_index % self.columns == 0: + self._current_row = dpg.add_table_row(parent=self.tag, height=self.row_height) + cell = dpg.add_table_cell(parent=self._current_row or self.tag) + self._next_index += 1 + return cell, self.cell_width() + + def cell_width(self) -> int | None: + if self.available_width <= 0: + return None + return max(int(self.available_width / self.columns), 1) def create_gauge_context(gauge_type: str, config: ConfigT) -> GaugeContext[ConfigT]: if not _dpg_context_active: return GaugeContext(register_gauge(gauge_type, config)) + layout_parent, layout_width = _next_layout_cell(config.parent) + if layout_parent is not None: + updates: dict[str, Any] = {"parent": layout_parent} + if layout_width is not None and _current_grid_fits_gauges() and config.width <= 0: + updates["width"] = layout_width + config = replace(config, **updates) + tag = config.tag container_tag = tag if tag is not None else None drawlist_tag = f"{tag}__drawlist" if tag is not None else None @@ -151,6 +222,49 @@ def create_gauge_context(gauge_type: str, config: ConfigT) -> GaugeContext[Confi return GaugeContext(state) +def _next_layout_cell(parent: Tag | None) -> tuple[Tag | None, int | None]: + grid = _current_grid() + if parent is not None or grid is None: + return None, None + return grid.next_cell() + + +def _current_grid() -> GridLayoutContext | None: + if not _active_grids: + return None + grid = _active_grids[-1] + if grid._suspend_depth != _layout_suspend_depth: + return None + return grid + + +def _current_grid_fits_gauges() -> bool: + grid = _current_grid() + return grid.fit_gauges if grid is not None else False + + +def _available_layout_width(parent: Tag | None, width: int) -> int: + if width > 0: + return width + if parent is not None and dpg.does_item_exist(parent): + return max(dpg.get_item_width(parent) or 0, 0) + try: + container = dpg.top_container_stack() + except Exception: + return 0 + if container is not None and dpg.does_item_exist(container): + return max(dpg.get_item_width(container) or 0, 0) + return 0 + + +def _resolved_columns(columns: int, min_column_width: int, available_width: int) -> int: + columns = max(int(columns), 1) + min_column_width = max(int(min_column_width), 0) + if available_width > 0 and min_column_width > 0: + columns = min(columns, max(1, available_width // min_column_width)) + return columns + + def gauge_panel( *, tag: Tag | None = None, @@ -168,6 +282,11 @@ def gauge_panel( """Create a lightweight child-window container for related gauges.""" if not _dpg_context_active: return LayoutContext(None) + layout_parent, layout_width = _next_layout_cell(parent) + if layout_parent is not None: + parent = layout_parent + if width <= 0 and layout_width is not None: + width = layout_width container = dpg.add_child_window( tag=tag or 0, parent=parent or 0, @@ -187,27 +306,42 @@ def gauge_panel( def gauge_grid( *, columns: int = 1, + min_column_width: int = 180, + fit_gauges: bool = True, + row_height: int = 0, tag: Tag | None = None, parent: Tag | None = None, width: int = 0, height: int = 0, show: bool = True, **config: Any, -) -> LayoutContext: - """Create a lightweight horizontal gauge layout container.""" +) -> GridLayoutContext: + """Create a lightweight wrapping gauge layout container.""" if not _dpg_context_active: - return LayoutContext(None) - columns = max(int(columns), 1) - container = dpg.add_group( + return GridLayoutContext(None, 1, min_column_width, fit_gauges) + layout_parent, layout_width = _next_layout_cell(parent) + if layout_parent is not None: + parent = layout_parent + if width <= 0 and layout_width is not None: + width = layout_width + available_width = _available_layout_width(parent, width) + columns = _resolved_columns(columns, min_column_width, available_width) + container = dpg.add_table( tag=tag or 0, parent=parent or 0, width=width, height=height, show=show, - horizontal=columns > 1, + header_row=False, + policy=dpg.mvTable_SizingStretchSame, + scrollX=False, **config, ) - return LayoutContext(container) + for _ in range(columns): + dpg.add_table_column(parent=container, width_stretch=True, init_width_or_weight=1.0) + return GridLayoutContext( + container, columns, min_column_width, fit_gauges, row_height, available_width + ) def analog_gauge( diff --git a/tests/test_step3_widget_renderer.py b/tests/test_step3_widget_renderer.py index e8d8296..9a2f037 100644 --- a/tests/test_step3_widget_renderer.py +++ b/tests/test_step3_widget_renderer.py @@ -1,6 +1,7 @@ # pyright: reportGeneralTypeIssues=false from collections.abc import Generator +from typing import cast import dearpygui.dearpygui as dpg import pytest @@ -9,6 +10,10 @@ import dpg_gauges as dpgg from dpg_gauges.state import clear_registry, get_gauge_state +def _children(item: int | str) -> dict[int, list[int | str]]: + return cast(dict[int, list[int | str]], dpg.get_item_children(item)) + + @pytest.fixture def dpg_context() -> Generator[None]: clear_registry() @@ -76,3 +81,42 @@ def test_panel_and_grid_are_lightweight_containers(dpg_context: None) -> None: assert dpg.does_item_exist("engine") assert dpg.does_item_exist("engine_grid") assert get_gauge_state("temp").renderer is not None + + +def test_grid_columns_wrap_gauges_into_rows(dpg_context: None) -> None: + with dpg.window(label="Dashboard", width=720), dpgg.gauge_grid( + tag="wrap_grid", columns=3, min_column_width=1 + ): + for index in range(5): + dpgg.digital_gauge(tag=f"metric_{index}", value=index, height=60) + + children = _children("wrap_grid") + assert len(children[0]) == 3 + assert len(children[1]) == 2 + assert [len(_children(row)[1]) for row in children[1]] == [3, 2] + + +def test_grid_auto_reduces_columns_to_parent_width(dpg_context: None) -> None: + with dpg.window(label="Narrow", width=380), dpgg.gauge_grid( + tag="narrow_grid", columns=3, min_column_width=180 + ): + for index in range(5): + dpgg.digital_gauge(tag=f"narrow_metric_{index}", value=index, height=60) + + children = _children("narrow_grid") + assert len(children[0]) == 2 + assert len(children[1]) == 3 + assert [len(_children(row)[1]) for row in children[1]] == [2, 2, 1] + + +def test_grid_routes_panels_without_stealing_panel_children(dpg_context: None) -> None: + with dpg.window(label="Nested", width=520), dpgg.gauge_grid(tag="nested_grid", columns=2): + with dpgg.gauge_panel(tag="nested_panel", height=120): + dpgg.digital_gauge(tag="inside_panel", value=1, height=60) + dpgg.digital_gauge(tag="beside_panel", value=2, height=60) + + panel_cell = cast(int | str, dpg.get_item_parent("nested_panel")) + assert dpg.get_item_type(panel_cell) == "mvAppItemType::mvTableCell" + assert dpg.get_item_parent("inside_panel") == "nested_panel" + beside_cell = cast(int | str, dpg.get_item_parent("beside_panel")) + assert dpg.get_item_type(beside_cell) == "mvAppItemType::mvTableCell" From 5bd819d812069cc521c337124dc46a1dd33a4735 Mon Sep 17 00:00:00 2001 From: Hector van der Aa Date: Tue, 7 Jul 2026 23:06:53 +0100 Subject: [PATCH 2/3] Clarify grid autobreak behavior --- README.md | 8 +++++--- docs/API_REFERENCE.md | 12 ++++++++---- examples/layout_grid.py | 9 +++++---- src/dpg_gauges/widget.py | 26 ++++++++++++++++++++------ tests/test_step3_widget_renderer.py | 14 ++++++++++++++ 5 files changed, 52 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 1b546e1..2da3792 100644 --- a/README.md +++ b/README.md @@ -43,9 +43,11 @@ with dpg.window(label="Engine"): dpgg.status_light(tag="ecu", label="ECU", state=True) ``` -`gauge_grid` is a wrapping, table-backed layout. `columns` is a maximum; if the parent is too -narrow for `columns * min_column_width`, the grid uses fewer columns and continues on the next row -instead of creating a horizontal scrollbar. Gauges with `width=0` or `width=-1` fill their grid cell. +`gauge_grid` is a wrapping, table-backed layout. An integer `columns` value is a maximum; if the +parent is too narrow for `columns * min_column_width`, the grid uses fewer columns and continues on +the next row instead of creating a horizontal scrollbar. Use `columns="auto"` for autobreak mode, +where the grid derives the column count from the available width. Gauges with `width=0` or +`width=-1` fill their grid cell. Gauges also accept Dear PyGui's usual `parent` argument for adding a gauge to an existing container after that container has already been created: diff --git a/docs/API_REFERENCE.md b/docs/API_REFERENCE.md index 7a4ab89..bdd3168 100644 --- a/docs/API_REFERENCE.md +++ b/docs/API_REFERENCE.md @@ -24,10 +24,14 @@ Creation functions are context managers and accept common options such as `tag`, ## Layout Helpers - `gauge_panel(**config)`: child-window panel for grouped gauges. -- `gauge_grid(columns=1, min_column_width=180, fit_gauges=True, **config)`: table-backed - wrapping gauge grid. `columns` is the maximum number of columns. If the parent is narrower than - `columns * min_column_width`, the grid uses fewer columns and wraps gauges onto later rows to - avoid horizontal scrolling. Gauges without an explicit positive width fill their grid cell. +- `gauge_grid(columns=1, min_column_width=180, fit_gauges=True, cell_padding=12, **config)`: + table-backed + wrapping gauge grid. Pass an integer `columns` to set the maximum column count; if the parent is + narrower than `columns * min_column_width`, the grid uses fewer columns and wraps gauges onto + later rows to avoid horizontal scrolling. Pass `columns="auto"` for autobreak mode, where the + column count is derived entirely from the available width and `min_column_width`. Gauges without + an explicit positive width fill their grid cell. Increase `cell_padding` if a custom Dear PyGui + theme uses wider table padding or borders. ## Runtime API diff --git a/examples/layout_grid.py b/examples/layout_grid.py index 43cfaba..35ece49 100644 --- a/examples/layout_grid.py +++ b/examples/layout_grid.py @@ -9,7 +9,7 @@ def main() -> None: dpg.create_context() try: with dpg.window(label="Grid layout", width=820, height=620): - dpg.add_text("Three-column grid: fixed column cap, automatic rows") + dpg.add_text("Max columns: columns=3 wraps onto new rows after every third gauge") with dpgg.gauge_panel(label="Wide panel", width=-1, height=270), dpgg.gauge_grid( columns=3, min_column_width=190 ): @@ -26,9 +26,10 @@ def main() -> None: dpgg.battery_gauge(tag="grid_battery", label="Battery", value=74, height=160) dpg.add_spacer(height=8) - dpg.add_text("Narrow panel: columns=3 auto-reduces to avoid horizontal scrolling") - with dpgg.gauge_panel(label="Narrow panel", width=390, height=250), dpgg.gauge_grid( - columns=3, min_column_width=180 + dpg.add_text("Autobreak: columns='auto' chooses columns from available width") + with ( + dpgg.gauge_panel(label="Autobreak narrow panel", width=430, height=285), + dpgg.gauge_grid(columns="auto", min_column_width=180), ): for index, value in enumerate((18, 42, 67, 91, 55), start=1): dpgg.digital_gauge( diff --git a/src/dpg_gauges/widget.py b/src/dpg_gauges/widget.py index 51ee1fc..e920512 100644 --- a/src/dpg_gauges/widget.py +++ b/src/dpg_gauges/widget.py @@ -134,6 +134,7 @@ class GridLayoutContext: columns: int min_column_width: int fit_gauges: bool + cell_padding: int = 12 row_height: int = 0 available_width: int = 0 _next_index: int = 0 @@ -169,7 +170,7 @@ class GridLayoutContext: def cell_width(self) -> int | None: if self.available_width <= 0: return None - return max(int(self.available_width / self.columns), 1) + return max(int(self.available_width / self.columns) - self.cell_padding, 1) def create_gauge_context(gauge_type: str, config: ConfigT) -> GaugeContext[ConfigT]: @@ -257,9 +258,15 @@ def _available_layout_width(parent: Tag | None, width: int) -> int: return 0 -def _resolved_columns(columns: int, min_column_width: int, available_width: int) -> int: - columns = max(int(columns), 1) +def _resolved_columns( + columns: int | Literal["auto"], min_column_width: int, available_width: int +) -> int: min_column_width = max(int(min_column_width), 0) + if columns == "auto": + if available_width > 0 and min_column_width > 0: + return max(1, available_width // min_column_width) + return 1 + columns = max(int(columns), 1) if available_width > 0 and min_column_width > 0: columns = min(columns, max(1, available_width // min_column_width)) return columns @@ -305,9 +312,10 @@ def gauge_panel( def gauge_grid( *, - columns: int = 1, + columns: int | Literal["auto"] = 1, min_column_width: int = 180, fit_gauges: bool = True, + cell_padding: int = 12, row_height: int = 0, tag: Tag | None = None, parent: Tag | None = None, @@ -318,7 +326,7 @@ def gauge_grid( ) -> GridLayoutContext: """Create a lightweight wrapping gauge layout container.""" if not _dpg_context_active: - return GridLayoutContext(None, 1, min_column_width, fit_gauges) + return GridLayoutContext(None, 1, min_column_width, fit_gauges, cell_padding) layout_parent, layout_width = _next_layout_cell(parent) if layout_parent is not None: parent = layout_parent @@ -340,7 +348,13 @@ def gauge_grid( for _ in range(columns): dpg.add_table_column(parent=container, width_stretch=True, init_width_or_weight=1.0) return GridLayoutContext( - container, columns, min_column_width, fit_gauges, row_height, available_width + container, + columns, + min_column_width, + fit_gauges, + cell_padding, + row_height, + available_width, ) diff --git a/tests/test_step3_widget_renderer.py b/tests/test_step3_widget_renderer.py index 9a2f037..6a72bf8 100644 --- a/tests/test_step3_widget_renderer.py +++ b/tests/test_step3_widget_renderer.py @@ -107,6 +107,20 @@ def test_grid_auto_reduces_columns_to_parent_width(dpg_context: None) -> None: assert len(children[0]) == 2 assert len(children[1]) == 3 assert [len(_children(row)[1]) for row in children[1]] == [2, 2, 1] + assert 0 < get_gauge_state("narrow_metric_0").config.width < 190 + + +def test_grid_auto_columns_uses_available_width(dpg_context: None) -> None: + with dpg.window(label="Auto", width=640), dpgg.gauge_grid( + tag="auto_grid", columns="auto", min_column_width=180 + ): + for index in range(7): + dpgg.digital_gauge(tag=f"auto_metric_{index}", value=index, height=60) + + children = _children("auto_grid") + assert len(children[0]) == 3 + assert len(children[1]) == 3 + assert [len(_children(row)[1]) for row in children[1]] == [3, 3, 1] def test_grid_routes_panels_without_stealing_panel_children(dpg_context: None) -> None: From 0a7b4f01729c98d287f0f0787f17f69ac27d4034 Mon Sep 17 00:00:00 2001 From: Hector van der Aa Date: Tue, 7 Jul 2026 23:12:07 +0100 Subject: [PATCH 3/3] Release 1.1.0 --- pyproject.toml | 2 +- src/dpg_gauges/__init__.py | 2 +- tests/test_step7_hardening.py | 2 +- uv.lock | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c576092..bb78a23 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "dpg-gauges" -version = "1.0.2" +version = "1.1.0" description = "Dear PyGui gauge widgets for dashboards and telemetry displays" readme = "README.md" authors = [ diff --git a/src/dpg_gauges/__init__.py b/src/dpg_gauges/__init__.py index d92361a..6b85cd9 100644 --- a/src/dpg_gauges/__init__.py +++ b/src/dpg_gauges/__init__.py @@ -35,7 +35,7 @@ from .types import ( ThresholdBand, ) -__version__ = "1.0.2" +__version__ = "1.1.0" __all__ = [ "configure", diff --git a/tests/test_step7_hardening.py b/tests/test_step7_hardening.py index 85dfc48..af68b4a 100644 --- a/tests/test_step7_hardening.py +++ b/tests/test_step7_hardening.py @@ -31,7 +31,7 @@ def dpg_context() -> Generator[None]: def test_public_exports_and_version() -> None: - assert dpgg.__version__ == "1.0.2" + assert dpgg.__version__ == "1.1.0" assert files("dpg_gauges").joinpath("py.typed").is_file() for name in dpgg.__all__: assert hasattr(dpgg, name) diff --git a/uv.lock b/uv.lock index 9f544ea..89cbb44 100644 --- a/uv.lock +++ b/uv.lock @@ -36,7 +36,7 @@ wheels = [ [[package]] name = "dpg-gauges" -version = "1.0.2" +version = "1.1.0" source = { editable = "." } dependencies = [ { name = "dearpygui" },