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

New configuration option for interactive #305

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ __pycache__
venv
.DS_Store
.vscode
src/plotman.egg-info
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,25 @@ archive jobs initiated. This is the one part of the interactive tool which is
stateful. There is no permanent record of these executed command lines, so if
you start a new interactive plotman session, this log is empty.

## `plotman` commands
altendky marked this conversation as resolved.
Show resolved Hide resolved
To get a complete list of all available commands run:
```shell
plotman -h
```

You can also use `plotman <command> -h` to get help about a specific command, like
```shell
plotman interactive -h
```

## Running `plotman` as a daemon
> _PS: this section assumes that you have already configured `plotman.yaml`._

By default the command `plotman plot` will start the plotting job and continue to run on the foregroud as long as you keep the terminal window open. If you want to have it constantly running, try the following:
```shell
nohup plotman plot >> ~/plotman.log 2>&1 &
```

## Limitations and Issues

The system is tested on Linux only. Plotman should be generalizable to other
Expand Down
15 changes: 15 additions & 0 deletions src/plotman/_tests/configuration_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,21 @@ def test_get_validated_configs__default(config_text):
res = configuration.get_validated_configs(config_text, '')
assert isinstance(res, configuration.PlotmanConfig)

def test_tool_interactive_should_be_none(config_text):
"""When tools/interacting doesn't exist, its configuration property should be None"""
loaded_yaml = yaml.load(config_text, Loader=yaml.SafeLoader)

del loaded_yaml["tools"]["interactive"]
reloaded_yaml = configuration.get_validated_configs(yaml.dump(loaded_yaml, Dumper=yaml.SafeDumper), '')
assert reloaded_yaml.tools.interactive is None

def test_tool_section_does_not_exist(config_text):
"""When tools doesn't exist, its configuration property should be None"""
loaded_yaml = yaml.load(config_text, Loader=yaml.SafeLoader)

del loaded_yaml["tools"]
reloaded_yaml = configuration.get_validated_configs(yaml.dump(loaded_yaml, Dumper=yaml.SafeDumper), '')
assert reloaded_yaml.tools is None

def test_get_validated_configs__malformed(config_text):
"""Check that get_validated_configs() raises exception with invalid plotman.yaml contents."""
Expand Down
9 changes: 9 additions & 0 deletions src/plotman/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,18 @@ class Plotting:
class UserInterface:
use_stty_size: bool = True

@attr.frozen
class Interactive:
autostart_plotting: bool

@attr.frozen
class Tools:
interactive: Optional[Interactive] = None
rafaelsteil marked this conversation as resolved.
Show resolved Hide resolved

@attr.frozen
class PlotmanConfig:
directories: Directories
scheduling: Scheduling
plotting: Plotting
tools: Optional[Tools] = None
user_interface: UserInterface = attr.ib(factory=UserInterface)
18 changes: 12 additions & 6 deletions src/plotman/interactive.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import math
import os
import subprocess

import sys
from plotman import archive, configuration, manager, reporting
from plotman.job import Job

Expand Down Expand Up @@ -62,14 +62,21 @@ def archiving_status_msg(configured, active, status):
else:
return '(not configured)'

def curses_main(stdscr):
# cmd_autostart_plotting is the (optional) argument passed from the command line. May be None
def curses_main(stdscr, cmd_autostart_plotting):
log = Log()

config_path = configuration.get_path()
config_text = configuration.read_configuration_text(config_path)
cfg = configuration.get_validated_configs(config_text, config_path)

plotting_active = True
if cmd_autostart_plotting is not None:
plotting_active = cmd_autostart_plotting
elif cfg.tools is not None and cfg.tools.interactive is not None:
plotting_active = cfg.tools.interactive.autostart_plotting
else:
plotting_active = True

archiving_configured = cfg.directories.archive is not None
archiving_active = archiving_configured

Expand Down Expand Up @@ -324,14 +331,13 @@ def curses_main(stdscr):
else:
pressed_key = key


