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

Improve command output with text banner, colour and alignment #113

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
3bcabef
Define ASCII art text banner w/ and w/o colour for CATS
sadielbartholomew Aug 22, 2024
67d2284
Escape some chars to avoid SyntaxWarning from ASCII art text banner
sadielbartholomew Aug 26, 2024
d8f12e0
Add new --no-colour/-n CLI option to toggle terminal colours
sadielbartholomew Aug 26, 2024
7de3050
Command output: align 'best job start time' w/ other output
sadielbartholomew Aug 26, 2024
6c56332
Command output: colour output to distinguish now vs. optimal
sadielbartholomew Aug 26, 2024
17e02d2
Subsume output informational message to logging system
sadielbartholomew Aug 26, 2024
28e44ae
Final escaping & adjust colours to traffic light colour rating
sadielbartholomew Aug 26, 2024
0803922
Move banner printout so it comes before any log- or printing
sadielbartholomew Aug 26, 2024
4769de7
Make clearer CLI description for --no-colour option
sadielbartholomew Aug 26, 2024
884c2dd
Command output: change CATS letting from white to default colour
sadielbartholomew Sep 30, 2024
637c9df
Fix some typos in comments & docstrings
sadielbartholomew Sep 30, 2024
56fb80e
CLI: add --no-color as alias to --no-colour
sadielbartholomew Sep 30, 2024
6499544
Fix further typos, in CLI interface (user-facing)
sadielbartholomew Sep 30, 2024
5eb5ac4
Fix bug whereby colour parameter was not assigned a default
sadielbartholomew Sep 30, 2024
e648100
Update tests to account for new colour arg for passing test suite
sadielbartholomew Sep 30, 2024
fc105a5
Fix for CATSOutput new better order of args
sadielbartholomew Oct 1, 2024
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
56 changes: 49 additions & 7 deletions cats/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from .configure import get_runtime_config
from .forecast import CarbonIntensityAverageEstimate
from .optimise_starttime import get_avg_estimates # noqa: F401
from .constants import CATS_ASCII_BANNER_COLOUR, CATS_ASCII_BANNER_NO_COLOUR

__version__ = "1.0.0"

Expand Down Expand Up @@ -182,6 +183,12 @@ def positive_integer(string):
type=positive_integer,
help="Amount of memory used by the job, in GB",
)
parser.add_argument(
"-n",
"--no-colour", # or could use American spelling like many other CLIs?
sadielbartholomew marked this conversation as resolved.
Show resolved Hide resolved
action="store_true",
help="Disable all terminal output colouring",
)

return parser

Expand All @@ -194,19 +201,41 @@ class CATSOutput:
carbonIntensityOptimal: CarbonIntensityAverageEstimate
location: str
countryISO3: str
colour: bool
emmissionEstimate: Optional[Estimates] = None

def __str__(self) -> str:
out = f"""Best job start time {self.carbonIntensityOptimal.start}
Carbon intensity if job started now = {self.carbonIntensityNow.value:.2f} gCO2eq/kWh
Carbon intensity at optimal time = {self.carbonIntensityOptimal.value:.2f} gCO2eq/kWh"""
if self.colour:
# Default colour
col_normal = "\33[0m" # reset any colour

# Optimal information colours
col_dt_opt = "\33[32m" # green i.e. 'good' in traffic light rating
col_ci_opt = "\33[32m" # green
col_ee_opt = "\33[32m" # green

# 'NOw' non-optimal colours
col_ci_now = "\33[31m" # red i.e. 'bad' in traffic light rating
col_ee_now = "\33[31m" # red
else:
col_normal = ""
col_dt_opt = ""
col_ci_opt = ""
col_ci_now = ""
col_ee_now = ""
col_ee_opt = ""

out = f"""
Best job start time = {col_dt_opt}{self.carbonIntensityOptimal.start}{col_normal}
Carbon intensity if job started now = {col_ci_now}{self.carbonIntensityNow.value:.2f} gCO2eq/kWh{col_normal}
Carbon intensity at optimal time = {col_ci_opt}{self.carbonIntensityOptimal.value:.2f} gCO2eq/kWh{col_normal}"""

