moigagoo / cliar Goto Github PK
View Code? Open in Web Editor NEWCreate modular Python CLIs with type annotations and inheritance
Home Page: https://moigagoo.nim.town/cliar/
Create modular Python CLIs with type annotations and inheritance
Home Page: https://moigagoo.nim.town/cliar/
Hi, I'm testing Cliar and it seems awesome! I'm trying to use an optional parameter with underscores in its name, but it looks Cliar is failing because of the '_' to '-' replacement (or maybe I'm misusing it). It's working for positional arguments, but not for optional ones. I'm using Python 3.7.4.
Example:
from cliar import Cliar, set_help
class Calculator(Cliar):
""" Calculator app. """
@set_help({'number_x': 'Number X', 'number_y': 'Number Y'})
def add(self, number_x: float, number_y: float = 0):
""" Add two numbers. """
print(f'The sum of {number_x} and {number_y} is {number_x+number_y}.')
if __name__ == '__main__':
Calculator().parse()
Output:
$ python cli.py add 1 --number-y 1
Traceback (most recent call last):
File "cli.py", line 31, in <module>
Calculator().parse()
File "/.../lib/python3.7/site-packages/cliar/cliar.py", line 280, in parse
command_args = {arg: vars(args)[arg] for arg in command.args}
File "/.../lib/python3.7/site-packages/cliar/cliar.py", line 280, in <dictcomp>
command_args = {arg: vars(args)[arg] for arg in command.args}
KeyError: 'number-y'
Thanks!
Kindly include a license :)
This code
#!/usr/bin/env python3
from cliar import Cliar
class Cli(Cliar):
def _root(self, url="", username=""):
pass
if __name__ == "__main__":
cli = Cli()
cli.parse()
Returns
Traceback (most recent call last):
File "./cli.py", line 12, in
cli = Cli()
File "/usr/local/lib/python3.7/site-packages/cliar/cliar.py", line 126, in init
self._register_root_args()
File "/usr/local/lib/python3.7/site-packages/cliar/cliar.py", line 147, in _register_root_args
self._register_arg(self._parser, arg_name, arg_data)
File "/usr/local/lib/python3.7/site-packages/cliar/cliar.py", line 188, in _register_arg
help=arg_data.help
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/argparse.py", line 1367, in add_argument
return self._add_action(action)
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/argparse.py", line 1730, in _add_action
self._optionals._add_action(action)
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/argparse.py", line 1571, in _add_action
action = super(_ArgumentGroup, self)._add_action(action)
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/argparse.py", line 1381, in _add_action
self._check_conflict(action)
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/argparse.py", line 1520, in _check_conflict
conflict_handler(action, confl_optionals)
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/argparse.py", line 1529, in _handle_conflict_error
raise ArgumentError(action, message % conflict_string)
argparse.ArgumentError: argument -u/--username: conflicting option string: -u
I can change one option to an uppercase but then the long name has first character uppercase.
class Cli(Cliar):
def _root(self, url="", Username=""):
pass
usage: cli.py [-h] [-u URL] [-U USERNAME] {} ...
optional arguments:
-h, --help show this help message and exit
-u URL, --url URL
-U USERNAME, --Username USERNAMEcommands:
{} Available commands:
Is is possible to produce:
-u URL, --url URL
-U USERNAME, --username USERNAME
I don't see a way with set_metavars
either but perhaps I missed something in the docs.
Hello !
very well thought project!
I had a little glitch when adding to my project :
poetry add cliar
Using version ^1.3.4 for cliar
Updating dependencies
Resolving dependencies... (0.5s)
[SolverProblemError]
The current project's Python requirement (>=3.6) is not compatible with some of the required packages Python requirement:
- cliar requires Python >=3.6,<4.0
Because cliar (1.3.4) requires Python >=3.6,<4.0
and no versions of cliar match >1.3.4,<2.0.0, cliar is forbidden.
So, because run-cli-unity depends on cliar (^1.3.4), version solving failed.
I had to modify in my pyproject.toml :
[tool.poetry.dependencies]
python = ">=3.6,<4.0"
Do you know why <4.0 is needed ?
Thank you!
As the author of cliar already went through the effort of comparing Click, docopts and cliar, i'd be interesting to see how the fire project compares:
PEP 563 -- Postponed Evaluation of Annotations made it so that annotations are stored as string literals, instead of the actual objects.
The annotations must then be resolved at runtime. https://www.python.org/dev/peps/pep-0563/#resolving-type-hints-at-runtime
File "/Users/pragy.a/Desktop/categorization/iab_tester/venv/lib/python3.7/site-packages/cliar/cliar.py", line 163, in __init__
self._register_commands(handlers)
File "/Users/pragy.a/Desktop/categorization/iab_tester/venv/lib/python3.7/site-packages/cliar/cliar.py", line 242, in _register_commands
self._register_arg(command_parser, arg_name, arg_data)
File "/Users/pragy.a/Desktop/categorization/iab_tester/venv/lib/python3.7/site-packages/cliar/cliar.py", line 215, in _register_arg
help=arg_data.help
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/argparse.py", line 1358, in add_argument
raise ValueError('%r is not callable' % (type_func,))
ValueError: 'open' is not callable
Optional arguments show as follows:
optional arguments:
--trials TRIALS Maximum trials for each URL in case the API returns an error.
This leaves the user with no information about the default value. One can manually include the default value in the help text, but that results in duplicate code and forces the developer to update the value in two places should the default value change.
It would be nice if instead the default value could show up in a new line, as:
optional arguments:
--trials TRIALS Maximum trials for each URL in case the API returns an error.
default: 5
Take conda
for example. We have commands like this:
conda create
conda list
conda env create
conda env list
conda env export
or git
:
git init
git commit
git stack push
git stack pop
git remote add
git remote show
I think one way to handle this is to create subcommand class and explicitly pass args
to it's parse
function:
from cliar import Cliar
class StackCommand(Cliar):
def push(self, ...):
...
def pop(self, ...):
...
class MainCommand(Cliar):
def __init__(self):
self.stack_command = StackCommand()
def stack(self, args):
self.stack_command.parse(args)
Currently, the Cliar
class impliedly take args
from the command line.
However, I think taking args from another command may be useful to build complex CLI.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.