mirror of
https://github.com/craigerl/aprsd.git
synced 2024-11-21 15:51:52 -05:00
Compare commits
2 Commits
28b54c330d
...
450bacfe99
Author | SHA1 | Date | |
---|---|---|---|
450bacfe99 | |||
cd62db95c1 |
@ -4,6 +4,7 @@ CHANGES
|
|||||||
v2.5.6
|
v2.5.6
|
||||||
------
|
------
|
||||||
|
|
||||||
|
* Changelog
|
||||||
* Tightened up the packet logging
|
* Tightened up the packet logging
|
||||||
* Added unit tests for USWeatherPlugin, USMetarPlugin
|
* Added unit tests for USWeatherPlugin, USMetarPlugin
|
||||||
* Added test\_location to test LocationPlugin
|
* Added test\_location to test LocationPlugin
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import click
|
import click
|
||||||
import click_completion
|
import click_completion
|
||||||
|
|
||||||
from ..aprsd import cli
|
from aprsd.aprsd import cli
|
||||||
|
|
||||||
|
|
||||||
CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
|
CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
|
||||||
|
@ -9,8 +9,7 @@ import click
|
|||||||
|
|
||||||
# local imports here
|
# local imports here
|
||||||
from aprsd import cli_helper, client, messaging, packets, plugin, stats, trace
|
from aprsd import cli_helper, client, messaging, packets, plugin, stats, trace
|
||||||
|
from aprsd.aprsd import cli
|
||||||
from ..aprsd import cli
|
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger("APRSD")
|
LOG = logging.getLogger("APRSD")
|
||||||
|
@ -14,9 +14,8 @@ import requests
|
|||||||
|
|
||||||
import aprsd
|
import aprsd
|
||||||
from aprsd import cli_helper, utils
|
from aprsd import cli_helper, utils
|
||||||
|
|
||||||
# local imports here
|
# local imports here
|
||||||
from ..aprsd import cli
|
from aprsd.aprsd import cli
|
||||||
|
|
||||||
|
|
||||||
# setup the global logger
|
# setup the global logger
|
||||||
|
@ -1,21 +1,183 @@
|
|||||||
|
import fnmatch
|
||||||
|
import importlib
|
||||||
import inspect
|
import inspect
|
||||||
import logging
|
import logging
|
||||||
from textwrap import indent
|
import os
|
||||||
|
import pkgutil
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from traceback import print_tb
|
||||||
|
from urllib.parse import urljoin
|
||||||
|
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
import click
|
import click
|
||||||
from tabulate import tabulate
|
import requests
|
||||||
|
from rich.console import Console
|
||||||
|
from rich.table import Table
|
||||||
|
from rich.text import Text
|
||||||
|
from thesmuggler import smuggle
|
||||||
|
|
||||||
from aprsd import cli_helper, plugin
|
from aprsd import cli_helper
|
||||||
|
from aprsd import plugin as aprsd_plugin
|
||||||
|
from aprsd.aprsd import cli
|
||||||
from aprsd.plugins import (
|
from aprsd.plugins import (
|
||||||
email, fortune, location, notify, ping, query, time, version, weather,
|
email, fortune, location, notify, ping, query, time, version, weather,
|
||||||
)
|
)
|
||||||
|
|
||||||
from ..aprsd import cli
|
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger("APRSD")
|
LOG = logging.getLogger("APRSD")
|
||||||
|
|
||||||
|
|
||||||
|
def onerror(name):
|
||||||
|
print(f"Error importing module {name}")
|
||||||
|
type, value, traceback = sys.exc_info()
|
||||||
|
print_tb(traceback)
|
||||||
|
|
||||||
|
|
||||||
|
def is_plugin(obj):
|
||||||
|
for c in inspect.getmro(obj):
|
||||||
|
if issubclass(c, aprsd_plugin.APRSDPluginBase):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def plugin_type(obj):
|
||||||
|
for c in inspect.getmro(obj):
|
||||||
|
if issubclass(c, aprsd_plugin.APRSDRegexCommandPluginBase):
|
||||||
|
return "RegexCommand"
|
||||||
|
if issubclass(c, aprsd_plugin.APRSDWatchListPluginBase):
|
||||||
|
return "WatchList"
|
||||||
|
if issubclass(c, aprsd_plugin.APRSDPluginBase):
|
||||||
|
return "APRSDPluginBase"
|
||||||
|
|
||||||
|
return "Unknown"
|
||||||
|
|
||||||
|
|
||||||
|
def walk_package(package):
|
||||||
|
return pkgutil.walk_packages(
|
||||||
|
package.__path__,
|
||||||
|
package.__name__ + ".",
|
||||||
|
onerror=onerror,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_module_info(package_name, module_name, module_path):
|
||||||
|
if not os.path.exists(module_path):
|
||||||
|
return None
|
||||||
|
|
||||||
|
dir_path = os.path.realpath(module_path)
|
||||||
|
pattern = "*.py"
|
||||||
|
|
||||||
|
obj_list = []
|
||||||
|
|
||||||
|
for path, _subdirs, files in os.walk(dir_path):
|
||||||
|
for name in files:
|
||||||
|
if fnmatch.fnmatch(name, pattern):
|
||||||
|
module = smuggle(f"{path}/{name}")
|
||||||
|
for mem_name, obj in inspect.getmembers(module):
|
||||||
|
if inspect.isclass(obj) and is_plugin(obj):
|
||||||
|
obj_list.append(
|
||||||
|
{
|
||||||
|
"package": package_name,
|
||||||
|
"name": mem_name, "obj": obj,
|
||||||
|
"version": obj.version,
|
||||||
|
"path": f"{'.'.join([module_name, obj.__name__])}",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return obj_list
|
||||||
|
|
||||||
|
|
||||||
|
def get_installed_plugins():
|
||||||
|
# installed plugins
|
||||||
|
ip = {}
|
||||||
|
for finder, name, ispkg in pkgutil.iter_modules():
|
||||||
|
if name.startswith("aprsd_"):
|
||||||
|
if ispkg:
|
||||||
|
module = importlib.import_module(name)
|
||||||
|
pkgs = walk_package(module)
|
||||||
|
for pkg in pkgs:
|
||||||
|
pkg_info = get_module_info(module.__name__, pkg.name, module.__path__[0])
|
||||||
|
ip[name] = pkg_info
|
||||||
|
return ip
|
||||||
|
|
||||||
|
|
||||||
|
def show_pypi_plugins(installed_plugins, console):
|
||||||
|
query = "aprsd"
|
||||||
|
api_url = "https://pypi.org/search/"
|
||||||
|
snippets = []
|
||||||
|
s = requests.Session()
|
||||||
|
for page in range(1, 3):
|
||||||
|
params = {"q": query, "page": page}
|
||||||
|
r = s.get(api_url, params=params)
|
||||||
|
soup = BeautifulSoup(r.text, "html.parser")
|
||||||
|
snippets += soup.select('a[class*="snippet"]')
|
||||||
|
if not hasattr(s, "start_url"):
|
||||||
|
s.start_url = r.url.rsplit("&page", maxsplit=1).pop(0)
|
||||||
|
|
||||||
|
title = Text.assemble(
|
||||||
|
("Pypi.org APRSD Installable Plugin Packages\n\n", "bold magenta"),
|
||||||
|
("Install any of the following plugins with ", "bold yellow"),
|
||||||
|
("pip install ", "bold white"),
|
||||||
|
("<Plugin Package Name>", "cyan"),
|
||||||
|
)
|
||||||
|
|
||||||
|
table = Table(title=title)
|
||||||
|
table.add_column("Plugin Package Name", style="cyan", no_wrap=True)
|
||||||
|
table.add_column("Description", style="yellow")
|
||||||
|
table.add_column("Version", style="yellow")
|
||||||
|
table.add_column("Released", style="bold green")
|
||||||
|
table.add_column("Installed?", style="red")
|
||||||
|
table.add_column("Version Installed", style="yellow")
|
||||||
|
for snippet in snippets:
|
||||||
|
link = urljoin(api_url, snippet.get("href"))
|
||||||
|
package = re.sub(r"\s+", " ", snippet.select_one('span[class*="name"]').text.strip())
|
||||||
|
version = re.sub(r"\s+", " ", snippet.select_one('span[class*="version"]').text.strip())
|
||||||
|
released = re.sub(r"\s+", " ", snippet.select_one('span[class*="released"]').text.strip())
|
||||||
|
description = re.sub(r"\s+", " ", snippet.select_one('p[class*="description"]').text.strip())
|
||||||
|
emoji = ":open_file_folder:"
|
||||||
|
if "aprsd-" not in package or "-plugin" not in package:
|
||||||
|
continue
|
||||||
|
under = package.replace("-", "_")
|
||||||
|
if under in installed_plugins:
|
||||||
|
installed = "Yes"
|
||||||
|
try:
|
||||||
|
version_installed = installed_plugins[under].__version__
|
||||||
|
except Exception:
|
||||||
|
version_installed = "Unknown"
|
||||||
|
else:
|
||||||
|
installed = "No"
|
||||||
|
version_installed = "Unknown"
|
||||||
|
table.add_row(
|
||||||
|
f"[link={link}]{emoji}[/link] {package}",
|
||||||
|
description, version, released, installed, version_installed,
|
||||||
|
)
|
||||||
|
|
||||||
|
console.print("\n")
|
||||||
|
console.print(table)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def show_installed_plugins(installed_plugins, console):
|
||||||
|
if not installed_plugins:
|
||||||
|
return
|
||||||
|
|
||||||
|
table = Table(
|
||||||
|
title="[not italic]:snake:[/] [bold][magenta]APRSD Installed 3rd party Plugins [not italic]:snake:[/]",
|
||||||
|
)
|
||||||
|
table.add_column("Package Name", style="white", no_wrap=True)
|
||||||
|
table.add_column("Plugin Name", style="cyan", no_wrap=True)
|
||||||
|
table.add_column("Type", style="bold green")
|
||||||
|
table.add_column("Plugin Path", style="bold blue")
|
||||||
|
for name in installed_plugins:
|
||||||
|
for plugin in installed_plugins[name]:
|
||||||
|
table.add_row(name.replace("_", "-"), plugin["name"], plugin_type(plugin["obj"]), plugin["path"])
|
||||||
|
|
||||||
|
console.print("\n")
|
||||||
|
console.print(table)
|
||||||
|
|
||||||
|
|
||||||
@cli.command()
|
@cli.command()
|
||||||
@cli_helper.add_options(cli_helper.common_options)
|
@cli_helper.add_options(cli_helper.common_options)
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
@ -30,7 +192,7 @@ def list_plugins(ctx):
|
|||||||
entries = inspect.getmembers(module, inspect.isclass)
|
entries = inspect.getmembers(module, inspect.isclass)
|
||||||
for entry in entries:
|
for entry in entries:
|
||||||
cls = entry[1]
|
cls = entry[1]
|
||||||
if issubclass(cls, plugin.APRSDPluginBase):
|
if issubclass(cls, aprsd_plugin.APRSDPluginBase):
|
||||||
info = {
|
info = {
|
||||||
"name": cls.__qualname__,
|
"name": cls.__qualname__,
|
||||||
"path": f"{cls.__module__}.{cls.__qualname__}",
|
"path": f"{cls.__module__}.{cls.__qualname__}",
|
||||||
@ -39,21 +201,32 @@ def list_plugins(ctx):
|
|||||||
"short_desc": cls.short_description,
|
"short_desc": cls.short_description,
|
||||||
}
|
}
|
||||||
|
|
||||||
if issubclass(cls, plugin.APRSDRegexCommandPluginBase):
|
if issubclass(cls, aprsd_plugin.APRSDRegexCommandPluginBase):
|
||||||
info["command_regex"] = cls.command_regex
|
info["command_regex"] = cls.command_regex
|
||||||
info["type"] = "RegexCommand"
|
info["type"] = "RegexCommand"
|
||||||
|
|
||||||
if issubclass(cls, plugin.APRSDWatchListPluginBase):
|
if issubclass(cls, aprsd_plugin.APRSDWatchListPluginBase):
|
||||||
info["type"] = "WatchList"
|
info["type"] = "WatchList"
|
||||||
|
|
||||||
plugins.append(info)
|
plugins.append(info)
|
||||||
|
|
||||||
lines = []
|
plugins = sorted(plugins, key=lambda i: i["name"])
|
||||||
headers = ("Plugin Name", "Plugin Path", "Type", "Info")
|
|
||||||
|
|
||||||
|
table = Table(
|
||||||
|
title="[not italic]:snake:[/] [bold][magenta]APRSD Built-in Plugins [not italic]:snake:[/]",
|
||||||
|
)
|
||||||
|
table.add_column("Plugin Name", style="cyan", no_wrap=True)
|
||||||
|
table.add_column("Info", style="bold yellow")
|
||||||
|
table.add_column("Type", style="bold green")
|
||||||
|
table.add_column("Plugin Path", style="bold blue")
|
||||||
for entry in plugins:
|
for entry in plugins:
|
||||||
lines.append(
|
table.add_row(entry["name"], entry["short_desc"], entry["type"], entry["path"])
|
||||||
(entry["name"], entry["path"], entry["type"], entry["short_desc"]),
|
|
||||||
)
|
|
||||||
|
|
||||||
click.echo(indent(tabulate(lines, headers, disable_numparse=True), " "))
|
console = Console()
|
||||||
|
console.print(table)
|
||||||
|
|
||||||
|
# now find any from pypi?
|
||||||
|
installed_plugins = get_installed_plugins()
|
||||||
|
show_pypi_plugins(installed_plugins, console)
|
||||||
|
|
||||||
|
show_installed_plugins(installed_plugins, console)
|
||||||
|
@ -16,8 +16,7 @@ import aprsd
|
|||||||
from aprsd import (
|
from aprsd import (
|
||||||
cli_helper, client, messaging, packets, stats, threads, trace, utils,
|
cli_helper, client, messaging, packets, stats, threads, trace, utils,
|
||||||
)
|
)
|
||||||
|
from aprsd.aprsd import cli
|
||||||
from ..aprsd import cli
|
|
||||||
|
|
||||||
|
|
||||||
# setup the global logger
|
# setup the global logger
|
||||||
|
@ -8,8 +8,7 @@ import click
|
|||||||
|
|
||||||
import aprsd
|
import aprsd
|
||||||
from aprsd import cli_helper, client, messaging, packets
|
from aprsd import cli_helper, client, messaging, packets
|
||||||
|
from aprsd.aprsd import cli
|
||||||
from ..aprsd import cli
|
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger("APRSD")
|
LOG = logging.getLogger("APRSD")
|
||||||
|
@ -10,8 +10,7 @@ from aprsd import (
|
|||||||
trace, utils,
|
trace, utils,
|
||||||
)
|
)
|
||||||
from aprsd import aprsd as aprsd_main
|
from aprsd import aprsd as aprsd_main
|
||||||
|
from aprsd.aprsd import cli
|
||||||
from ..aprsd import cli
|
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger("APRSD")
|
LOG = logging.getLogger("APRSD")
|
||||||
|
@ -22,3 +22,5 @@ flask-socketio
|
|||||||
eventlet
|
eventlet
|
||||||
tabulate
|
tabulate
|
||||||
rich
|
rich
|
||||||
|
# For the list-plugins pypi.org search scraping
|
||||||
|
beautifulsoup4
|
||||||
|
@ -10,6 +10,8 @@ aprslib==0.7.0
|
|||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
backoff==1.11.1
|
backoff==1.11.1
|
||||||
# via opencage
|
# via opencage
|
||||||
|
beautifulsoup4==4.10.0
|
||||||
|
# via -r requirements.in
|
||||||
bidict==0.21.2
|
bidict==0.21.2
|
||||||
# via python-socketio
|
# via python-socketio
|
||||||
certifi==2021.5.30
|
certifi==2021.5.30
|
||||||
@ -112,6 +114,8 @@ six==1.16.0
|
|||||||
# imapclient
|
# imapclient
|
||||||
# pyopenssl
|
# pyopenssl
|
||||||
# signalslot
|
# signalslot
|
||||||
|
soupsieve==2.3.1
|
||||||
|
# via beautifulsoup4
|
||||||
tabulate==0.8.9
|
tabulate==0.8.9
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
thesmuggler==1.0.1
|
thesmuggler==1.0.1
|
||||||
|
Loading…
Reference in New Issue
Block a user