diff --git a/.github/workflows/pylint.yml b/.forgejo/workflows/pylint.yml similarity index 66% rename from .github/workflows/pylint.yml rename to .forgejo/workflows/pylint.yml index bda3e4a..72d4b4d 100644 --- a/.github/workflows/pylint.yml +++ b/.forgejo/workflows/pylint.yml @@ -7,11 +7,11 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11"] + python-version: ["3.8.17", "3.9.17", "3.10.12", "3.11.4"] steps: - - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 + - uses: https://github.com/actions/checkout@v3 + - name: "Set up Python ${{ matrix.python-version }}" + uses: https://github.com/actions/setup-python@v3 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/README.md b/README.md index ce15469..a09732e 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ A Python module/TUI for AMD GPU statistics ![Screenshot of the main stats table](https://raw.githubusercontent.com/joshlay/amdgpu_stats/master/screens/main.svg "Main screen") ![Screenshot of the 'graphing' scroll bars](https://raw.githubusercontent.com/joshlay/amdgpu_stats/master/screens/graphs.svg "Graphs") +![Screenshot of the 'Logs' tab pane](https://raw.githubusercontent.com/joshlay/amdgpu_stats/master/screens/logs.svg "Logs") Tested _only_ on `RX6000` series cards; APUs and more _may_ be supported. Please file an issue if finding incompatibility! diff --git a/pyproject.toml b/pyproject.toml index f5ce478..1eed51b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,9 +1,9 @@ [tool.poetry] name = "amdgpu-stats" -version = "0.1.19" +version = "0.1.20" description = "A module/TUI for AMD GPU statistics" authors = ["Josh Lay "] -repository = "https://github.com/joshlay/amdgpu_stats" +repository = "https://git.jlay.dev/jlay/amdgpu_stats" license = "MIT" readme = "README.md" documentation = "https://amdgpu-stats.readthedocs.io/en/latest/" @@ -22,9 +22,8 @@ classifiers = [ [tool.poetry.dependencies] python = "^3.8" -textual = ">=0.30.0" +textual = ">=0.32.0" humanfriendly = ">=10.0" -pyyaml = "^6.0" [tool.poetry.scripts] amdgpu-stats = "amdgpu_stats:textual_run" diff --git a/screens/logs.svg b/screens/logs.svg new file mode 100644 index 0000000..c12384c --- /dev/null +++ b/screens/logs.svg @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AMD GPU Stats + + + + + + + + + + AMD GPU Stats — logs22:56:06 + +StatsGraphsLogs +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +[2023-08-0522:55:55] App started, logging begin!▄▄ +[2023-08-0522:55:55] Stat columns: +  - 'Card' +  - 'Core clock' +  - 'Memory clock' +  - 'Utilization' +  - 'Voltage' +  - 'Power' +  - 'Limit' +  - 'Default' +  - 'Capability' +  - 'Fan RPM' +  - 'Edge temp' +  - 'Junction temp' +  - 'Memory temp' +[2023-08-0522:55:55] Added row for 'card0', stats dir: '/sys/class/drm/card0/device/hwmon/hwmon3' +▀▀ +▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + C  Colors  T  Tab switch  S  Screenshot  ↑  Scroll Logs  ↓  Scroll Logs  Q  Quit  + + + diff --git a/src/amdgpu_stats/tui.py b/src/amdgpu_stats/tui.py index 7d8499e..01f695e 100644 --- a/src/amdgpu_stats/tui.py +++ b/src/amdgpu_stats/tui.py @@ -16,7 +16,6 @@ Functions: # pylint: disable=line-too-long from datetime import datetime from typing import Optional -from yaml import dump from rich.text import Text from textual import work @@ -32,7 +31,7 @@ from textual.widgets import ( Static, TabbedContent, TabPane, - TextLog, + Log, ) from .utils import ( @@ -129,10 +128,9 @@ class GPUStatsWidget(Static): def __init__(self, *args, cards=None, **kwargs): super().__init__(*args, **kwargs) self.cards = cards - self.text_log = TextLog(highlight=True, - markup=True, - name='log_gpu', - classes='logs') + self.text_log = Log(highlight=True, + name='log_gpu', + classes='logs') self.stats_table = DataTable(zebra_stripes=True, show_cursor=True, name='stats_table', @@ -142,18 +140,17 @@ class GPUStatsWidget(Static): def on_mount(self) -> None: '''Fires when stats widget 'mounted', behaves like on first showing''' - self.update_log("[bold green]App started, logging begin!\n") + self.update_log("App started, logging begin!") # construct the table columns columns = list(self.get_column_data_mapping(None).keys()) + self.update_log('Stat columns:') for column in columns: + self.update_log(f" - '{column}'", show_ts=False) if column in ['Limit', 'Default', 'Capability']: self.stats_table.add_column(label='[italic]' + column, key=column) else: self.stats_table.add_column(label=column, key=column) - # self.update_log(f' - "{column}"') - self.update_log('[bold]Stat columns:') - self.update_log(dump(data=columns, default_flow_style=False, sort_keys=True)) # do a one-off stat collection, populate table before the interval self.get_stats() # stand up the stat-collecting interval, twice per second @@ -176,9 +173,19 @@ class GPUStatsWidget(Static): with TabPane("Logs", id="tab_logs"): yield self.text_log - def update_log(self, message: str) -> None: - """Update the TextLog widget with a new message.""" - self.text_log.write(message) + def update_log(self, message: str, show_ts: bool = True) -> None: + """Update the Log widget with a new message. + + Highest Textual version-requiring widget; >=0.32.0 + Should be more performant than the old TextLog widget + + Args: + message (str): The message to be added to the logging widget on the 'Logs' tab. + show_ts (bool, optional): If True (default), appends a timestamp to the message. + """ + if show_ts: + message = f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] {message}" + self.text_log.write_line(message) @work(exclusive=True) async def get_stats(self):