Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
bc67375
Feature: Refactor with own command-arg parser
winkidney Dec 15, 2017
9274551
Fix: Never display help message if function call success
winkidney Dec 20, 2017
9014095
Feature: Move all tests out of package
winkidney Dec 21, 2017
983010e
Refactor: Make root-node-name as constants
winkidney Dec 21, 2017
8206e64
Refactor: rename aparser to cmd_node
winkidney Dec 21, 2017
844f782
Refactor: Remove unused vars and parser-type code
winkidney Dec 21, 2017
3028fa0
Feature: Remove outdated parser tests / fix bug for normalize-func
winkidney Dec 21, 2017
5bde166
Refactor: Move help function to tree object
winkidney Dec 21, 2017
e76f54b
Fix: Fix reference error for CommandNode
winkidney Dec 21, 2017
108f084
Fix: Use correct comand for cmd-not-found error
winkidney Dec 21, 2017
43d7a05
Refacto: Improve error-message for sub-commands
winkidney Dec 21, 2017
65bc655
Fix: Fix all unittest for parser
winkidney Dec 21, 2017
e0d8a6f
Fix: index too large if positional argument detected
winkidney Dec 21, 2017
d806f1e
Fix: Use new path for test command
winkidney Dec 21, 2017
287f553
Fix: return entry execution result in entry
winkidney Dec 21, 2017
24c53d1
Fix: Remove unused argparse deps
winkidney Dec 21, 2017
e1d32ac
Fix: Try to fix "no tests found" error on travis
winkidney Dec 21, 2017
4c06eda
Feature: Catch and reprint error message
winkidney Dec 22, 2017
8408203
Feature: Remove unused runtest.sh
winkidney Jan 2, 2018
4a7fe45
Feature: Add help message for options/arguments/subcommands
winkidney Jan 2, 2018
82f09f4
Refactor: Add cmd_path for CommandNode
winkidney Jan 2, 2018
4c916fc
Refactor: Use cmd-path instead of cmd-name
winkidney Jan 3, 2018
46e68b2
Feature: Exit-code should be 1 if error occurs
winkidney Jan 3, 2018
2850c90
Feature: Add sub-commands help for all command
winkidney Jan 3, 2018
81a9db1
Fix: Fix wrong parent node for command-group's help message
winkidney Jan 3, 2018
fe6b3c6
Feature: Flake8
winkidney Jan 3, 2018
8c2af26
Feature: Add flake8 in travis-ci
winkidney Jan 3, 2018
7aa9fb0
Feature: Raise exception if parent node does not exist
winkidney Jan 3, 2018
22c5532
Feature: Use textwrap instead in python2
winkidney Jan 3, 2018
6753e36
Fix: flake8
winkidney Jan 3, 2018
af75b60
Fix: Remove CI for python-2.6
winkidney Jan 3, 2018
f6b3ed3
Fix: Remove support for python-3.2
winkidney Jan 3, 2018
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
6 changes: 4 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
language: python
python:
- 2.6
- 2.7
- 3.5
- 3.6
# command to install dependencies
before_install:
- pip install -r src/test-requirements.txt
Expand All @@ -11,6 +11,8 @@ install:
- cd src
- python setup.py install
# command to run tests
script: py.test cmdtree --cov=cmdtree
script:
- make test
- make flake8
after_success:
- coveralls
15 changes: 15 additions & 0 deletions doc/ParserFlow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

## Error Type

+ No such command
+ Argument Required
+ Invalid Argument Type

```
cmd_path = get_cmd_path()
parser = get_parser(cmd_path)
find command (argv, cmd_path)->
validate argument-length
find command(child_cmd_path, argv[command_2:])

```
2 changes: 2 additions & 0 deletions src/.flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[flake8]
max-line-length = 120
7 changes: 5 additions & 2 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ clean:
rm -fr ./dist ./build ./cmdtree.egg-info ./.cache

test:
py.test --cov=cmdtree --cov-report=term-missing cmdtree

py.test tests --cov=cmdtree --cov-report=term-missing cmdtree
flake8:
flake8 cmdtree
flake8 tests
flake8 examples
develop:
python setup.py develop
File renamed without changes.
17 changes: 15 additions & 2 deletions src/cmdtree/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from cmdtree.parser import AParser
from cmdtree.registry import env
from cmdtree.shortcuts import (
argument,
Expand All @@ -20,6 +19,20 @@
)

# globals and entry point
env.parser = AParser()
entry = env.entry

__all__ = (
"argument",
"option",
"command",
"group",
"STRING",
"INT",
"FLOAT",
"BOOL",
"UUID",
"Choices",
"IntRange",
"File",
"entry",
)
3 changes: 2 additions & 1 deletion src/cmdtree/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
def get_filesystem_encoding():
return sys.getfilesystemencoding() or sys.getdefaultencoding()


