Source code for errbot.plugin_wizard
import errno
import os
import re
import sys
from configparser import ConfigParser
from typing import List, Optional
import jinja2
from errbot.version import VERSION
[docs]
def new_plugin_wizard(directory: Optional[str] = None) -> None:
"""
Start the wizard to create a new plugin in the current working directory.
"""
if directory is None:
print("This wizard will create a new plugin for you in the current directory.")
directory = os.getcwd()
else:
print(f"This wizard will create a new plugin for you in '{directory}'.")
if os.path.exists(directory) and not os.path.isdir(directory):
print(f"Error: The path '{directory}' exists but it isn't a directory")
sys.exit(1)
name = ask(
"What should the name of your new plugin be?",
validation_regex=r"^[a-zA-Z][a-zA-Z0-9 _-]*$",
).strip()
module_name = name.lower().replace(" ", "_")
directory_name = name.lower().replace(" ", "-")
class_name = "".join([s.capitalize() for s in name.lower().split(" ")])
description = ask(
"What may I use as a short (one-line) description of your plugin?"
)
python_version = "3"
errbot_min_version = ask(
f"Which minimum version of errbot will your plugin work with?\n"
f"Leave blank to support any version or input CURRENT to select "
f"the current version {VERSION}."
).strip()
if errbot_min_version.upper() == "CURRENT":
errbot_min_version = VERSION
errbot_max_version = ask(
f"Which maximum version of errbot will your plugin work with?\n"
f"Leave blank to support any version or input CURRENT to select "
f"the current version {VERSION}."
).strip()
if errbot_max_version.upper() == "CURRENT":
errbot_max_version = VERSION
plug = ConfigParser()
plug["Core"] = {
"Name": name,
"Module": module_name,
}
plug["Documentation"] = {
"Description": description,
}
plug["Python"] = {
"Version": python_version,
}
if errbot_max_version != "" or errbot_min_version != "":
plug["Errbot"] = {}
if errbot_min_version != "":
plug["Errbot"]["Min"] = errbot_min_version
if errbot_max_version != "":
plug["Errbot"]["Max"] = errbot_max_version
plugin_path = directory
plugfile_path = os.path.join(plugin_path, module_name + ".plug")
pyfile_path = os.path.join(plugin_path, module_name + ".py")
try:
os.makedirs(plugin_path, mode=0o700)
except IOError as e:
if e.errno != errno.EEXIST:
raise
if os.path.exists(plugfile_path) or os.path.exists(pyfile_path):
path = os.path.join(directory, f"{module_name}.{{py,plug}}")
ask(
f"Warning: A plugin with this name was already found at {path}\n"
f"If you continue, these will be overwritten.\n"
f"Press Ctrl+C to abort now or type in 'overwrite' to confirm overwriting of these files.",
valid_responses=["overwrite"],
)
with open(plugfile_path, "w") as f:
plug.write(f)
with open(pyfile_path, "w") as f:
f.write(render_plugin(locals()))
print(f"Success! You'll find your new plugin at '{plugfile_path}'")
print(
"(Don't forget to include a LICENSE file if you are going to publish your plugin)."
)
[docs]
def ask(
question: str,
valid_responses: Optional[List[str]] = None,
validation_regex: Optional[str] = None,
) -> Optional[str]:
"""
Ask the user for some input. If valid_responses is supplied, the user
must respond with something present in this list.
"""
response = None
print(question)
while True:
response = input("> ")
if valid_responses is not None:
assert isinstance(valid_responses, list)
if response in valid_responses:
break
else:
print(f"Bad input: Please answer one of: {', '.join(valid_responses)}")
elif validation_regex is not None:
m = re.search(validation_regex, response)
if m is None:
print(
f"Bad input: Please respond with something matching this regex: {validation_regex}"
)
else:
break
else:
break
return response
[docs]
def render_plugin(values) -> jinja2.Template:
"""
Render the Jinja template for the plugin with the given values.
"""
env = jinja2.Environment(
loader=jinja2.FileSystemLoader(
os.path.join(os.path.dirname(__file__), "templates")
),
auto_reload=False,
keep_trailing_newline=True,
autoescape=True,
)
template = env.get_template("new_plugin.py.tmpl")
return template.render(**values)
if __name__ == "__main__":
try:
new_plugin_wizard()
except KeyboardInterrupt:
sys.exit(1)