Implement building plugins

This commit is contained in:
Tulir Asokan 2018-12-13 19:47:41 +02:00
parent 54e117c9e7
commit c334afd38b
2 changed files with 85 additions and 3 deletions

View file

@ -13,19 +13,101 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from typing import Optional
from io import BytesIO
import zipfile
import os
from mautrix.client.api.types.util import SerializerError
from ruamel.yaml import YAML, YAMLError
from colorama import Fore, Style
from PyInquirer import prompt
import click
from ...loader import PluginMeta
from ..base import app
from ..cliq.validators import PathValidator
yaml = YAML()
def zipdir(zip, dir):
for root, dirs, files in os.walk(dir):
for file in files:
zip.write(os.path.join(root, file))
def read_meta(path: str) -> Optional[PluginMeta]:
try:
with open(os.path.join(path, "maubot.yaml")) as meta_file:
try:
meta_dict = yaml.load(meta_file)
except YAMLError as e:
print(Fore.RED + "Failed to build plugin: Metadata file is not YAML")
print(Fore.RED + str(e) + Style.RESET_ALL)
return None
except FileNotFoundError:
print(Fore.RED + "Failed to build plugin: Metadata file not found" + Style.RESET_ALL)
return None
try:
meta = PluginMeta.deserialize(meta_dict)
except SerializerError as e:
print(Fore.RED + "Failed to build plugin: Metadata file is not valid")
print(Fore.RED + str(e) + Style.RESET_ALL)
return None
return meta
def read_output_path(output: str, meta: PluginMeta) -> Optional[str]:
directory = os.getcwd()
filename = f"{meta.id}-v{meta.version}.mbp"
if not output:
output = os.path.join(directory, filename)
elif os.path.isdir(output):
output = os.path.join(output, filename)
elif os.path.exists(output):
override = prompt({
"type": "confirm",
"name": "override",
"message": f"{output} exists, override?"
})["override"]
if not override:
return None
os.remove(output)
return os.path.abspath(output)
def write_plugin(meta: PluginMeta, output: str) -> None:
with zipfile.ZipFile(output, "w") as zip:
meta_dump = BytesIO()
yaml.dump(meta.serialize(), meta_dump)
zip.writestr("maubot.yaml", meta_dump.getvalue())
for module in meta.modules:
if os.path.isfile(f"{module}.py"):
zip.write(f"{module}.py")
elif os.path.isdir(module):
zipdir(zip, module)
else:
print(Fore.YELLOW + f"Module {module} not found, skipping")
for file in meta.extra_files:
zip.write(file)
@app.command(short_help="Build a maubot plugin",
help="Build a maubot plugin. First parameter is the path to root of the plugin "
"to build. You can also use --output to specify output file.")
@click.argument("path", default=".")
@click.argument("path", default=os.getcwd())
@click.option("-o", "--output", help="Path to output built plugin to",
type=PathValidator.click_type)
@click.option("-u", "--upload", help="Upload plugin to main server after building", is_flag=True,
default=False)
def build(path: str, output: str, upload: bool) -> None:
pass
meta = read_meta(path)
output = read_output_path(output, meta)
if not output:
return
os.chdir(path)
write_plugin(meta, output)
print(Fore.GREEN + "Plugin build complete.")

View file

@ -1,2 +1,2 @@
from .abc import PluginLoader, PluginClass, IDConflictError
from .abc import PluginLoader, PluginClass, IDConflictError, PluginMeta
from .zip import ZippedPluginLoader, MaubotZipImportError