You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
4.2 KiB
118 lines
4.2 KiB
import argparse |
|
import re |
|
|
|
from collections import namedtuple |
|
from pathlib import Path |
|
|
|
|
|
TIME_UNIT_FACTORS = { |
|
"s": 1, |
|
"m": 60, |
|
"h": 60 * 60, |
|
} |
|
|
|
ParsedDuration = namedtuple("ParsedDuration", ["value", "unit", "seconds"]) |
|
|
|
Settings = namedtuple( |
|
"Settings", ["duration", "interval", "directory", "port"] |
|
) |
|
|
|
|
|
def parse_duration(raw_value, default_unit="m"): |
|
"""' parses a duration like 10sec, 5min or 2h |
|
|
|
:params raw_value: string value to parse |
|
:params default_unit: default unit to use, if no (known) unit is present |
|
:returns: ParsedTime named tuple or None |
|
""" |
|
match = re.match(r"(?P<value>\d+)(?P<unit>.*)", raw_value) |
|
if not match: |
|
return None |
|
value = int(match["value"]) |
|
unit = _normalize_time_unit(match["unit"], default_unit=default_unit) |
|
factor = TIME_UNIT_FACTORS[unit] |
|
return ParsedDuration(value, unit, value * factor) |
|
|
|
|
|
def parse_cli_arguments(): |
|
""" parses command line interface arguments """ |
|
parser = argparse.ArgumentParser( |
|
description="Make time series measurements with a Sartorius scale.", |
|
epilog=( |
|
"Times can be specified as 10s, 10m, or 10h" |
|
"for seconds, minutes or hours respectively." |
|
"A relative directory path starts at the Desktop." |
|
), |
|
) |
|
parser.add_argument("port", nargs="?", default="COM4", metavar="COMPORT") |
|
parser.add_argument("-d", "--duration", nargs="?", default="30m") |
|
parser.add_argument("-i", "--interval", nargs="?", default="10s") |
|
parser.add_argument("-o", "--output", nargs="?", metavar="DIRECTORY") |
|
raw_arguments = parser.parse_args() |
|
return _normalize_cli_arguments(raw_arguments) |
|
|
|
|
|
def parse_gui_arguments(): |
|
from gooey import GooeyParser |
|
""" parses command line interface arguments """ |
|
parser = GooeyParser( |
|
description="Make time series measurements with a Sartorius scale.", |
|
epilog=( |
|
"Times can be specified as 10s, 10m, or 10h" |
|
"for seconds, minutes or hours respectively." |
|
"A relative directory path starts at the Desktop." |
|
), |
|
) |
|
parser.add_argument("port", nargs="?", default="COM4", metavar="COMPORT", help="Serial Port that connects the Scale, defaults to 'COM4'") |
|
parser.add_argument("-d", "--duration", nargs="?", default="30m", help="Measurement duration, e.g. 10s, 30m, 2h") |
|
parser.add_argument("-i", "--interval", nargs="?", default="10s", help="Measurement interval, e.g. 5s, 1m, 1h") |
|
parser.add_argument("-o", "--output", nargs="?", metavar="DIRECTORY", widget='DirChooser', help="Select Output Directory, defaults to 'Desktop'") |
|
raw_arguments = parser.parse_args() |
|
return _normalize_cli_arguments(raw_arguments) |
|
|
|
|
|
# helper functions |
|
|
|
|
|
def _normalize_time_unit(raw_unit, default_unit): |
|
""" checks if a known time unit is present, else uses the default unit """ |
|
known_units = "hms" |
|
found = [unit for unit in known_units if unit in raw_unit.lower()] |
|
unit = found[0] if found else default_unit |
|
return unit |
|
|
|
|
|
def _normalize_cli_arguments(raw_arguments): |
|
""" transforms cli arguments into a suitable form """ |
|
# time related stuff |
|
duration = parse_duration(raw_arguments.duration, default_unit="m") |
|
interval = parse_duration(raw_arguments.interval, default_unit="s") |
|
|
|
# directory stuff |
|
dir_path = _check_output_directory_path(raw_arguments.output) |
|
|
|
return Settings(duration, interval, dir_path, raw_arguments.port) |
|
|
|
|
|
def _check_output_directory_path(raw_path): |
|
""" returns the absolue path of the output directory |
|
|
|
The desktop path (~/Desktop) is considered the default directory. If a |
|
relative path is provided, it is considered relative to the desktop. |
|
""" |
|
# the desktop path is the default output directory |
|
out_path = desktop_path = Path.home() / "Desktop" |
|
|
|
# if a relative path is provided, make it relative to the desktop |
|
if raw_path: |
|
out_path = Path(raw_path) |
|
if not out_path.is_absolute(): |
|
out_path = desktop_path / out_path |
|
out_path = out_path.resolve() |
|
|
|
# if the provided path is something strange like an existing file, |
|
# use the default path (Desktop) |
|
if out_path.exists() and not out_path.is_dir(): |
|
out_path = desktop_path |
|
|
|
return out_path
|
|
|