File: plugin_wizard.py

package info (click to toggle)
errbot 6.1.7+ds-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, sid
  • size: 3,712 kB
  • sloc: python: 13,831; makefile: 164; sh: 97
file content (153 lines) | stat: -rw-r--r-- 4,848 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/usr/bin/env python

import errno
import os
import re
import sys
from configparser import ConfigParser

import jinja2

from errbot.version import VERSION


def new_plugin_wizard(directory=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? "
        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? "
        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)."
    )


def ask(question, valid_responses=None, validation_regex=None):
    """
    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


def render_plugin(values):
    """
    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)