Skip to content

Commit

Permalink
CLI modification (#238)
Browse files Browse the repository at this point in the history
* fix : CLI functions moved to cli.py

* fix : setup.py entry-point updated

* fix : run_samila function added to cli.py

* fix : minor edit in main function

* fix : cli_test.py added

* fix : cli_test.py updated

* fix : cli_test.py updated

* fix : cli_test.py updated

* fix : cli_test.py removed

* fix : .coveragerc updated

* fix : pytest.ini updated

* fix : error_test.py updated

* doc : CHANGELOG.md updated

* doc : cli.py docstring updated

* fix : autopep8

* fix : minor edit in test.yml

* fix : PLOT_DATA_ERROR updated
  • Loading branch information
sepandhaghighi authored Nov 17, 2024
1 parent 3ece622 commit 7b0cdfc
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 155 deletions.
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ omit =
*/samila/__main__.py
*/samila/__init__.py
*/samila/test.py
*/samila/cli.py
[report]
# Regexes for lines to exclude from consideration
exclude_lines =
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
samila --info
- name: Samila CLI test
run: |
samila --no-display --color=red --bgcolor=black --rotation=30 --projection=polar --mode f2_vs_f1 --save-image test.png
samila --verbose --no-display --color=red --bgcolor=black --rotation=30 --projection=polar --mode f2_vs_f1 --save-image test.png
- name: Test requirements Installation
run: |
python otherfiles/requirements-splitter.py
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Command Line Interface (CLI)
### Changed
- GitHub actions are limited to the `dev` and `master` branches
- Test system modified
- `Python 3.13` added to `test.yml`
## [1.3] - 2024-09-09
### Added
Expand Down
2 changes: 1 addition & 1 deletion pytest.ini
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# content of pytest.ini
[pytest]
addopts = --doctest-modules
doctest_optionflags= NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL
doctest_optionflags= NORMALIZE_WHITESPACE ELLIPSIS
148 changes: 1 addition & 147 deletions samila/__main__.py
Original file line number Diff line number Diff line change
@@ -1,153 +1,7 @@
# -*- coding: utf-8 -*-
"""Samila main."""

import argparse
import matplotlib.pyplot as plt

from art import tprint
from .params import SAMILA_VERSION, GenerateMode, Projection, Marker
from .params import LOG_GI_CREATED, LOG_GI_GENERATED, LOG_GI_PLOTTED
from .params import LOG_IMG_SAVED, LOG_DATA_SAVED, LOG_CONFIG_SAVED
from .params import ERR_IMG_SAVE_FAILED, ERR_DATA_SAVE_FAILED, ERR_CONFIG_SAVE_FAILED
from .params import ERR_GENERAL, EXIT_MESSAGE
from .functions import samila_help, print_line
from .genimage import GenerativeImage


def init_argparse():
"""
Initialize argparse.
:return: parser
"""
parser = argparse.ArgumentParser()
parser.add_argument('--version', help='version', action='store_true', default=False)
parser.add_argument('--info', help='info', action='store_true', default=False)
parser.add_argument('--verbose', help='verbose', action='store_true', default=False)

parser.add_argument('--load-config', help='load config', type=str)
parser.add_argument('--load-data', help='load data', type=str)
parser.add_argument('--function1', help='function1', type=str)
parser.add_argument('--function2', help='function2', type=str)
parser.add_argument('--function_seed', help='function seed', type=str)

parser.add_argument('--seed', help='generate seed', type=str)
parser.add_argument('--start', help='start point', type=float)
parser.add_argument('--step', help='step size', type=float)
parser.add_argument('--stop', help='stop point', type=float)
parser.add_argument(
'--mode',
help='generation mode',
type=str,
choices=[x.value for x in GenerateMode])

parser.add_argument('--color', help='color', type=str)
parser.add_argument('--bgcolor', help='background color', type=str)
parser.add_argument('--cmap', help='cmap', type=str)
parser.add_argument('--spot-size', help='spot size', type=float)
parser.add_argument('--size', help='size', type=tuple)
parser.add_argument('--alpha', help='alpha', type=float)
parser.add_argument('--linewidth', help='line width', type=float)
parser.add_argument('--rotation', help='rotation', type=float)
parser.add_argument(
'--projection',
help='projection type',
type=str,
choices=[x.value for x in Projection])
parser.add_argument(
'--marker',
help='marker type',
type=str,
choices=[x.value for x in Marker])

parser.add_argument('--save-image', help='save image', type=str)
parser.add_argument('--depth', help='depth', type=float)
parser.add_argument('--save-data', help='save data', type=str)
parser.add_argument('--save-config', help='save config', type=str)
parser.add_argument('--no-display', help='no display', action='store_true', default=False)

return parser


def log_results(is_verbose, result, log_success, log_fail):
"""
Save result function.
:param is_verbose: is verbose
:type is_verbose: bool
:param result: result dictionary
:type result: dict
:param log_success: log for successful result
:type log_success: str
:param log_fail: log for failed result
:type log_fail: str
:return: None
"""
if is_verbose:
if result['status']:
print(log_success.format(result['message']))
print_line()
else:
print(log_fail.format(result['message']))
print_line()


def main():
"""
CLI main function.
:return: None
"""
parser = init_argparse()
args = parser.parse_args()

if args.version:
print(SAMILA_VERSION)
elif args.info:
tprint("samila")
tprint("V:" + SAMILA_VERSION)
samila_help()
else:
try:
gi = GenerativeImage(
function1=args.function1, function2=args.function2,
func_seed=args.function_seed, data=args.load_data, config=args.load_config,
)
if args.verbose:
print(LOG_GI_CREATED)
print_line()
gi.generate(
seed=args.seed,
start=args.start, step=args.step, stop=args.stop,
mode=args.mode,
)
if args.verbose:
print(LOG_GI_GENERATED)
print_line()
gi.plot(
color=args.color, bgcolor=args.bgcolor, cmap=args.cmap, spot_size=args.spot_size,
size=args.size, projection=args.projection, marker=args.marker, alpha=args.alpha,
linewidth=args.linewidth, rotation=args.rotation,
)
if args.verbose:
print(LOG_GI_PLOTTED)
print_line()
if not args.no_display:
plt.show()

if args.save_image:
result = gi.save_image(args.save_image, args.depth)
log_results(args.verbose, result, LOG_IMG_SAVED, ERR_IMG_SAVE_FAILED)
if args.save_data:
result = gi.save_data(args.save_data)
log_results(args.verbose, result, LOG_DATA_SAVED, ERR_DATA_SAVE_FAILED)
if args.save_config:
result = gi.save_config(args.save_config)
log_results(args.verbose, result, LOG_CONFIG_SAVED, ERR_CONFIG_SAVE_FAILED)
except (KeyboardInterrupt, EOFError):
print(EXIT_MESSAGE)
except Exception as e:
print(ERR_GENERAL.format(str(e)))
from .cli import main


if __name__ == "__main__":
Expand Down
162 changes: 162 additions & 0 deletions samila/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# -*- coding: utf-8 -*-
"""Samila CLI."""

import argparse
import matplotlib.pyplot as plt
from art import tprint
from .params import SAMILA_VERSION, GenerateMode, Projection, Marker
from .params import LOG_GI_CREATED, LOG_GI_GENERATED, LOG_GI_PLOTTED
from .params import LOG_IMG_SAVED, LOG_DATA_SAVED, LOG_CONFIG_SAVED
from .params import ERR_IMG_SAVE_FAILED, ERR_DATA_SAVE_FAILED, ERR_CONFIG_SAVE_FAILED
from .params import ERR_GENERAL, EXIT_MESSAGE
from .functions import samila_help, print_line
from .genimage import GenerativeImage


def init_argparse():
"""
Initialize argparse.
:return: parser
"""
parser = argparse.ArgumentParser()
parser.add_argument('--version', help='version', action='store_true', default=False)
parser.add_argument('--info', help='info', action='store_true', default=False)
parser.add_argument('--verbose', help='verbose', action='store_true', default=False)

parser.add_argument('--load-config', help='load config', type=str)
parser.add_argument('--load-data', help='load data', type=str)
parser.add_argument('--function1', help='function1', type=str)
parser.add_argument('--function2', help='function2', type=str)
parser.add_argument('--function_seed', help='function seed', type=str)

parser.add_argument('--seed', help='generate seed', type=str)
parser.add_argument('--start', help='start point', type=float)
parser.add_argument('--step', help='step size', type=float)
parser.add_argument('--stop', help='stop point', type=float)
parser.add_argument(
'--mode',
help='generation mode',
type=str,
choices=[x.value for x in GenerateMode])

parser.add_argument('--color', help='color', type=str)
parser.add_argument('--bgcolor', help='background color', type=str)
parser.add_argument('--cmap', help='cmap', type=str)
parser.add_argument('--spot-size', help='spot size', type=float)
parser.add_argument('--size', help='size', type=tuple)
parser.add_argument('--alpha', help='alpha', type=float)
parser.add_argument('--linewidth', help='line width', type=float)
parser.add_argument('--rotation', help='rotation', type=float)
parser.add_argument(
'--projection',
help='projection type',
type=str,
choices=[x.value for x in Projection])
parser.add_argument(
'--marker',
help='marker type',
type=str,
choices=[x.value for x in Marker])

parser.add_argument('--save-image', help='save image', type=str)
parser.add_argument('--depth', help='depth', type=float)
parser.add_argument('--save-data', help='save data', type=str)
parser.add_argument('--save-config', help='save config', type=str)
parser.add_argument('--no-display', help='no display', action='store_true', default=False)

return parser


def log_results(is_verbose, result, log_success, log_fail):
"""
Save result function.
:param is_verbose: is verbose
:type is_verbose: bool
:param result: result dictionary
:type result: dict
:param log_success: log for successful result
:type log_success: str
:param log_fail: log for failed result
:type log_fail: str
:return: None
"""
if is_verbose:
if result['status']:
print(log_success.format(result['message']))
print_line()
else:
print(log_fail.format(result['message']))
print_line()


def run_samila(args):
"""
Run samila.
:param args: arguments
:type args: argparse.Namespace
:return: None
"""
gi = GenerativeImage(
function1=args.function1, function2=args.function2,
func_seed=args.function_seed, data=args.load_data, config=args.load_config,
)
if args.verbose:
print(LOG_GI_CREATED)
print_line()
gi.generate(
seed=args.seed,
start=args.start, step=args.step, stop=args.stop,
mode=args.mode,
)
if args.verbose:
print(LOG_GI_GENERATED)
print_line()
gi.plot(
color=args.color, bgcolor=args.bgcolor, cmap=args.cmap, spot_size=args.spot_size,
size=args.size, projection=args.projection, marker=args.marker, alpha=args.alpha,
linewidth=args.linewidth, rotation=args.rotation,
)
if args.verbose:
print(LOG_GI_PLOTTED)
print_line()
if not args.no_display:
plt.show()

if args.save_image:
result = gi.save_image(args.save_image, args.depth)
log_results(args.verbose, result, LOG_IMG_SAVED, ERR_IMG_SAVE_FAILED)
if args.save_data:
result = gi.save_data(args.save_data)
log_results(args.verbose, result, LOG_DATA_SAVED, ERR_DATA_SAVE_FAILED)
if args.save_config:
result = gi.save_config(args.save_config)
log_results(args.verbose, result, LOG_CONFIG_SAVED, ERR_CONFIG_SAVE_FAILED)


def main(sys_args=None):
"""
CLI main function.
:param sys_args: system arguments
:type sys_args: list
:return: None
"""
parser = init_argparse()
args = parser.parse_args(args=sys_args)

if args.version:
print(SAMILA_VERSION)
elif args.info:
tprint("samila")
tprint("V:" + SAMILA_VERSION)
samila_help()
else:
try:
run_samila(args=args)
except (KeyboardInterrupt, EOFError):
print(EXIT_MESSAGE)
except Exception as e:
print(ERR_GENERAL.format(str(e)))
2 changes: 1 addition & 1 deletion samila/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
CONFIG_TYPE_ERROR = "Provided config file is not supported. It should be either file or io.IOBase."
CONFIG_FORMAT_ERROR = "Provided config file is not supported. It should include f1 and f2."
CONFIG_NO_STR_FUNCTION_ERROR = "Config file can't be saved. At least one of the function1_str or function2_str is None."
PLOT_DATA_ERROR = "Plotting process can't be Done because data{0} is empty. Use generate method first."
PLOT_DATA_ERROR = "Plotting process can't be done because data{0} is empty. Use generate method first."
COLOR_SIZE_ERROR = "Color list size is not equal to the data size."
SAVE_NO_DATA_ERROR = "Data file can't be saved. At least one of the data1 or data2 is None."
INVALID_COLOR_TYPE_ERROR = "Given color/bgcolor type is not supported."
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def read_description():
include_package_data=True,
entry_points={
'console_scripts': [
'samila = samila.__main__:main',
'samila = samila.cli:main',
]
}
)
Loading

0 comments on commit 7b0cdfc

Please sign in to comment.