-
Notifications
You must be signed in to change notification settings - Fork 2
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
Refactor command line interface #14
Merged
tjesser-ucdavis-edu
merged 2 commits into
geodynamics:master
from
hlokavarapu:call_new_CLI
Jan 31, 2017
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
"""Submodule for 'license' command functionality. | ||
""" | ||
|
||
import licenses | ||
|
||
|
||
def main(args, config): | ||
"""CLI program command: list | ||
Output each supported license by name. | ||
""" | ||
for license_name in get_license_list(): | ||
print(license_name) | ||
|
||
|
||
def get_license_list(): | ||
"""Return a sorted list of supported license names. | ||
""" | ||
return sorted(licenses.license_dict.keys()) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,292 +1,32 @@ | ||
#! /usr/bin/env python3 | ||
|
||
import argparse | ||
import os | ||
import pprint | ||
import re | ||
|
||
import config_handling | ||
import license_handling | ||
import userfiles_handling | ||
import utils.load_config as utils | ||
|
||
import cli_parser.main_parser as main_parser | ||
|
||
def main_check(args, config): | ||
"""CLI program command: check | ||
Check project files for license/header text. | ||
""" | ||
if args.files: | ||
filepaths = set(args.files) | ||
else: | ||
filepaths = (os.path.relpath(os.path.join(cwd, file)) | ||
for cwd, dirs, files in os.walk(".") | ||
for file in files | ||
if file != config_handling.CONFIG_FILENAME) | ||
|
||
if (not args.no_ignore) and config["IgnoredFiles"]: | ||
ignore_regex = "|".join( | ||
config_handling.param_ignoredfiles_to_regex(ignore_string) | ||
for ignore_string | ||
in config["IgnoredFiles"] | ||
) | ||
|
||
filepaths = (file for file in filepaths | ||
if not re.match(ignore_regex, file)) | ||
|
||
if filepaths: | ||
text_dict = license_handling.fill_in_license( | ||
config["License"], config | ||
) | ||
|
||
license_text = text_dict["license_text"] | ||
header_text = text_dict["header_text"] | ||
|
||
for path in filepaths: | ||
if not userfiles_handling.file_has_correct_header(path, args, config): | ||
if args.add_missing: | ||
if args.info_level == "verbose": | ||
print("Adding header to {}.".format(path)) | ||
|
||
commented_header_text, comment_format = \ | ||
license_handling.comment_out_header( | ||
header_text, path, args, config | ||
) | ||
|
||
userfiles_handling.write_header( | ||
commented_header_text, | ||
path, | ||
( | ||
comment_format.get("InsertAtLine", 0) | ||
if comment_format | ||
else 0 | ||
), | ||
) | ||
else: | ||
if args.info_level == "quiet": | ||
print(path) | ||
else: | ||
print( | ||
"{} has an incorrect or missing header.".format(path) | ||
) | ||
|
||
|
||
def main_choose(args, config): | ||
"""CLI program command: choose | ||
Select or change a project license. | ||
""" | ||
if args.license in license_handling.get_license_list(): | ||
def arg_to_parameters(string_list): | ||
return dict(pair.split(":") | ||
for arg in string_list | ||
for pair in arg.split(",")) | ||
|
||
if args.parameters: | ||
try: | ||
args.parameters = arg_to_parameters(args.parameters) | ||
except TypeError: | ||
print("ERROR: Parameter input not formatted properly") | ||
exit(1) | ||
|
||
config["License"] = args.license | ||
|
||
userfiles_handling.update_license(config) | ||
|
||
else: | ||
print(("WARNING: {} is not a supported license. Please use the list" | ||
" command to see a list of supported licenses." | ||
).format(args.license)) | ||
|
||
|
||
def main_list(args, config): | ||
"""CLI program command: list | ||
Output each supported license by name. | ||
""" | ||
for license_name in license_handling.get_license_list(): | ||
print(license_name) | ||
|
||
|
||
def main_settings(args, config): | ||
"""CLI program command: settings | ||
Display or edit project license configuration. | ||
""" | ||
if args.info_level != "verbose": | ||
pprint.pprint(config, depth=2) | ||
else: | ||
def dict_doc_print(d, doc, acc=""): | ||
indent = " " | ||
|
||
if hasattr(d, "items"): | ||
for key, value in d.items(): | ||
if doc.get(key): | ||
print("\n" + acc + "# " + str(doc.get(key))) | ||
print(acc + str(key) + ":") | ||
|
||
if hasattr(value, "items"): | ||
dict_doc_print(value, doc, acc + indent) | ||
elif hasattr(value, "__iter__") and value != str(value): | ||
for x in value: | ||
print(acc + indent + str(x)) | ||
else: | ||
print(acc + indent + str(value)) | ||
|
||
config_doc = { | ||
"License": ("The license that will be used to generate the LICENSE" | ||
" file"), | ||
"LicenseParameters": ("Necessary user input to be inserted into" | ||
" the license"), | ||
} | ||
|
||
dict_doc_print(config, config_doc) | ||
|
||
|
||
def create_main_parser(): | ||
"""Create CLI parser for this program. | ||
""" | ||
parser = argparse.ArgumentParser( | ||
description="Where you go to get your software license.", | ||
) | ||
subparsers = parser.add_subparsers( | ||
title="Commands", | ||
dest="command", | ||
) | ||
subparsers.required = True | ||
|
||
parser_check = subparsers.add_parser( | ||
"check", | ||
help="Check all project files for licensing information", | ||
description="Check all project files for licensing information.", | ||
) | ||
parser_check.add_argument( | ||
"--no-ignore", | ||
action="store_true", | ||
help="Also check files that are set to be ignored", | ||
) | ||
parser_check.add_argument( | ||
"-a", | ||
"--add-missing", | ||
action="store_true", | ||
help="Add project license to files that fail the check", | ||
) | ||
parser_check.add_argument( | ||
"-f", | ||
"--files", | ||
metavar="FILE", | ||
nargs="+", | ||
help="Check these files only", | ||
) | ||
|
||
verbosity_group = parser_check.add_mutually_exclusive_group() | ||
|
||
verbosity_group.add_argument( | ||
"-v", | ||
"--verbose", | ||
action="store_const", | ||
const="verbose", | ||
dest="info_level", | ||
default="", | ||
help="Output more information about executed command", | ||
) | ||
verbosity_group.add_argument( | ||
"-q", | ||
"--quiet", | ||
action="store_const", | ||
const="quiet", | ||
dest="info_level", | ||
default="", | ||
help="Silence all non-error output", | ||
) | ||
|
||
parser_choose = subparsers.add_parser( | ||
"choose", | ||
help="Choose a license to insert into your project", | ||
description="Choose a license to insert into your project.", | ||
) | ||
|
||
verbosity_group = parser_choose.add_mutually_exclusive_group() | ||
|
||
verbosity_group.add_argument( | ||
"-v", | ||
"--verbose", | ||
action="store_const", | ||
const="verbose", | ||
dest="info_level", | ||
default="", | ||
help="Output more information about executed command", | ||
) | ||
verbosity_group.add_argument( | ||
"-q", | ||
"--quiet", | ||
action="store_const", | ||
const="quiet", | ||
dest="info_level", | ||
default="", | ||
help="Silence all non-error output", | ||
) | ||
|
||
parser_choose.add_argument( | ||
"--no-apply", | ||
action="store_false", | ||
dest="apply_choice", | ||
help="Write/update config file, but do not apply license to project", | ||
) | ||
|
||
parser_choose.add_argument( | ||
"-p", | ||
"--parameter", | ||
action="append", | ||
dest="parameters", | ||
help=("Set a license parameter. Input is in key:value form and" | ||
" multiple parameters can be set by using multiple flags or by" | ||
" concatenating key-value pairs with commas. e.g. '--parameter=" | ||
"project:foo,author:bar'."), | ||
) | ||
parser_choose.add_argument( | ||
"license", | ||
metavar="LICENSE", | ||
help=("License to be created for your project. Use the 'list' command" | ||
" to see all supported licenses."), | ||
) | ||
|
||
parser_list = subparsers.add_parser( | ||
"list", | ||
help="List supported licenses", | ||
description="List supported licenses.", | ||
) | ||
|
||
parser_settings = subparsers.add_parser( | ||
"settings", | ||
help="Show current license settings for your project", | ||
description="Show current license settings for your project.", | ||
) | ||
parser_settings.add_argument( | ||
"-v", | ||
"--verbose", | ||
action="store_const", | ||
const="verbose", | ||
dest="info_level", | ||
default="", | ||
help="Show all settings and their documentation", | ||
) | ||
|
||
return parser | ||
|
||
import program_commands.check_command as check_command | ||
import program_commands.config_command as config_command | ||
import program_commands.license_command as license_command | ||
import program_commands.write_command as write_command | ||
|
||
def main(args): | ||
"""Program entrypoint. | ||
Calls requested CLI command. | ||
""" | ||
|
||
if args.command == "list": | ||
main_list(args, None) | ||
if args.command == "license": | ||
license_command.main(args, None) | ||
else: | ||
config = config_handling.load_configfile() | ||
if args.command == "check": | ||
main_check(args, config) | ||
elif args.command == "choose": | ||
main_choose(args, config) | ||
elif args.command == "settings": | ||
main_settings(args, config) | ||
config = utils.load_config(".") | ||
if args.command == "check" or args.command == "check-project": | ||
check_command.main(args, config) | ||
elif args.command == "config": | ||
config_command.main(args) | ||
elif args.command == "write": | ||
write_command.main(args, config) | ||
|
||
|
||
if __name__ == "__main__": | ||
main(create_main_parser().parse_args()) | ||
main(main_parser.create_main_parser().parse_args()) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the new CLI doesn't use this file, changing it shouldn't be in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally, however, the file program_commands/check_command
imports userfiles_handling
which then wraps back toimport userfiles_handling
For example,
The following functions are defined in userfiles_handling and are called in check_command module:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Darn. Okay, it's probably better to save removing this dependency for a different PR then.