documentation and completion for plugins
This commit is contained in:
+5
-2
@@ -76,6 +76,7 @@ options:
|
||||
conn pc@office
|
||||
conn server
|
||||
```
|
||||
## Plugin Requirements for Connpy
|
||||
### General Structure
|
||||
- The plugin script must be a Python file.
|
||||
- Only the following top-level elements are allowed in the plugin script:
|
||||
@@ -312,13 +313,15 @@ from .configfile import configfile
|
||||
from .connapp import connapp
|
||||
from .api import *
|
||||
from .ai import ai
|
||||
from .plugins import Plugins
|
||||
from ._version import __version__
|
||||
from pkg_resources import get_distribution
|
||||
|
||||
__all__ = ["node", "nodes", "configfile", "connapp", "ai"]
|
||||
__all__ = ["node", "nodes", "configfile", "connapp", "ai", "Plugins"]
|
||||
__author__ = "Federico Luzzi"
|
||||
__pdoc__ = {
|
||||
'core': False,
|
||||
'completion': False,
|
||||
'api': False
|
||||
'api': False,
|
||||
'plugins': False
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
__version__ = "3.8.0b2"
|
||||
__version__ = "3.8.0b3"
|
||||
|
||||
|
||||
+55
-2
@@ -2,6 +2,7 @@ import sys
|
||||
import os
|
||||
import json
|
||||
import glob
|
||||
import importlib.util
|
||||
|
||||
def _getallnodes(config):
|
||||
#get all nodes on configfile
|
||||
@@ -47,15 +48,49 @@ def _getcwd(words, option, folderonly=False):
|
||||
pathstrings = [s for s in pathstrings if os.path.isdir(s)]
|
||||
return pathstrings
|
||||
|
||||
def _get_plugins(which, defaultdir):
|
||||
enabled_files = []
|
||||
disabled_files = []
|
||||
all_files = []
|
||||
all_plugins = {}
|
||||
# Iterate over all files in the specified folder
|
||||
for file in os.listdir(defaultdir + "/plugins"):
|
||||
# Check if the file is a Python file
|
||||
if file.endswith('.py'):
|
||||
enabled_files.append(os.path.splitext(file)[0])
|
||||
all_plugins[os.path.splitext(file)[0]] = os.path.join(defaultdir + "/plugins", file)
|
||||
# Check if the file is a Python backup file
|
||||
elif file.endswith('.py.bkp'):
|
||||
disabled_files.append(os.path.splitext(os.path.splitext(file)[0])[0])
|
||||
|
||||
if which == "--disable":
|
||||
return enabled_files
|
||||
elif which == "--enable":
|
||||
return disabled_files
|
||||
elif which == "--del":
|
||||
all_files.extend(enabled_files)
|
||||
all_files.extend(disabled_files)
|
||||
return all_files
|
||||
elif which == "all":
|
||||
return all_plugins
|
||||
|
||||
|
||||
def main():
|
||||
home = os.path.expanduser("~")
|
||||
defaultdir = home + '/.config/conn'
|
||||
defaultfile = defaultdir + '/config.json'
|
||||
pathfile = defaultdir + '/.folder'
|
||||
try:
|
||||
with open(pathfile, "r") as f:
|
||||
configdir = f.read().strip()
|
||||
except:
|
||||
configdir = defaultdir
|
||||
defaultfile = configdir + '/config.json'
|
||||
jsonconf = open(defaultfile)
|
||||
config = json.load(jsonconf)
|
||||
nodes = _getallnodes(config)
|
||||
folders = _getallfolders(config)
|
||||
profiles = list(config["profiles"].keys())
|
||||
plugins = _get_plugins("all", defaultdir)
|
||||
app = sys.argv[1]
|
||||
if app in ["bash", "zsh"]:
|
||||
positions = [2,4]
|
||||
@@ -64,10 +99,21 @@ def main():
|
||||
wordsnumber = int(sys.argv[positions[0]])
|
||||
words = sys.argv[positions[1]:]
|
||||
if wordsnumber == 2:
|
||||
strings=["--add", "--del", "--rm", "--edit", "--mod", "--show", "mv", "move", "ls", "list", "cp", "copy", "profile", "run", "bulk", "config", "api", "ai", "export", "import", "--help"]
|
||||
strings=["--add", "--del", "--rm", "--edit", "--mod", "--show", "mv", "move", "ls", "list", "cp", "copy", "profile", "run", "bulk", "config", "api", "ai", "export", "import", "--help", "plugin"]
|
||||
if plugins:
|
||||
strings.extend(plugins.keys())
|
||||
strings.extend(nodes)
|
||||
strings.extend(folders)
|
||||
|
||||
elif wordsnumber >=3 and words[0] in plugins.keys():
|
||||
try:
|
||||
spec = importlib.util.spec_from_file_location("module.name", plugins[words[0]])
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
plugin_completion = getattr(module, "_connpy_completion")
|
||||
strings = plugin_completion(wordsnumber, words)
|
||||
except:
|
||||
exit()
|
||||
elif wordsnumber >= 3 and words[0] == "ai":
|
||||
if wordsnumber == 3:
|
||||
strings = ["--help", "--org", "--model", "--api_key"]
|
||||
@@ -91,6 +137,8 @@ def main():
|
||||
strings.extend(folders)
|
||||
if words[0] in ["--rm", "--del", "-r", "--mod", "--edit", "-e", "--show", "-s", "mv", "move", "cp", "copy"]:
|
||||
strings.extend(nodes)
|
||||
if words[0] == "plugin":
|
||||
strings = ["--help", "--add", "--del", "--enable", "--disable"]
|
||||
if words[0] in ["run", "import", "export"]:
|
||||
strings = ["--help"]
|
||||
if words[0] == "export":
|
||||
@@ -120,6 +168,11 @@ def main():
|
||||
strings=["true", "false"]
|
||||
if words[0] == "config" and words[1] in ["--configfolder"]:
|
||||
strings=_getcwd(words,words[0],True)
|
||||
if words[0] == "plugin" and words[1] in ["--del", "--enable", "--disable"]:
|
||||
strings=_get_plugins(words[1], defaultdir)
|
||||
|
||||
elif wordsnumber == 5 and words[0] == "plugin" and words[1] == "--add":
|
||||
strings=_getcwd(words, words[0])
|
||||
else:
|
||||
exit()
|
||||
|
||||
|
||||
+1
-1
@@ -160,7 +160,7 @@ class connapp:
|
||||
#Add plugins
|
||||
file_path = self.config.defaultdir + "/plugins"
|
||||
self.plugins = Plugins()
|
||||
self.plugins.import_plugins_to_argparse(file_path, subparsers)
|
||||
self.plugins._import_plugins_to_argparse(file_path, subparsers)
|
||||
#Generate helps
|
||||
nodeparser.usage = self._help("usage", subparsers)
|
||||
nodeparser.epilog = self._help("end", subparsers)
|
||||
|
||||
+33
-3
@@ -11,6 +11,36 @@ class Plugins:
|
||||
self.plugin_parsers = {}
|
||||
|
||||
def verify_script(self, file_path):
|
||||
"""
|
||||
Verifies that a given Python script meets specific structural requirements.
|
||||
|
||||
This function checks a Python script for compliance with predefined structural
|
||||
rules. It ensures that the script contains only allowed top-level elements
|
||||
(functions, classes, imports, pass statements, and a specific if __name__ block)
|
||||
and that it includes mandatory classes with specific attributes and methods.
|
||||
|
||||
### Arguments:
|
||||
- file_path (str): The file path of the Python script to be verified.
|
||||
|
||||
### Returns:
|
||||
- str: A message indicating the type of violation if the script doesn't meet
|
||||
the requirements, or False if all requirements are met.
|
||||
|
||||
### Verifications:
|
||||
- The presence of only allowed top-level elements.
|
||||
- The existence of two specific classes: 'Parser' and 'Entrypoint'.
|
||||
- 'Parser' class must only have an '__init__' method and must assign 'self.parser'
|
||||
and 'self.description'.
|
||||
- 'Entrypoint' class must have an '__init__' method accepting specific arguments.
|
||||
|
||||
If any of these checks fail, the function returns an error message indicating
|
||||
the reason. If the script passes all checks, the function returns False,
|
||||
indicating successful verification.
|
||||
|
||||
### Exceptions:
|
||||
- SyntaxError: If the script contains a syntax error, it is caught and
|
||||
returned as a part of the error message.
|
||||
"""
|
||||
with open(file_path, 'r') as file:
|
||||
source_code = file.read()
|
||||
|
||||
@@ -60,14 +90,14 @@ class Plugins:
|
||||
else:
|
||||
return "Classes Entrypoint and Parser are mandatory"
|
||||
|
||||
def import_from_path(self, path):
|
||||
def _import_from_path(self, path):
|
||||
spec = importlib.util.spec_from_file_location("module.name", path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules["module.name"] = module
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
|
||||
def import_plugins_to_argparse(self, directory, subparsers):
|
||||
def _import_plugins_to_argparse(self, directory, subparsers):
|
||||
for filename in os.listdir(directory):
|
||||
commands = subparsers.choices.keys()
|
||||
if filename.endswith(".py"):
|
||||
@@ -80,7 +110,7 @@ class Plugins:
|
||||
if check_file:
|
||||
continue
|
||||
else:
|
||||
self.plugins[root_filename] = self.import_from_path(filepath)
|
||||
self.plugins[root_filename] = self._import_from_path(filepath)
|
||||
self.plugin_parsers[root_filename] = self.plugins[root_filename].Parser()
|
||||
subparsers.add_parser(root_filename, parents=[self.plugin_parsers[root_filename].parser], add_help=False, description=self.plugin_parsers[root_filename].description)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user