CLI command devel:newplugin now allows specifying most of the parameters of the template
This commit is contained in:
parent
3c2d2b579d
commit
628b9edbab
2 changed files with 86 additions and 5 deletions
|
|
@ -52,6 +52,10 @@ class OctoPrintDevelCommands(click.MultiCommand):
|
|||
|
||||
@contextlib.contextmanager
|
||||
def custom_cookiecutter_config(config):
|
||||
"""
|
||||
Allows overriding cookiecutter's user config with a custom dict
|
||||
with fallback to the original data.
|
||||
"""
|
||||
from octoprint.util import fallback_dict
|
||||
|
||||
original_get_user_config = cookiecutter.main.get_user_config
|
||||
|
|
@ -62,15 +66,92 @@ class OctoPrintDevelCommands(click.MultiCommand):
|
|||
finally:
|
||||
cookiecutter.main.get_user_config = original_get_user_config
|
||||
|
||||
@contextlib.contextmanager
|
||||
def custom_cookiecutter_prompt(options):
|
||||
"""
|
||||
Custom cookiecutter prompter for the template config.
|
||||
|
||||
If a setting is available in the provided options (read from the CLI)
|
||||
that will be used, otherwise the user will be prompted for a value
|
||||
via click.
|
||||
"""
|
||||
original_prompt_for_config = cookiecutter.main.prompt_for_config
|
||||
|
||||
def custom_prompt_for_config(context, no_input=False):
|
||||
import cookiecutter.prompt
|
||||
|
||||
cookiecutter_dict = {}
|
||||
env = cookiecutter.prompt.Environment()
|
||||
|
||||
for key, raw in cookiecutter.prompt.iteritems(context['cookiecutter']):
|
||||
if key in options:
|
||||
val = options[key]
|
||||
else:
|
||||
raw = raw if cookiecutter.prompt.is_string(raw) else str(raw)
|
||||
val = env.from_string(raw).render(cookiecutter=cookiecutter_dict)
|
||||
|
||||
if not no_input:
|
||||
new_val = click.prompt(key, default=val)
|
||||
if new_val != "":
|
||||
val = new_val
|
||||
|
||||
cookiecutter_dict[key] = val
|
||||
return cookiecutter_dict
|
||||
|
||||
try:
|
||||
cookiecutter.main.prompt_for_config = custom_prompt_for_config
|
||||
yield
|
||||
finally:
|
||||
cookiecutter.main.prompt_for_config = original_prompt_for_config
|
||||
|
||||
@click.command("newplugin")
|
||||
def command():
|
||||
@click.option("--name", "-n", help="The name of the plugin")
|
||||
@click.option("--package", "-p", help="The plugin package")
|
||||
@click.option("--author", "-a", help="The plugin author's name")
|
||||
@click.option("--email", "-e", help="The plugin author's mail address")
|
||||
@click.option("--license", "-l", help="The plugin's license")
|
||||
@click.option("--description", "-d", help="The plugin's description")
|
||||
@click.option("--homepage", help="The plugin's homepage URL")
|
||||
@click.option("--source", "-s", help="The URL to the plugin's source")
|
||||
@click.option("--installurl", "-i", help="The plugin's install URL")
|
||||
@click.argument("identifier", required=False)
|
||||
def command(name, package, author, email, description, license, homepage, source, installurl, identifier):
|
||||
"""Creates a new plugin based on the OctoPrint Plugin cookiecutter template."""
|
||||
from octoprint.util import tempdir
|
||||
|
||||
with tempdir() as path:
|
||||
# deleting a git checkout folder might run into access errors due
|
||||
# to write-protected sub folders, so we use a custom onerror handler
|
||||
# that tries to fix such permissions
|
||||
def onerror(func, path, exc_info):
|
||||
"""Originally from http://stackoverflow.com/a/2656405/2028598"""
|
||||
import stat
|
||||
import os
|
||||
|
||||
if not os.access(path, os.W_OK):
|
||||
os.chmod(path, stat.S_IWUSR)
|
||||
func(path)
|
||||
else:
|
||||
raise
|
||||
|
||||
with tempdir(onerror=onerror) as path:
|
||||
custom = dict(cookiecutters_dir=path)
|
||||
with custom_cookiecutter_config(custom):
|
||||
cookiecutter.main.cookiecutter("gh:OctoPrint/cookiecutter-octoprint-plugin")
|
||||
raw_options = dict(
|
||||
plugin_identifier=identifier,
|
||||
plugin_package=package,
|
||||
plugin_name=name,
|
||||
full_name=author,
|
||||
email=email,
|
||||
plugin_description=description,
|
||||
plugin_license=license,
|
||||
plugin_homepage=homepage,
|
||||
plugin_source=source,
|
||||
plugin_installurl=installurl
|
||||
)
|
||||
options = dict((k, v) for k, v in raw_options.items() if v is not None)
|
||||
|
||||
with custom_cookiecutter_prompt(options):
|
||||
cookiecutter.main.cookiecutter("gh:OctoPrint/cookiecutter-octoprint-plugin")
|
||||
|
||||
return command
|
||||
|
||||
|
|
|
|||
|
|
@ -625,7 +625,7 @@ def atomic_write(filename, mode="w+b", prefix="tmp", suffix=""):
|
|||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def tempdir(**kwargs):
|
||||
def tempdir(ignore_errors=False, onerror=None, **kwargs):
|
||||
import tempfile
|
||||
import shutil
|
||||
|
||||
|
|
@ -633,7 +633,7 @@ def tempdir(**kwargs):
|
|||
try:
|
||||
yield dirpath
|
||||
finally:
|
||||
shutil.rmtree(dirpath)
|
||||
shutil.rmtree(dirpath, ignore_errors=ignore_errors, onerror=onerror)
|
||||
|
||||
|
||||
def bom_aware_open(filename, encoding="ascii", mode="r", **kwargs):
|
||||
|
|
|
|||
Loading…
Reference in a new issue