if WIN:
def _get_argv_encoding():
import locale
return locale.getpreferredencoding()
else:
def _get_argv_encoding():
return getattr(sys.stdin, 'encoding', None) or get_filesystem_encoding()
return getattr(sys.stdin, 'encoding', None) or get_filesystem_encoding()
1 change: 1 addition & 0 deletions src/cmdtree/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ROOT_NODE_NAME = "root"
23 changes: 23 additions & 0 deletions src/cmdtree/decorators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from functools import wraps

from cmdtree import echo
from cmdtree.exceptions import ParserError
from cmdtree.format import format_node_help


def format_error(func):

@wraps(func)
def wrapped(*args, **kwargs):
try:
return func(*args, **kwargs)
except ParserError as e:
assert hasattr(args[0], "tree")
node_dict = args[0].tree.get_node_by_path(
e.node.cmd_path
)
node_help = format_node_help(node_dict)
echo.error("Error: %s" % str(e.format_error(node_help)))
exit(1)

return wrapped
6 changes: 6 additions & 0 deletions src/cmdtree/echo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import sys


def error(error_msg):
sys.stderr.write(error_msg)
sys.stderr.write("\n")
72 changes: 70 additions & 2 deletions src/cmdtree/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,70 @@
class ArgumentParseError(ValueError):
pass

class ParserError(ValueError):
DEFAULT_TPL = (
"{error}\n\n"
"{cmd_ref}"
"{help}"
"{sub_cmd_help}"
)

def __init__(self, *args, **kwargs):
super(ParserError, self).__init__(*args)
self.node = kwargs.pop("node", None)

def format_error(self, sub_cmd_help=None):
cmd_ref = "Help message for '{name}':\n\n"
node_help = ""
_cmd_ref = ""
if sub_cmd_help is not None:
sub_cmd_help = sub_cmd_help + "\n"
else:
sub_cmd_help = ""
if self.node is not None:
node_help = self.node.format_help()
if node_help:
node_help += "\n\n"
_cmd_ref = cmd_ref.format(
name=self.node.name
)
return self.DEFAULT_TPL.format(
error=str(self),
cmd_ref=_cmd_ref,
sub_cmd_help=sub_cmd_help,
help=node_help,
)


class DevelopmentError(ValueError):
pass


class ArgumentRepeatedRegister(DevelopmentError):
pass


class ArgumentTypeError(DevelopmentError):
pass


class CmdRepeatedRegister(DevelopmentError):
pass


class NodeDoesExist(DevelopmentError):
pass


class NoSuchCommand(ParserError):
pass


class InvalidCommand(ParserError):
pass


class ArgumentError(ParserError):
pass


class OptionError(ParserError):
pass
88 changes: 88 additions & 0 deletions src/cmdtree/format.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from cmdtree.templates import E_NO_CMD_GIVEN_TPL

try:
from textwrap import indent
except ImportError:
import textwrap

def indent(text, indent_with):
wrapper = textwrap.TextWrapper(
initial_indent=indent_with,
subsequent_indent=indent_with
)
return wrapper.fill(text)


INDENT_1 = " " * 4


def _format_arg_help(argument):
"""
:type argument: cmdtree.parser.Argument
"""
tpl = "{name}: {help}"
_help = argument.help
if argument.help is None:
_help = "argument"
return tpl.format(
name=argument.name,
help=_help,
)


def _format_cmd_help(cmd_node):
tpl = "{name}: {help}"
_help = cmd_node.help
if cmd_node.help is None:
_help = cmd_node.name
return tpl.format(
name=cmd_node.name,
help=_help,
)


def _format_cmd_choice(parent_name, cmd_node_list):
help_msg = "\n".join(
_format_cmd_help(ele)
for ele in cmd_node_list
)
return E_NO_CMD_GIVEN_TPL.format(
name=parent_name,
cmds=indent(help_msg, INDENT_1)
)


def format_node_help(tree_node):
"""
:type tree_node: dict
"""
node = tree_node
_help = ""
if not node['cmd'].callable():
if node['cmd'].help is not None:
_help += node['cmd'].help
cmds = tuple(
value['cmd']
for value in node['children'].values()
)
if len(cmds) >= 0:
_help += _format_cmd_choice(node['name'], cmds)
return _help if len(_help) > 0 else None


def format_arg_help(title, arguments):
"""
:type arguments: iterable[cmdtree.parser.Argument]
:type title: str
"""
if len(arguments) == 0:
return
details = tuple(
_format_arg_help(arg)
for arg in arguments
)
details = indent("\n".join(details), INDENT_1)
return (
"{title}\n"
"{details}"
).format(title=title, details=details)
Loading