Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature/bgunnar5/status-pager #420

Merged
merged 5 commits into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ build:
python: '3.10'
jobs:
post_install:
- pip install poetry>=1.2
- pip install poetry==1.4.2
- poetry config virtualenvs.create false
- poetry install

Expand Down
2 changes: 2 additions & 0 deletions docs/Maestro/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ maestro status [OPTIONS] DIRECTORY [DIRECTORY ...]
| ---- | ---- | ----------- | ------- |
| `-h`, `--help` | boolean | Show this help message and exit. | `False` |
| `--layout` | choice (`flat` | `legacy` | `narrow`) | Alternate status table layouts. See [Status Layouts](monitoring.md#status-layouts) for description of these options| `flat` |
| `--disable-theme` | boolean | Turn off styling for the status layout. See [Status Theme](monitoring.md#status-theme) for more information on this option. | `False` |
| `--disable-pager` | boolean | Turn off the pager for the status display. See [Status Pager](monitoring.md#status-pager) for more information on this option. | `False` |


## **conductor**
Expand Down
72 changes: 71 additions & 1 deletion docs/Maestro/monitoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,26 @@ The resulting output will look something like below:
<figcaption>Flat layout view of status of an in progress study</figcaption>
</figure>

!!! note

If the output of your study looks something like this:

<figure markdown>
![Maestro Status Theme Error](../assets/images/examples/study_monitoring/status_theme_error.png)
<figcaption>Example of a theme error with the status output</figcaption>
</figure>

Then there are a couple things you can try to fix this problem:

1. Set the MANPAGER or PAGER environment variable to be "less -r" (e.g. export MANPAGER="less -r") and run again

2. If the error isn't fixed after 1. above, then:

a. You can disable the theme with the ``--disable-theme`` option (see [Status Theme](#status-theme) below).

b. If you'd rather not disable the theme, the error usually stems from using the pager functionality, so you can try disabling that with the ``--disable-pager`` option (see [Status Pager](#status-pager) below). <text class=caution>Caution:</text> you may end up outputting a lot of information to the terminal all at once when using this option.

To return to your terminal window, press `q` (see [Status Pager](#status-pager) below for more information).

The general statuses that are usually encountered are:

Expand Down Expand Up @@ -75,7 +95,7 @@ $ maestro status ./tests/lulesh --layout narrow
A snippet of the narrow layout for the above study is shown below. These layouts are computed by status command, so you can alternate between them in the same study without issue:

<figure markdown>
![Flat Layout Lulesh Cancelled](../assets/images/examples/study_monitoring/narrow_layout_lulesh_cancelled.png)
![Narrow Layout Lulesh Cancelled](../assets/images/examples/study_monitoring/narrow_layout_lulesh_cancelled.png)
FrankD412 marked this conversation as resolved.
Show resolved Hide resolved
<figcaption>Narrow layout view of status of a cancelled study</figcaption>
</figure>

Expand Down Expand Up @@ -114,3 +134,53 @@ Finally, the original status layout is still available via the `legacy` option.
post-process-lulesh-size_SIZE.20 SIZE.20 CANCELLED --:--:-- --:--:-- -- -- 2018-08-07 17:25:06.810216 0
run-lulesh_ITER.30.SIZE.30 ITER.30.SIZE.30 FINISHED 0:00:00.915474 0:00:00.915682 2018-08-07 17:24:05.818191 2018-08-07 17:24:05.817983 2018-08-07 17:24:06.733665 0
```

## Status Theme

Maestro's status monitor comes with a built-in theme to incorporate colors when displaying statuses in order to make the resulting output easier to read (see the images above).

If you have trouble getting the colors in the theme to display properly or you want to disable the theme entirely, you can use the ``--disable-theme`` option as shown below:

``` console
$ maestro status ./tests/lulesh --disable-theme
```

The resulting output of this command is shown below. Notice how the color scheme is now gone:

<figure markdown>
![Status With Disable Theme](../assets/images/examples/study_monitoring/status_with_disable_theme.png)
<figcaption>View of the status table with the theme disabled</figcaption>
</figure>

## Status Pager

For many Maestro studies, there can be a significant amount of information to display when the status command is run. To help keep terminals from being overloaded with output, Maestro uses paging functionality. This opens a [pager](https://en.wikipedia.org/wiki/Terminal_pager) that allows you to view the output of the status command until you wish to close it:

<figure markdown>
![Lulesh Status Inside Pager](../assets/images/examples/study_monitoring/status_inside_pager.png)
<figcaption>View of the status of a study inside the pager</figcaption>
</figure>

You can close the pager window by pressing `q`. Once closed, the output from the status command will disappear entirely until you re-run the command and a new pager window is opened:

<figure markdown>
![Terminal Once Pager is Closed](../assets/images/examples/study_monitoring/status_outside_pager.png)
<figcaption>The display when you close the pager</figcaption>
</figure>

!!! warning

Disabling the pager could result in a lot of information being output directly to the terminal, which may result in performance issues or output errors.

If you wish to disable the pager, you may do so with the ``--disable-pager`` option as shown below:

``` console
$ maestro status ./tests/lulesh --disable-pager
```

This will output the results of running the status command directly to the stdout of the terminal rather than opening a pager window:

<figure markdown>
![Status With Disable Pager Functionality](../assets/images/examples/study_monitoring/status_with_disable_pager.png)
<figcaption>View of the status table with the pager disabled</figcaption>
</figure>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions docs/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@
align: center;
text-align: center;
}

.caution {
color: yellow;
font-weight: bold;
}
62 changes: 30 additions & 32 deletions maestrowf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ def __init__(self, *args, **kwargs):
self._study_title = ''
self._theme_dict = {}

self.disable_theme = kwargs.pop("disable_theme", False)
self.disable_pager = kwargs.pop("disable_pager", False)

@abstractmethod
def layout(self, status_data, study_title=None, data_filters=None):
"""Setup concrete status layout
Expand All @@ -94,9 +97,28 @@ def layout(self, status_data, study_title=None, data_filters=None):
"""
pass

@abstractmethod
def render(self, theme=None):
pass
"""Do the actual printing"""
# Apply any theme customization
if theme:
for key, value in theme.items():
self._theme_dict[key] = value

# If we're disabling the theme, we need to set all themes in the theme dict to none
if self.disable_theme:
for key in self._theme_dict.keys():
self._theme_dict[key] = 'none'

# Get the rich Console
status_theme = Theme(self._theme_dict)
_printer = Console(theme=status_theme)

# Display the status table
if self.disable_pager:
_printer.print(self._status_table)
else:
with _printer.pager(styles=(not self.disable_theme)):
_printer.print(self._status_table)


class LegacyStatusRenderer(BaseStatusRenderer):
Expand Down Expand Up @@ -237,20 +259,6 @@ def layout(self, status_data, study_title=None, filter_dict=None):
style=row_style
)

def render(self, theme=None):
"""Do the actual printing"""

# Apply any theme customization
if theme:
for key, value in theme.items():
self._theme_dict[key] = value

status_theme = Theme(self._theme_dict)

_printer = Console(theme=status_theme)

_printer.print(self._status_table)

def render_to_str(self, theme=None, width=200):
"""Capture output to string"""

Expand Down Expand Up @@ -440,20 +448,6 @@ def layout(self, status_data, study_title=None, filter_dict=None):

self._status_table.add_row(step_table, end_section=True)

def render(self, theme=None):
"""Do the actual printing"""

# Apply any theme customization
if theme:
for key, value in theme.items():
self._theme_dict[key] = value

status_theme = Theme(self._theme_dict)

_printer = Console(theme=status_theme)

_printer.print(self._status_table)

def render_to_str(self, theme=None, width=120):
"""Capture output to string"""

Expand Down Expand Up @@ -510,11 +504,15 @@ def register_layout(self, layout, renderer):
"""
self._layouts[layout] = renderer

def get_renderer(self, layout):
def get_renderer(self, layout, disable_theme, disable_pager):
"""Get handle for specific layout renderer to instantiate

Args:
layout (str): Name of layout renderer
disable_theme (bool): True if the user wants to disable themes when displaying status.
False otherwise.
disable_pager (bool): True if the user wants to disable the pager when displaying status.
False otherwise.

Returns:
BaseStatusRenderer: The concrete status renderer class
Expand All @@ -525,7 +523,7 @@ def get_renderer(self, layout):
if not renderer:
raise ValueError(layout)

return renderer()
return renderer(disable_theme=disable_theme, disable_pager=disable_pager)

def get_layouts(self):
"""Get list of registered layouts
Expand Down
11 changes: 10 additions & 1 deletion maestrowf/maestro.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def status_study(args):
try:
# Wasteful to not reuse this renderer for all paths?
status_renderer = status_renderer_factory.get_renderer(
status_layout)
status_layout, args.disable_theme, args.disable_pager)

except ValueError:
print("Layout '{}' not implemented.".format(status_layout))
Expand Down Expand Up @@ -452,6 +452,15 @@ def setup_argparser():
"--layout", type=str, choices=status_renderer_factory.get_layouts(),
default='flat',
help="Alternate status table layouts. [Default: %(default)s]")
status.add_argument(
"--disable-theme", action="store_true", default=False,
help="Turn off styling for the status layout. (If you want styling but it's not working, try modifying "
"the MANPAGER or PAGER environment variables to be 'less -r'; i.e. export MANPAGER='less -r')"
)
status.add_argument(
"--disable-pager", action="store_true", default=False,
help="Turn off the pager functionality when viewing the status."
)
status.set_defaults(func=status_study)

# global options
Expand Down
2 changes: 1 addition & 1 deletion tests/status/test_status_renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def test_status_layout(load_csv_status, expected_status,
layout, title, expected):
"""Captures status table to string without color codes for verification"""
expected_status_output = expected_status(expected)
status_renderer = status_renderer_factory.get_renderer(layout)
status_renderer = status_renderer_factory.get_renderer(layout, disable_theme=False, disable_pager=False)
status_renderer.layout(status_data=load_csv_status,
study_title=title)

Expand Down