ialbert / plac Goto Github PK
View Code? Open in Web Editor NEWPlac: Parsing the Command Line the Easy Way
License: BSD 2-Clause "Simplified" License
Plac: Parsing the Command Line the Easy Way
License: BSD 2-Clause "Simplified" License
There are two broken links in the section http://micheles.github.io/plac/#plac-vs-argparse
two links with the text advanced usage document link to a non-existent link http://micheles.github.io/plac/in-writing
I assume the link address needs corrected to http://micheles.github.io/plac/#implementing-subcommands
plac currently requires option names to be valid python identifiers, so it is
impossible to have an option like "--dry-run". You have to use "--dry_run"
instead, which is awkward because it has both dashes and underscores in it.
This can be fixed with just a one-line patch that replaces underscores with
dashes in option names before calling add_argument.
I'm including the patch below. It includes two possibilities: either accept
*only* dashed options, or accept options with either dashes or underscores,
which would be more backward-compatible, but sometimes confusing in the help
screen.
$ hg diff -w plac_core.py
diff --git a/plac_core.py b/plac_core.py
--- a/plac_core.py
+++ b/plac_core.py
@@ -255,6 +255,10 @@
shortlong = (prefix + a.abbrev, prefix*2 + name)
else:
shortlong = (prefix + name,)
+ # Replace underscores with dashes in argument names
+ # shortlong = [ s.replace('_', '-') for s in shortlong ]
+ # # Accept either dashes or underscores
+ shortlong = tuple([ s.replace('_', '-') for s in shortlong if
s.find('_') != -1 ]) + shortlong
elif default is NONE: # required argument
self.add_argument(name, help=a.help, type=a.type,
choices=a.choices, metavar=metavar)
Original issue reported on code.google.com by [email protected]
on 16 Dec 2011 at 1:01
Google code page hosting for plac just goes to a 404 now for these two links:
Plac shows default argument as argparse metavar. But when argparse is given a metavar of an empty string, the results look more like a flag than an option, which is confusing. (To be fair, there are differences, but very hard to spot.)
$ cat test_plac.py
#!/usr/bin/env python
def func(opt: ('opt', 'option', 'o') = ''):
print(opt)
import plac
plac.call(func)
$ ./test_plac.py -h
usage: test_plac.py [-h] [-o]
optional arguments:
-h, --help show this help message and exit
-o , --opt opt
When running python scripts that depend on plac_ext.py
under a recent version of Python, a deprecation warning will be issued on every run:
/home/leonard/.local/lib64/python3.6/site-packages/plac_ext.py:6: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
import imp
Minimum code to replicate this bug:
Python 3.6.8 |Anaconda, Inc.| (default, Dec 29 2018, 19:04:46)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.4.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: import plac
In [2]: def foo(a: str): return
In [3]: p = plac.parser_from(foo)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-3-3cd6684a2926> in <module>()
----> 1 p = plac.parser_from(foo)
~/anaconda3/lib/python3.6/site-packages/plac_core.py in parser_from(obj, **confparams)
182 parser.addsubcommands(obj.commands, obj, 'subcommands')
183 else:
--> 184 parser.populate_from(obj)
185 return parser
186
~/anaconda3/lib/python3.6/site-packages/plac_core.py in populate_from(self, func)
332 for name, default in zip(f.args, alldefaults):
333 ann = f.annotations.get(name, ())
--> 334 a = Annotation.from_(ann)
335 metavar = a.metavar
336 if default is NONE:
~/anaconda3/lib/python3.6/site-packages/plac_core.py in from_(cls, obj)
136 return obj # do nothing
137 elif hasattr(obj, '__iter__') and not isinstance(obj, (str, bytes)):
--> 138 return cls(*obj)
139 return cls(obj)
140 from_ = classmethod(from_)
TypeError: type object argument after * must be an iterable, not type
In [4]:
The problematic code is here:
Line 137 in a970c1a
Hi . I want to read a list of plugins from a config file, then dynamically generate usage and options parsing information for them. The config file is also specified via an argument on the command line invocation, but the modules are loaded with import_module at runtime based on the config.
Are there any examples of how to do this?
I really like this library and have been using it regularly.
While doing so made me realize several substantial limitations in the way this tool is documented and explained, that, in my opinion, is perhaps the greatest hindrance to the acceptance of the tool.
Whenever I forget the exact invocation or I want to look up more details I find that the documentation website at
https://micheles.github.io/plac/
is very tedious and non-supportive to help get things done. It has a long-winded writing style and goes into various tangential issues on the rationale. Overall it fails to support the practical use cases that a programmer needs and wants. Give us examples on how to use the tool.
Imagine that you are using a library and trying to look up the use cases, instead the documentation writer continuously talks about the rationale then and produces examples that are either too simplistic or too complicated - that is exactly how I feel reading the docs.
The entire library is meant to demonstrate the importance of scaling down" yet the help and documentation is anything but scaling down.
In the eagerness to demonstrate how easy is to use the library everything is documented in several, alternative and different ways - only adding to the confusion.
The actual feature that everyone will eventually use for anything but the most trivial code is listed deep down in the "More features" section, this is the line I have to constantly find to remind myself of the order of annotations:
(help, kind, abbrev, type, choices, metavar)
The entire documentation should start with a simple example like so
@plac.annotations(
fname=("input file", "option", "f", str, None, "PATH"),
count=("word count", "option", "c", int, None, "INT"),
)
def run(fname, count):
pass
perhaps adding a few variants to cover the main use-cases
so that people can look that up and move on and not have to continuously scour through pages and pages of content they don't care about.
print >> sys.stderr, 'Process %d killed by CTRL-C' % os.getpid()
in plac_tk.py will break in Python 3.
Thanks
This looks like a very promising library for simplifying command line argument handling. However I have a use case which may not be handled. I read the documentation but am not sure if it is possible or not.
I was wondering how to go about calling an intermediate function (named facade) in a library that uses some arguments and then passes back to the project's main function?
eg.
def main(hdx_site: str = "prod", output_failures: bool = False):
print(f"I only use output_failures which is {output_failures}")
if __name__ == "__main__":
plac.call(main)
The library has the intermediate function, facade:
def facade(projectmainfn: Callable[[Any], None], **kwargs: Any):
print(f"I do some setup and use hdx_site which is {hdx_site} then I call the project's main")
projectmainfn(**kwargs)
The plac.call line needs to use main to get the allowed command line arguments, but call facade passing main and the the parsed keyword arguments as parameters to facade. facade does some stuff using some of those arguments then calls main with them (although not all are actually used by main).
Is this possible somehow?
What steps will reproduce the problem?
1. download plac-0.9.1.tar.gz from pypi
2. install to python 3.3.1 with
py -3.3 setup.py install
(this is equivalent to c:\python33\python.exe setup.py install)
3. cd plac-0.9.1
py -3.3 test_plac.py
What is the expected output?
A message telling all ok or no output at all
What do you see instead?
D:\tmp\plac-0.9.1\doc>py -3 test_plac.py
Running test_batch
Running test_cmd_abbrevs
usage: test_plac.py {help,commit} ...
test_plac.py: error: No command 'foo'
Running test_cmds
Traceback (most recent call last):
File "test_plac.py", line 230, in <module>
maybegen = test()
File "test_plac.py", line 184, in test_cmds
expect(SystemExit, plac.call, cmds, [])
File "test_plac.py", line 18, in expect
func(*args, **kw)
File "C:\Python33\lib\site-packages\plac-0.9.1-py3.3.egg\plac_core.py", line 3
09, in call
cmd, result = parser_from(obj).consume(arglist)
File "C:\Python33\lib\site-packages\plac-0.9.1-py3.3.egg\plac_core.py", line 1
89, in consume
args = [getattr(ns, a) for a in self.argspec.args]
AttributeError: 'ArgumentParser' object has no attribute 'argspec'
What version of the product are you using? On what operating system?
plac 0.9.1
On windows xp sp3
Please provide any additional information below.
Installing and testing to python 2.7 shows no error.
Running test_plac.py in py 3.3.1 with pytest 2.3.5 tells that it is the only
test failing in the file, (besides the one for sqlalchemy, which fails because
the module is missing)
Additionally, deprecation warnings are seen for module imp.
Original issue reported on code.google.com by [email protected]
on 9 May 2013 at 10:49
I know this is painful to fix, but I call it a bug anyway because it is very unexpected: users would think it easy to know that "--opt", requiring one option, will take the "abc=" below.
$ cat test_plac.py
#!/usr/bin/env python
def func(opt: ('opt', 'option', 'o') = 'foo', **kw: ('kw',)):
print(opt, kw)
import plac
plac.call(func)
$ python test_plac.py --opt abc=
usage: test_plac.py [-h] [-o foo] [kw [kw ...]]
test_plac.py: error: argument -o/--opt: expected one argument
http://google-opensource.blogspot.com/2015/03/farewell-to-google-code.html
Original issue reported on code.google.com by [email protected]
on 13 Mar 2015 at 11:51
The documentation is bit hard to read, mostly due to it's presentation/templating I guess, which is very off from the expected python standards used in the community.
I am attaching some screenshots for comparison, showing the extremes of a 4k desktop and a mobile screen:
https://click.palletsprojects.com/en/7.x/options/
https://docs.scrapy.org/en/latest/intro/tutorial.html
Requests:
https://requests.kennethreitz.org/en/master/user/advanced/
The counter examples seem so more easier to follow and pleasant to read, both on mobile and on larger screens (except for requests on mobile, which is a little bit off).
The main points for improvement I identified are:
The pdf version has the same issues, except for the fixed margin, which helps on desktop, but it is still not responsive (friendly on a range of screens).
I personally love this project and how it scales down, but at a first contact I did find it very welcoming for the questions I had that the README didn't answer and I almost skipped it. I'm glad I stayed but I wonder if the same happened to others. I would love to see this project gaining more visibility and adoption and I believe a more pleasant documentation could help.
I can see a fair amount of time was already spent on the documentation content, it's just that its current presentation doesn't do it justice .
I think the https://readthedocs.org/ project already has a very good default template that addresses most of the issues I am pointing. They use sphinx, which support rst format that plac is already using, so I believe the migration would be fairly simple.
If the issue seems fair and help is wanted, let me know 😉
Is there a way to still support nargs while using plac? I know there is no plan to support it in plac but is there a workaround that can be used?
I have a script with two subcommands (say install and update), and I want to
add a argument that is common to all subcommands (verbose), in order to do this
:
python myscript.py -v install
or
python myscript.py -v update
without having to write the code to handle -v twice.
I couln't find it in the docs nor by reading the code. Is there a way to do so
? If I think this is a valid use case.
Original issue reported on code.google.com by [email protected]
on 6 Feb 2012 at 9:50
usage: example5.py [-h] dsn [table] [today]
Do something on the database
positional arguments:
dsn
table # default here?
today # default here?
Original issue reported on code.google.com by [email protected]
on 12 May 2011 at 9:02
since plac is a wrapper over argparse, it seems there is an issue when running it inside a Jupyter Notebook.
Here's an example from spacy tutorials
At runtime, I get the following error:
usage: ipykernel_launcher.py [-h] [-m None] [-o None] [-n 100]
ipykernel_launcher.py: error: unrecognized arguments: -f /Users/<my_user>/Library/Jupyter/runtime/kernel-b09996b6-dd81-4a9a-8619-c99b6c9a4919.json
An exception has occurred, use %tb to see the full traceback.
SystemExit: 2
/Users/<my_user>/anaconda3/lib/python3.6/site-packages/IPython/core/interactiveshell.py:2918: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.
warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
I found a workaround for argparse on stackoverflow, but I am not sure if it can be applied to plac.
Does plac support named arguments, like below?
python myfile.py positional1 positional2 --some-named=True
Thanks for the great tool. It is very enjoyable to use.
One problem that impacts usability is that multiline docstrings will be printed indented in the automatically generated help. This basically forces us to only have single quote docstrings which does two things, limits help to one line but also interferes with code formatting standards. Many tools will reformat docstrings to triple quote blocks.
I was wondering if you have plans to add an automatic de-denting of the docstring, or if not if you could point me to the code where I could add this de-denting myself in a local fork of the code.
thanks.
I would expect this decoration
@plac.opt('n', "Number of iterations", type=int, choices=[100,200] )
to show the choices on the help message (like it does using argparse directly)
Example:
`@plac.pos('gds', "GDSII input file name", type=Path)
@plac.opt('out', "Optional output directory", type=Path)
@plac.opt('n', "Number of iterations", type=int, choices=[100,200] )
@plac.flg('debug', "Enable debug mode")
def main(
gds, # required
out='.', #optional. Default to cwd.
n=100, #optional. Example of int.
debug=False,#optional. Example of boolean.
):
''' What does this program not do? ''' # Displayed in usage message.
print(f"-gds {gds}")
print(f"-out {out}")
print(f"-n {n}")
print(f"-debug {debug}")
return
`
But output does not show choices 100, 200 :
...
optional arguments:
-h, --help show this help message and exit
-o ., --out . Optional output directory
-n 100, --n 100 Number of iterations
-d, --debug Enable debug mode
...
Do I want to implement that?
Original issue reported on code.google.com by [email protected]
on 18 Jun 2011 at 5:59
In some cases, the programmer has to perform additional validation of arguments
beyond what is possible in Plac (for example, when arguments depend on each
other or conflict with each other). When doing this additional validation, it
would be nice to be able to print an error message followed by the script's
help text, or simply print the help text by itself. I have an example
implementation of this (linked below), but it's imperfect because it requires
you to tell it how far up the stack the "main" function is. I wonder if it is
possible to make available the "currently active" plac parser object, i.e. the
parser generated by the latest call to "plac.call".
https://github.com/DarwinAwardWinner/placsupport/blob/master/placsupport/__init_
_.py
Original issue reported on code.google.com by [email protected]
on 17 Jun 2012 at 8:39
plac is now producing an universal wheel with use_2to3
which does not appear to work. If you pip install plac in Python 2 you will get the 2to3 fixes, eg. print('Process %d killed by CTRL-C' % os.getpid(), file=sys.stderr)
withouth from __future__ import print_function
.
I guess that until you remove 2to3 (which would be a good change!) you will have to use the old way and distribute Python 2 and Python 3 versions.
Thanks
Following the examples in the documentation,
def main(dirname):
""" Do something with this directory.
"""
if __name__ == "__main__":
import plac; plac.call(main)
works correctly. but changing the definition to
def main(dirname: str):
which is valid Python 3.5 (with typing
package) or valid Python 3.6, results in
Traceback (most recent call last):
File "process.py", line 47, in <module>
import plac; plac.call(main)
File "/home/user/.local/lib/python3.6/site-packages/plac_core.py", line 324, in call
parser = parser_from(obj)
File "/home/user/.local/lib/python3.6/site-packages/plac_core.py", line 133, in parser_from
parser.populate_from(obj)
File "/home/user/.local/lib/python3.6/site-packages/plac_core.py", line 257, in populate_from
a = Annotation.from_(ann)
File "/home/user/.local/lib/python3.6/site-packages/plac_core.py", line 91, in from_
return cls(*obj)
TypeError: type object argument after * must be an iterable, not type
What steps will reproduce the problem?
1. Define a command; insert unicode character into docstring
2. Attempt to print script's help
Expect to see the help string; instead experience a stack trace.
pip show plac
---
Name: plac
Version: 0.9.1
See attached test case. Use with:
python test.py -h
See attached patch for one way to fix.
Original issue reported on code.google.com by [email protected]
on 20 Jan 2015 at 7:57
Attachments:
Not sure if I am doing something wrong, but I am trying to run this simple test from the IPython prompt where I do most of my dev work but it is not picking up the -h
flag or any other normal arguments. I am printing the sys.argv
just for debugging purposes.
It seems like this should work just like from the bash prompt. Here is my code:
#!/usr/bin/env python
"""
Testing CLI
"""
import sys
import plac
# @plac.annotations(
# dsn=("Random input", "option", "dsn", int))
def main(dsn):
print dsn
if __name__ == '__main__':
print sys.argv
plac.call(main)
Output:
# IPython prompt
In [43]: %run clitest.py -h
['clitest.py', '-h']
usage: clitest.py [-h] dsn
clitest.py: error: too few arguments
An exception has occurred, use %tb to see the full traceback.
SystemExit: 2
In [44]:
I think current folder structure in the project is a bit confusing. First time I looked around I thought the project had no tests, for my first PR I then found them "hidden" in the doc
folder, there is a lot of files in there and it is the only folder in the project.
Perhaps a layout like this could make things much more clearer to users and contributors:
plac/
│
├── docs/
│ ├── snippets/
│ │ ├── example1.py
│ │ ├── example2.py
│ │ ├── example3.help
│ │ ├── example3.py
│ │ └── ...
│ ├── plac_adv.rst
│ ├── plac_core.rst
│ └── plac.rst
│
├── plac/
│ ├── __init__.py
│ ├── core.py
│ ├── ext.py
│ ├── runner.py
│ └── tk.py
│
├── tests/
│ ├── test_ishelve_more.py
│ ├── test_ishelve.py
│ ├── test_pi.py
│ ├── test_plac.py
│ ├── test_runp.py
│ └── test_server.py
│
├── .travis.yml
├── LICENSE.txt
├── Makefile
├── MANIFEST.in
├── README.rst
├── setup.cfg
└── setup.py
Since plac supports multiple python versions, an added benefit would be easier future integration with tox.
Some interesting references on project layouts:
First of all, thank you very much for plac
, it is a very useful tool.
I would like to know if it is possible to choose the function to call in the command line?
Simply by taking the example of the doc.
# updatedb.py
import sys
from datetime import datetime
def main(dsn, table='product', today=datetime.today()):
"Do something on the database"
print(dsn, table, today)
def main2(dsn, table='product', today=datetime.today()):
"Do something on the database"
print(dsn, table, today)
FUNCTION_MAP = {'main' : main,
'main2': main2}
if __name__ == '__main__':
import plac
plac.call(FUNCTION_MAP[sys.argv[1]])
Like this, an error is raised:
python updatedb.py "main2" hello
Is there a way? I don't think I saw an example like this in the doc. Thank you for your help.
One should rething the mechanism for commands declaration
Original issue reported on code.google.com by [email protected]
on 15 Jun 2011 at 8:21
Without kwargs, unrecognized arguments leads to an error notifying the user that the command used is wrong. But with kwargs...
$ cat test_plac.py
#!/usr/bin/env python
def func(**kw: ('kw',)):
print(kw)
import plac
plac.call(func)
$ ./test_plac.py foo
{}
Please change Description text
Automatically exported from code.google.com/p/plac
into
Plac: Parsing the Command Line the Easy Way
See this line: https://github.com/micheles/plac/blob/master/setup.py#L40
PyPI description says that it only exists for python 2.5/2.5: https://pypi.org/project/multiprocessing/
What steps will reproduce the problem?
1. install python 3.2.3 and plac 0.9.1
2. in plac doc folder execute "example3.py foo"
What is the expected output? What do you see instead?
expected:
foo
instead:
Traceback (most recent call last):
File "C:\Setup\ heruntergeladen\Python\plac-0.9.1.tar\dist\plac-0.9.1\doc\example3.py", line 8, in <module>
import plac; plac.call(main)
File "C:\run\Python\lib\site-packages\plac.py", line 35, in <module>
from plac_ext import (Interpreter, import_main, ReadlineInput,
File "C:\run\Python\lib\site-packages\plac_ext.py", line 33
raise etype, exc, tb
^
SyntaxError: invalid syntax
What version of the product are you using? On what operating system?
Windows 7
Python 3.2.3
plac-0.9.1.tar.gz, downloaded from PyPi, installed via "python setup.py install"
Please provide any additional information below.
i have seen this multible tracebacks thing anywhere, but cant find it anymore,
isnt that a new python 3.x thing?
Original issue reported on code.google.com by [email protected]
on 2 Jul 2012 at 5:18
Use the same example from the tutorial (ishelve), I'm using python2.7 on amd64
Arch Linux.
What is the expected output? What do you see instead?
There is the following traceback:
python2.7 ishelve_i.py -i
Traceback (most recent call last):
File "ishelve_i.py", line 19, in <module>
plac.call(main)
File "/usr/lib/python2.7/site-packages/plac_core.py", line 309, in call
cmd, result = parser_from(obj).consume(arglist)
File "/usr/lib/python2.7/site-packages/plac_core.py", line 195, in consume
return cmd, self.func(*(args + varargs + extraopts), **kwargs)
File "ishelve_i.py", line 13, in main
plac.Interpreter(ishelve.main).interact()
File "/usr/lib/python2.7/site-packages/plac_ext.py", line 805, in __init__
self.tm = TaskManager(obj)
File "/usr/lib/python2.7/site-packages/plac_ext.py", line 482, in __init__
obj, prog='' if interact else None, formatter_class=PlacFormatter)
File "/usr/lib/python2.7/site-packages/plac_core.py", line 127, in parser_from
parser.populate_from(obj)
File "/usr/lib/python2.7/site-packages/plac_core.py", line 275, in populate_from
self.add_argument(action='store_true', help=a.help, *shortlong)
File "/usr/lib/python2.7/argparse.py", line 1291, in add_argument
self._get_formatter()._format_args(action, None)
File "/usr/lib/python2.7/argparse.py", line 572, in _format_args
get_metavar = self._metavar_formatter(action, default_metavar)
File "/usr/lib/python2.7/site-packages/plac_ext.py", line 165, in _metavar_formatter
action.choices = dict((n, c) for n, c in action.choices.iteritems()
AttributeError: 'NoneType' object has no attribute 'iteritems'
[1] 7853 exit 1 python2.7 ishelve_i.py -i
What version of the product are you using? On what operating system?
plac 0.9.0, Python 2.7.2
Please provide any additional information below.
Original issue reported on code.google.com by [email protected]
on 31 Oct 2011 at 8:28
It seems the feature "Determine argument type automatically from default" described on issue #22
breaks the default value of None
, which is pretty common idiom in python.
See, this works:
def main(posarg1, posarg2, posarg3=''):
pass
But this does not:
def main(posarg1, posarg2, posarg3=None):
pass
Output:
$ python plac_exp.py aaaa bbbb cccc
usage: plac_exp.py [-h] arg1 arg2 [arg3]
plac_exp.py: error: argument arg3: invalid NoneType value: 'cccc'
This idiom is very commonly used to differentiate falsy objects with is not None
instead of just boolean check.
For instance, in the example above, empty string is a valid input for me and None is used to differentiate it from an omitted argument.
I'm writing a program that I want to distribute with a setup.py that contains the following lines:
entry_points={
'console_scripts': [
'git-explorer=git_explorer.cli:main',
'git-explorer-similar=git_explorer.find_similar:main',
],
},
the find_similar.py
contains this:
if __name__ == '__main__':
plac.call(main)
And the main
function declaration looks like this:
@plac.annotations(
repo_url=("Repository", "positional", None, str, None, 'REPOSITORY'),
commit_id=("Commit", "positional", None, str, None, 'COMMIT'),
limit=("Only search among the LIMIT latest commits (tip: supports negavive numbers)", "option", 'l', int, None, 'LIMIT'),
fast=("Skip fetching if local repository exists", "flag", 's', bool, False),
git_cache= ("Git repository dir", "option", 'g', str, GIT_CACHE, 'GIT_CACHE'),
verbose=("Verbose", "flag", 'v', bool),
)
def main(repo_url, commit_id, limit=0, fast=False, git_cache=GIT_CACHE, verbose=False):
.....
.....
Now, if I install the package and try to use the console script git-explorer-similar
I get the following:
Traceback (most recent call last):
File "/home/xxxxxx/.local/share/virtualenvs/git_explorer-Hd8x6_Ku/bin/git-explorer-similar", line 11, in <module>
load_entry_point('git-explorer', 'console_scripts', 'git-explorer-similar')()
TypeError: main() missing 2 required positional arguments: 'repo_url' and 'commit_id'
What is the correct way to use plac in combination with the console_scripts
directive of a standard setup.py
? I could not find anything in the otherwise excellent documentation...
I know that this was already raised here
(https://code.google.com/p/plac/issues/detail?id=8) and was declared invalid,
but my use-case is quite different so might be reconsidered?
If you consider svn as an example of a program with sub-commands, you might
want to have an `svn --version` option. This is a global setting that should
always have the same effect, independent of the sub-command and in fact should
work without a sub-command.
If there is already a way to achieve this, I'd appreciate your help.
Thanks,
David
Original issue reported on code.google.com by [email protected]
on 9 Aug 2013 at 11:45
Hello,
Using a straight copy-paste of example9.py as listed on http://micheles.github.io/plac/#scripts-with-flags , I get the following error:
./plactest00.py hello
./plactest00.py: line 3: syntax error near unexpected token (' ./plactest00.py: line 3:
def main(verbose: ('prints more info', 'flag', 'v'), dsn: 'connection string'):'
I am a Python novice, so if I'm missing anything obvious I apologize in advance.
OS: Mac OS X 10.12.6
Python: Python 2.7.10
virtualenv:
certifi (2017.7.27.1)
chardet (3.0.4)
idna (2.6)
keyring (5.4)
pip (9.0.1)
plac (0.9.6)
requests (2.18.4)
setuptools (18.2)
urllib3 (1.22)
wheel (0.24.0)
Hey-lo,
I'm building a version of plac
using conda
for conda-forge. When possible, we try to both include a link to the license file in the meta.yaml
specification for the build and pin down the exact identity of the license.
Two questions for you:
plac
is under the BSD 2-Clause or 3-Clause license?Plac looks great, but I never use it because it takes too long to read through the documentation. When I'm working I really want a quick way to lookup methods and suggested usage. It's great that there's documentation with all the motivations behind plac
, and comparisons to other approaches such as argparse
, but to be useful, I need documentation without all that. Something efficient to use while I'm in the middle of writing code.
I suggest adding 2 pieces of documentation which are separate from the existing documentation.
Quick Start
This would show the top N common uses. For example, these uses cases could be covered:
API Doc
Something in the style of https://docs.python.org/3/library/argparse.html where the doc follows other python documentation in style and organization. It should have:
It would be neat if you could add a gh-pages
branch with plac.html
as index.html
. That way, one could access the docs online via micheles.github.io/plac
.
See here for more info.
The SQLSoup Python module is unmaintained upstream and doesn't work with SQLAlchemy 1.4.23, which Debian has upgraded to, leading to build and CI failures in Debian infrastructure for things that use SQLSoup. The SQLSoup author suggested to switch to the SQLAlchemy automap extension. Since the SQLSoup Python module is only used in plac as an optional test dependency, the Debian package of plac will likely just drop it, but you might want to add support for using the SQLAlchemy automap extension as an alternative to the SQLSoup Python module.
https://bugs.debian.org/995781
https://bugs.debian.org/997325
zzzeek/sqlsoup#1
https://docs.sqlalchemy.org/en/14/orm/extensions/automap.html
When a function has multi-line comments, it is usually the case that it has to end with extra spaces, e.g., to satisfy coding standards. But this results into ugly help string.
$ cat test_plac.py
#!/usr/bin/env python
def func(opt: ('opt',)):
"""This is title
This is content
"""
print(opt)
import plac
plac.call(func)
$ ./test_plac.py -h
usage: test_plac.py [-h] opt
This is title
This is content
positional arguments:
opt opt
optional arguments:
-h, --help show this help message and exit
if an argument data type is not provided explicitly but a default value is:
if default is not a tuple:
argtype = type(default)
elif all(type(val) == type(default[0]) for val in default[1:]):
argtype = type(default[0])
I just have a quick question that the doc doesn't seem to explain.
I have this program taking many options, and sometimes plac generates option flags with two dashes (like epochs
becomes --epochs
), but sometimes for more long winded argument names, it generates flags with a single dash (like train_vgg
becomes -train-vgg
, validation_steps
becomes -validation-steps
).
I'd like to understand why that is the case. Is there a practical reason for this behaviour ?
From my CLI experience, I usually expect long argument names to have two dashes and one letter argument names to have one dash.
As an example, here is the help display for nmap
:
$ nmap --help
SCAN TECHNIQUES:
-sS/sT/sA/sW/sM: TCP SYN/Connect()/ACK/Window/Maimon scans
-sU: UDP Scan
-sN/sF/sX: TCP Null, FIN, and Xmas scans
--scanflags <flags>: Customize TCP scan flags
-sI <zombie host[:probeport]>: Idle scan
-sY/sZ: SCTP INIT/COOKIE-ECHO scans
-sO: IP protocol scan
-b <FTP relay host>: FTP bounce scan
PORT SPECIFICATION AND SCAN ORDER:
-p <port ranges>: Only scan specified ports
Ex: -p22; -p1-65535; -p U:53,111,137,T:21-25,80,139,8080,S:9
--exclude-ports <port ranges>: Exclude the specified ports from scanning
-F: Fast mode - Scan fewer ports than the default scan
-r: Scan ports consecutively - don't randomize
--top-ports <number>: Scan <number> most common ports
--port-ratio <ratio>: Scan ports more common than <ratio>
SERVICE/VERSION DETECTION:
-sV: Probe open ports to determine service/version info
--version-intensity <level>: Set from 0 (light) to 9 (try all probes)
--version-light: Limit to most likely probes (intensity 2)
--version-all: Try every single probe (intensity 9)
--version-trace: Show detailed version scan activity (for debugging)
This strange behaviour of plac makes using the flags unintuitive. Is there a way to force plac to use double dash instead of single dash ?
Is there a reason why one might prefer using single dash with long argument names ?
def main():
plac.Interpreter.(FooContainer)
class FooContainer(object):
[...]
commands=('foo_command',)
@plac.annotate(
foo="The default argument"
)
def __init__(self, foo):
self.foo = foo
then run foo.py and get:
$ ./foo.py -h
usage: foo.py [-i] foo [args [args ...]]
foo.py: error: too few arguments
What is the expected output? What do you see instead?
For a user, it's important to know what the first argument can/should be. the
examples indicate that this can be done by outputting examples as though the
full help messages, including annotations for the constructor of the container,
but in practice I can't get this output.
What version of the product are you using? On what operating system?
0.9 with argparse 1.2.1 on solaris 10.
Original issue reported on code.google.com by [email protected]
on 14 Jul 2011 at 9:01
Please find some corrections to docs and examples:
<http://code.google.com/r/nicolalarosa-plac/source/detail?r=cd156d9657bb60056e47
e202c419a71d118c0b91>.
Thanks for plac!
Original issue reported on code.google.com by [email protected]
on 8 Apr 2013 at 11:21
Assuming a package with multiple CLIs powered by plac, is there a pattern that is recommended to allow "pluggable" subcommands? In other words, there is an entry point for a package for a CLI command powered by plac, would it be possible to have subcommands from that CLI trigger other CLIs in the package (and then hopefully from other plac CLIs)?
mypackage:
- setup.py (entry point for mycli=mypackage/__main__.py:run)
- main/
- __main__.py (plac powered)
- ...
- foo/
- __main__.py (plac powered)
- ...
- bar/
- __main__.py (plac powered)
- ...
All three CLIs could be called independently (mycli
--> main or python -m mypackage.main
, and then python -m mypackage.foo
and python -m mypackage.bar
)
Execution examples:
mycli toplevel_command
mycli foo [args_for_foo]
mycli bar [args_for_foo]
Ref for a native solution: https://stackoverflow.com/questions/54263164/pluggable-python-sub-command-pattern
The problem is that imp.load_module is not looking in the current directory in
the search path. You can see the problem with
$ plac_runner.py doc/ishelve3.py
or
$ plac_runner.py doc/ishelve2.py
not finding ishelve2.py
Original issue reported on code.google.com by [email protected]
on 19 Jun 2011 at 9:37
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.