if self.emmissionEstimate:
out += f"""
Estimated emissions if job started now = {self.emmissionEstimate.now}
Estimated emissions at optimal time = {self.emmissionEstimate.best} (- {self.emmissionEstimate.savings})"""
Estimated emissions if job started now = {col_ee_now}{self.emmissionEstimate.now}{col_normal}
Estimated emissions at optimal time = {col_ee_opt}{self.emmissionEstimate.best} (- {self.emmissionEstimate.savings}){col_normal}"""

out += "\n\nUse --format=json to get this in machine readable format"
logging.info("Use '--format=json' to get this in machine readable format")
return out

def to_json(self, dateformat: str = "", **kwargs) -> str:
Expand All @@ -222,6 +251,15 @@ def to_json(self, dateformat: str = "", **kwargs) -> str:
return json.dumps(data, **kwargs)


def print_banner(colour):
"""Print an ASCII art banner with the CATS title, optionally in colour.
"""
if colour:
print(CATS_ASCII_BANNER_COLOUR)
else:
print(CATS_ASCII_BANNER_NO_COLOUR)


def schedule_at(
output: CATSOutput, args: list[str], at_command: str = "at"
) -> Optional[str]:
Expand Down Expand Up @@ -251,6 +289,10 @@ def schedule_at(
def main(arguments=None) -> int:
parser = parse_arguments()
args = parser.parse_args(arguments)

# Print CATS ASCII art banner, before any output from printing or logging
print_banner(not args.no_colour)

if args.command and not args.scheduler:
print(
"cats: To run a command with the -c or --command option, you must\n"
Expand Down Expand Up @@ -287,7 +329,7 @@ def main(arguments=None) -> int:
# Find best possible average carbon intensity, along
# with corresponding job start time.
now_avg, best_avg = get_avg_estimates(CI_forecast, duration=duration)
output = CATSOutput(now_avg, best_avg, location, "GBR")
output = CATSOutput(now_avg, best_avg, location, "GBR", not args.no_colour)

################################
## Calculate carbon footprint ##
Expand Down
19 changes: 19 additions & 0 deletions cats/constants.py
Original file line number Diff line number Diff line change
@@ -1 +1,20 @@
MEMORY_POWER_PER_GB = 0.3725 # W/GB

CATS_ASCII_BANNER_COLOUR = """
\33[34mThe\33[35m.\33[34m\33[37m____ \33[35m..... \33[37m__ \33[35m.... \33[37m________ \33[35m. \33[37m______\33[35m...
\33[35m.. \33[37m/ __)\33[35m.....\33[37m/ \\\33[35m....\33[37m(__ __)\33[35m.\33[37m) ____)\33[35m....
\33[35m..\33[37m| /\33[35m.......\33[37m/ \\\33[35m......\33[37m| |\33[35m...\33[37m( (___\33[35m........
\33[35m..\33[37m| |\33[34mlimate\33[35m.\33[37m/ () \\\33[34mware\33[35m.\33[37m| |\33[34mask\33[35m.\33[37m\\___ \\\33[34mcheduler
\33[35m..\33[37m| \\__\33[35m...\33[37m| __ |\33[35m....\33[37m| |\33[35m....\33[37m____) )\33[35m....
\33[35m...\33[37m\\ )\33[35m..\33[37m| (\33[35m..\33[37m) |\33[35m....\33[37m| |\33[35m...\33[37m( (\33[35m..\33[0m
"""

# Same as above but without the colour codes, so not given custom colouring
CATS_ASCII_BANNER_NO_COLOUR = """
The.____ ..... __ .... ________ . ______ ...
.. / __)...../ \\....(__ __).) ____)....
..| /......./ \\......| |...( (___........
..| |limate./ () \\ware.| |ask.\\___ \\cheduler
..| \\__...| __ |....| |....____) )....
...\\ )..| (..) |....| |...( (..
"""
Loading