def run_interactive():
def run_interactive(autostart_plotting = None):
locale.setlocale(locale.LC_ALL, '')
code = locale.getpreferredencoding()
# Then use code as the encoding for str.encode() calls.

try:
curses.wrapper(curses_main)
curses.wrapper(curses_main, autostart_plotting)
except curses.error as e:
raise TerminalTooSmallError(
"Your terminal may be too small, try making it bigger.",
Expand Down
23 changes: 20 additions & 3 deletions src/plotman/plotman.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
import random
from shutil import copyfile
import time
import sys

# Plotman libraries
from plotman import analyzer, archive, configuration, interactive, manager, plot_util, reporting
from plotman import resources as plotman_resources
from plotman.job import Job


class PlotmanArgParser:
def add_idprefix_arg(self, subparser):
subparser.add_argument(
Expand All @@ -30,7 +30,16 @@ def parse_args(self):

sp.add_parser('dirs', help='show directories info')

sp.add_parser('interactive', help='run interactive control/monitoring mode')
p_interactive = sp.add_parser('interactive', help='run interactive control/monitoring mode')
p_interactive.add_argument('--autostart-plotting',
action='store_true',
default=None,
help='Automatically start plotting when the tool opens')

p_interactive.add_argument('--no-autostart-plotting',
action='store_true',
default=None,
help='Do not start plotting when the tool opens')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Take a look at BooleanOptionalAction in https://docs.python.org/3/library/argparse.html#action. I think this can be a single added argument.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so I think we can do it like this. Setting the dest to the same name on both let's them override each other which I believe is 'normal' cli behavior. It also eliminates any logic needed to process the results later.

https://replit.com/@altendky/ImmaterialTintedInterfacestandard-1

import argparse


parser = argparse.ArgumentParser()
parser.add_argument('--x', action='store_true', dest='x')
parser.add_argument('--no-x', action='store_false', dest='x')

print(parser.parse_args([]).x, False)
print(parser.parse_args(['--x']).x, True)
print(parser.parse_args(['--no-x']).x, False)
print(parser.parse_args(['--x', '--no-x']).x, False)
print(parser.parse_args(['--no-x', '--x']).x, True)
False False
True True
False False
False False
True True

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Slight update to account for the not-passed case so we can use the value in the config file.

https://replit.com/@altendky/ImmaterialTintedInterfacestandard-2

import argparse


parser = argparse.ArgumentParser()
parser.add_argument('--x', action='store_true', default=None, dest='x')
parser.add_argument('--no-x', action='store_false', default=None, dest='x')

print(parser.parse_args([]).x, None)
print(parser.parse_args(['--x']).x, True)
print(parser.parse_args(['--no-x']).x, False)
print(parser.parse_args(['--x', '--no-x']).x, False)
print(parser.parse_args(['--no-x', '--x']).x, True)
None None
True True
False False
False False
True True


sp.add_parser('dsched', help='print destination dir schedule')

Expand Down Expand Up @@ -170,7 +179,15 @@ def main():
print(reporting.dirs_report(jobs, cfg.directories, cfg.scheduling, get_term_width()))

elif args.cmd == 'interactive':
interactive.run_interactive()
if args.autostart_plotting is not None:
autostart_plotting = True
elif args.no_autostart_plotting is not None:
autostart_plotting = False
else:
# In this case we'll check the configuration file
autostart_plotting = None

interactive.run_interactive(autostart_plotting)

# Start running archival
elif args.cmd == 'archive':
Expand Down
7 changes: 7 additions & 0 deletions src/plotman/resources/plotman.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ user_interface:
# you resize the terminal window, you can try setting this to True.
use_stty_size: True

# Optional custom settings for the tools (status, interactive etc)
tools:
rafaelsteil marked this conversation as resolved.
Show resolved Hide resolved
interactive:
# Set it to False if you don't want to auto start plotting when 'interactive' is ran.
# You can override this value from the command line, type "plotman interactive -h" for details
autostart_plotting: True

# Where to plot and log.
directories:
# One directory in which to store all plot job logs (the STDOUT/
Expand Down